Allow compilation with threads off.

This commit is contained in:
Alberto Torres 2024-09-13 02:15:32 +02:00
parent c77187fa9f
commit 5b588fddf1
4 changed files with 108 additions and 95 deletions

View file

@ -75,15 +75,16 @@ proc newLoadableResource*[T: LoadableResource](
result.str = proc(): string = "" result.str = proc(): string = ""
result.use_threads = use_threads result.use_threads = use_threads
# main -> thread channels when compileOption("threads"):
var to_start: Channel[LoadableResource] # main -> thread channels
# main <- thread channels var to_start: Channel[LoadableResource]
var to_return: Channel[(LoadableResource, bool, string, SliceMem[byte])] # main <- thread channels
var to_return: Channel[(LoadableResource, bool, string, SliceMem[byte])]
proc start*[T: LoadableResource](self: T) = proc start*[T: LoadableResource](self: T) =
self.status = Started self.status = Started
if self.use_threads: if self.use_threads:
to_start.send self when compileOption("threads"): to_start.send self
else: else:
self.start_func(self) self.start_func(self)
@ -97,7 +98,8 @@ proc onload*[T: LoadableResource](self: T, ok: bool, err: string, data = SliceMe
# self.result[] = (ok, err, data) # self.result[] = (ok, err, data)
if self.onload_func != nil: if self.onload_func != nil:
if self.use_threads: if self.use_threads:
to_return.send((self.LoadableResource, ok, err, data)) when compileOption("threads"):
to_return.send((self.LoadableResource, ok, err, data))
else: else:
self.onload_func(ok, err, data) self.onload_func(ok, err, data)
@ -124,30 +126,31 @@ proc cancel*[T: LoadableResource](self: T) =
# results.add res.result[] # results.add res.result[]
# res.result = nil # res.result = nil
var worker: Thread[void] when compileOption("threads"):
proc workerThreadProc() {.thread.} = var worker: Thread[void]
while true: proc workerThreadProc() {.thread.} =
let res = to_start.recv() while true:
if res == nil: let res = to_start.recv()
break if res == nil:
cast[proc(self: LoadableResource) {.gcsafe.}](res.start_func)(res) break
cast[proc(self: LoadableResource) {.gcsafe.}](res.start_func)(res)
worker.createThread(workerThreadProc) worker.createThread(workerThreadProc)
to_start.open() to_start.open()
to_return.open() to_return.open()
proc updateLoadableWorkerThreads*() = proc updateLoadableWorkerThreads*() =
while true: while true:
let tried = to_return.tryRecv() let tried = to_return.tryRecv()
if not tried.dataAvailable: if not tried.dataAvailable:
break break
let (res, ok, err, data) = tried.msg let (res, ok, err, data) = tried.msg
res.onload_func(ok, err, data) res.onload_func(ok, err, data)
proc terminateLoadableWorkerThreads*() = proc terminateLoadableWorkerThreads*() =
# TODO: test this # TODO: test this
to_start.send(nil.LoadableResource) to_start.send(nil.LoadableResource)
worker.joinThread() worker.joinThread()
type Fetch* = ref object of LoadableResource type Fetch* = ref object of LoadableResource
custom: pointer custom: pointer
@ -246,7 +249,10 @@ proc loadUri*(
var start_func: proc(self: LoadableResource) var start_func: proc(self: LoadableResource)
var self: Fetch var self: Fetch
var uri = uri var uri = uri
var use_threads = use_threads when compileOption("threads"):
var use_threads = use_threads
else:
var use_threads = false
when not defined(onlyLocalFiles): when not defined(onlyLocalFiles):
when defined(emscripten): when defined(emscripten):
const is_remote = true const is_remote = true

View file

@ -367,32 +367,33 @@ proc loadOptimized*(tex: Texture, slices: seq[SliceMem[byte]],
, flip = flip, min_channels = min_channels) , flip = flip, min_channels = min_channels)
# main -> thread channels when compileOption("threads"):
type DecodeChanMsg = tuple[ # main -> thread channels
tex: Texture, slices: seq[SliceMem[byte]], type DecodeChanMsg = tuple[
callback_uncompressed: CallbackUncompressed, tex: Texture, slices: seq[SliceMem[byte]],
callback_compressed: CallbackCompressed, callback_uncompressed: CallbackUncompressed,
flip: bool, min_channels: int, callback_compressed: CallbackCompressed,
] flip: bool, min_channels: int,
var decode_chan: Channel[DecodeChanMsg] ]
# main <- thread channels var decode_chan: Channel[DecodeChanMsg]
type DecodeReturnChanMsg = tuple[ # main <- thread channels
callback: CallbackUncompressed, type DecodeReturnChanMsg = tuple[
tex: Texture, data: SliceMem[byte], callback: CallbackUncompressed,
] tex: Texture, data: SliceMem[byte],
var decode_return_chan: Channel[DecodeReturnChanMsg] ]
type CompressedReturnChanMsg = tuple[ var decode_return_chan: Channel[DecodeReturnChanMsg]
callback: CallbackCompressed, type CompressedReturnChanMsg = tuple[
tex: Texture, data: KtxInfoParts, refdata: seq[SliceMem[byte]], callback: CallbackCompressed,
] tex: Texture, data: KtxInfoParts, refdata: seq[SliceMem[byte]],
var compressed_return_chan: Channel[CompressedReturnChanMsg] ]
var compressed_return_chan: Channel[CompressedReturnChanMsg]
proc loadOptimizedThreaded*(tex: Texture, slices: seq[SliceMem[byte]], proc loadOptimizedThreaded*(tex: Texture, slices: seq[SliceMem[byte]],
callback_uncompressed: CallbackUncompressed = nil, callback_uncompressed: CallbackUncompressed = nil,
callback_compressed: CallbackCompressed = nil, callback_compressed: CallbackCompressed = nil,
flip = true, min_channels = 0) = flip = true, min_channels = 0) =
when false: when not compileOption("threads"):
loadOptimized(tex, slices, callback_uncompressed, callback_compressed, flip, min_channels) loadOptimized(tex, slices, callback_uncompressed, callback_compressed, flip, min_channels)
else: else:
decode_chan.send((tex: tex, slices: slices, decode_chan.send((tex: tex, slices: slices,
@ -400,45 +401,46 @@ proc loadOptimizedThreaded*(tex: Texture, slices: seq[SliceMem[byte]],
callback_compressed: callback_compressed, callback_compressed: callback_compressed,
flip: flip, min_channels: min_channels)) flip: flip, min_channels: min_channels))
var workers = newSeq[Thread[void]](myouEngineNumTextureThreads) when compileOption("threads"):
proc workerThreadProc() {.thread.} = var workers = newSeq[Thread[void]](myouEngineNumTextureThreads)
# TODO: handle errors proc workerThreadProc() {.thread.} =
while true: # TODO: handle errors
let to_decode = decode_chan.recv() while true:
if to_decode.tex == nil: let to_decode = decode_chan.recv()
break if to_decode.tex == nil:
proc cb(tex: Texture, data: SliceMem[byte]) = break
decode_return_chan.send((callback: to_decode.callback_uncompressed, tex: tex, data: data)) proc cb(tex: Texture, data: SliceMem[byte]) =
proc cbc(tex: Texture, data: KtxInfoParts, refdata: seq[SliceMem[byte]]) = decode_return_chan.send((callback: to_decode.callback_uncompressed, tex: tex, data: data))
compressed_return_chan.send((callback: to_decode.callback_compressed, tex: tex, data: data, refdata: refdata)) proc cbc(tex: Texture, data: KtxInfoParts, refdata: seq[SliceMem[byte]]) =
let cb_out = if to_decode.callback_uncompressed != nil: cb else: nil compressed_return_chan.send((callback: to_decode.callback_compressed, tex: tex, data: data, refdata: refdata))
let cbc_out = if to_decode.callback_compressed != nil: cbc else: nil let cb_out = if to_decode.callback_uncompressed != nil: cb else: nil
loadOptimized(to_decode.tex, to_decode.slices, cb_out, cbc_out, let cbc_out = if to_decode.callback_compressed != nil: cbc else: nil
to_decode.flip, to_decode.min_channels) loadOptimized(to_decode.tex, to_decode.slices, cb_out, cbc_out,
to_decode.flip, to_decode.min_channels)
decode_chan.open() decode_chan.open()
decode_return_chan.open() decode_return_chan.open()
compressed_return_chan.open() compressed_return_chan.open()
for worker in workers.mitems: for worker in workers.mitems:
worker.createThread(workerThreadProc) worker.createThread(workerThreadProc)
proc updateTextureWorkerThreads*() = proc updateTextureWorkerThreads*() =
# TODO: handle errors # TODO: handle errors
while true: while true:
let tried = decode_return_chan.tryRecv() let tried = decode_return_chan.tryRecv()
if not tried.dataAvailable: if not tried.dataAvailable:
break break
let (cb, tex, data) = tried.msg let (cb, tex, data) = tried.msg
cb(tex, data) cb(tex, data)
while true: while true:
let tried = compressed_return_chan.tryRecv() let tried = compressed_return_chan.tryRecv()
if not tried.dataAvailable: if not tried.dataAvailable:
break break
let (cb, tex, data, refdata) = tried.msg let (cb, tex, data, refdata) = tried.msg
cb(tex, data, refdata) cb(tex, data, refdata)
proc terminateTextureWorkerThreads*() = proc terminateTextureWorkerThreads*() =
for worker in workers: for worker in workers:
decode_chan.send(DecodeChanMsg.default) decode_chan.send(DecodeChanMsg.default)
for worker in workers: for worker in workers:
worker.joinThread() worker.joinThread()

View file

@ -77,8 +77,9 @@ import ./screen
import ./platform/platform import ./platform/platform
import ./loaders/blend import ./loaders/blend
import ./util import ./util
from loadable import updateLoadableWorkerThreads when compileOption("threads"):
from ./gpu_formats/texture_optimize import updateTextureWorkerThreads from loadable import updateLoadableWorkerThreads
from ./gpu_formats/texture_optimize import updateTextureWorkerThreads
import arr_ref import arr_ref
export arr_ref export arr_ref
@ -167,8 +168,10 @@ proc myou_main_loop*(self: MyouEngine) =
## ##
## You usually don't need to call this. Use `run <#run,MyouEngine>`_ ## You usually don't need to call this. Use `run <#run,MyouEngine>`_
## instead. ## instead.
updateTextureWorkerThreads() self.renderer.unbind_all_ubos()
updateLoadableWorkerThreads() when compileOption("threads"):
updateTextureWorkerThreads()
updateLoadableWorkerThreads()
# TODO: make a table object that can be iterated while changing, e.g. with a # TODO: make a table object that can be iterated while changing, e.g. with a
# seq and a dirty flag to update the seq # seq and a dirty flag to update the seq
if self.new_scenes.len != 0: if self.new_scenes.len != 0:

View file

@ -46,8 +46,9 @@ import ../screen
import ../util import ../util
import ../graphics/render import ../graphics/render
import ../input import ../input
from loadable import terminateLoadableWorkerThreads when compileOption("threads"):
from ../gpu_formats/texture_optimize import terminateTextureWorkerThreads from loadable import terminateLoadableWorkerThreads
from ../gpu_formats/texture_optimize import terminateTextureWorkerThreads
proc screen*(window: Window): Screen {.inline.} = proc screen*(window: Window): Screen {.inline.} =
cast[Screen](window.getWindowUserPointer) cast[Screen](window.getWindowUserPointer)
@ -234,8 +235,9 @@ proc start_platform_main_loop*(engine: MyouEngine, main_loop: proc(self: MyouEng
for i in 0 ..< window.screen.frame_interval: for i in 0 ..< window.screen.frame_interval:
window.swapBuffers() window.swapBuffers()
glfw.pollEvents() glfw.pollEvents()
terminateLoadableWorkerThreads() when compileOption("threads"):
terminateTextureWorkerThreads() terminateLoadableWorkerThreads()
terminateTextureWorkerThreads()
glfw.terminate() glfw.terminate()
proc myouAndroidGetActivity*(): pointer = proc myouAndroidGetActivity*(): pointer =