floooh / sokol

minimal cross-platform standalone C headers
https://floooh.github.io/sokol-html5
zlib License
6.94k stars 488 forks source link

sokol_gfx.h: d3d11 dynamic texture array #322

Open lithiumtoast opened 4 years ago

lithiumtoast commented 4 years ago

With d3d11, when creating an image using SG_IMAGETYPE_ARRAY, SG_USAGE_DYNAMIC, and layers/depth >1, the image fails to be created. However, it works with other backends like OpenGL and Metal.

When building and using the debug build which uses D3D11_CREATE_DEVICE_DEBUG flag, the following is printed: D3D11 ERROR: ID3D11Device::CreateTexture2D: A D3D11_USAGE_DYNAMIC Resource must have ArraySize equal to 1. [ STATE_CREATION ERROR #101: CREATETEXTURE2D_INVALIDDIMENSIONS]

What are your thoughts on this? Is there a work-around I'm not aware of?

Btw, the texture array sample works because it is using SG_USAGE_IMMUTABLE (the default); changing it to SG_USAGE_DYNAMIC re-produces the problem.

floooh commented 4 years ago

Hmm, from googling around that seems to be indeed a D3D11 limitation, I wasn't aware of that yet. The recommended workaround (when using D3D11 directly) seems to be to create a second identical staging texture (D3D11_USAGE_STAGING, which is CPU mappable), update this with the CPU, and then copy the staging texture into the actual texture with D3D11DeviceContext::CopyResource(), this procedure needs to be implemented by sokol-gfx though.

Another workaround is to use "resource injection", where you create and maintain the D3D11 texture yourself, and "inject" the array texture to be used for rendering like in the inject_d3d11.c demo:

https://github.com/floooh/sokol-samples/blob/48660ba8dae8b7732db33cf627324238447cd6fe/d3d11/inject-d3d11.c#L127-L159

I'll use this ticket as reminder though to implement the workaround described above in sokol-gfx though.

PS: this resource injection stuff might also be useful for your other ticket if you need more control than what sokol-gfx currently allows: https://github.com/floooh/sokol/issues/323