Closed leiradel closed 6 months ago
Oh, I think I should say that I tried many different combinations of values in pixel_format
for both the color attachment and the depth buffer, after looking at the sokol examples. Unfortunately, nothing worked.
I think these are several issues. The first one I need to investigate (e.g. why does creating a rendering target with pixel format sgdesc.context.depth_format
fail, which is most likely SG_PIXELFORMAT_DEPTH_STENCIL, this is definitely weird.
The second problem regarding VALIDATE_ABND_FS_IMAGE_MSAA
was a breaking change from May 2023:
https://github.com/floooh/sokol/blob/master/CHANGELOG.md#19-may-2023
(an MSAA render target now needs to be explicitly resolved into a non-MSAA render target, and this resolved image needs to be used as texture).
As for the first error, can you check these two things:
if (sg_query_pixelformat(SG_PIXELFORMAT_DEPTH_STENCIL).render) {
printf("depth stencil is renderable\n");
} else {
printf("depth stencil is not renderable!\n");
}
...if this already ends up in the else branch, then there's something weird about your D3D11 driver, because in this case the D3D11 driver says that SG_PIXELFORMAT_DEPTH_STENCIL isn't renderable (this check happens here: https://github.com/floooh/sokol/blob/bd7fa9300dc2e2edca087cf436d1c5c07bd754fc/sokol_gfx.h#L9816)
...second can you check that the pixel format in sgdesc.context.depth_format
is indeed SG_PIXELFORMAT_DEPTH_STENCIL
(numeric value 43)?
PS: the closest sokol sample for your use case is this:
https://github.com/floooh/sokol-samples/blob/master/sapp/offscreen-msaa-sapp.c
...specifically this part where the pass object is created:
Note how there's now 3 image objects required instead of two:
...to access the render target as texture in a pixel shader you would need the resolve-image now
As for the first error, can you check these two things:
if (sg_query_pixelformat(SG_PIXELFORMAT_DEPTH_STENCIL).render) { printf("depth stencil is renderable\n"); } else { printf("depth stencil is not renderable!\n"); }
...if this already ends up in the else branch, then there's something weird about your D3D11 driver, because in this case the D3D11 driver says that SG_PIXELFORMAT_DEPTH_STENCIL isn't renderable (this check happens here:
https://github.com/floooh/sokol/blob/bd7fa9300dc2e2edca087cf436d1c5c07bd754fc/sokol_gfx.h#L9816 )
It ends up in the else
branch:
[INFO ] Initializing platform services
[INFO ] Initializing GDI+
[INFO ] Initializing time
[INFO ] Initializing renderer
[INFO ] depth stencil is not renderable!
...second can you check that the pixel format in
sgdesc.context.depth_format
is indeedSG_PIXELFORMAT_DEPTH_STENCIL
(numeric value 43)?
Thread 1 hit Breakpoint 1, (anonymous namespace)::SokolRenderTarget::SokolRenderTarget (this=0x1484c3189f0, width=1280, height=888) at Platform/Sokol/Renderer.cpp:117
117 desc.sample_count = sgdesc.context.sample_count;
(gdb) p sgdesc.context.depth_format
$2 = SG_PIXELFORMAT_DEPTH_STENCIL
(gdb) p (int)SG_PIXELFORMAT_DEPTH_STENCIL
$4 = 43
This is when creating the render target.
PS: the closest sokol sample for your use case is this:
https://github.com/floooh/sokol-samples/blob/master/sapp/offscreen-msaa-sapp.c
I'm not using MSAA, maybe it's something from sokol_gp? Also, I'm using sokol_app on Windows, but not on Android.
[INFO ] depth stencil is not renderable!
Wait, it's the same here on my laptop! I need to investigate this. In the meantime, please use SG_PIXELFORMAT_DEPTH as workaround for offscreen render targets (unless stencil is needed, in that case you'd need to wait for a fix).
I'm not using MSAA
Hmm, the error VALIDATE_ABND_FS_IMAGE_MSAA
happens when trying to bind a render target image with .sample_count > 1 to a shader stage, and since in your code a render target image is initialized like this:
sg_image_desc desc = {};
desc.render_target = true;
desc.width = width;
desc.height = height;
desc.pixel_format = SG_PIXELFORMAT_RGBA8;
desc.sample_count = sgdesc.context.sample_count; <===================
_target = sg_make_image(&desc);
...I was assuming that sgdesc.context.sample_count
is set to a value > 1. If no MSAA is intended for offscreen rendering, it's better to set desc.sample_count
explicitly to 1 (also in the pipeline objects used for offscreen rendering!)
I'll check what's up with the non-renderable SG_PIXELFORMAT_DEPTH_STENCIL next.
I'm preparing a fix for the non-renderable SG_PIXELFORMAT_DEPTH_STENCIL images in this PR:
https://github.com/floooh/sokol/pull/937
...the problem was that all depth pixel formats should also be reported as renderable (which didn't happen in the d3d11 backend). I also cleaned up the texture vs resource-view pixel formats for SG_PIXELFORMAT_DEPTH_STENCIL in the D3D11 backend (similar how it was already done for SG_PIXELFORMAT_DEPTH). I tested in the offscreen-sapp.c sample by switching all occurances of SG_PIXELFORMAT_DEPTH to SG_PIXELFORMAT_DEPTH_STENCIL.
The multisample validation error is something else though (please check that your rendertarget image really isn't created with a sample_count > 1.
Ok, PR https://github.com/floooh/sokol/pull/937 has been merged, which should fix the first part of the problem (not being able to create a depth-stencil render-target image.
Let me know if this works, and let's look into the multisample validation error next :)
Ok, I've updated sokol_gfx, and changed sokol_gp at one place to replace SG_SAMPLERTYPE_SAMPLE
with SG_SAMPLERTYPE_FILTERING
. My code to create a render target now looks like this:
SokolRenderTarget(long const width, long const height) : rm::RenderTarget(width, height) {
sg_desc sgdesc = sg_query_desc();
{
sg_image_desc desc = {};
desc.render_target = true;
desc.width = width;
desc.height = height;
desc.pixel_format = SG_PIXELFORMAT_RGBA8;
desc.sample_count = 1;
_target = sg_make_image(&desc);
if (sg_query_image_state(_target) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer image");
return;
}
RM_INFO("Created color attachment");
desc.pixel_format = SG_PIXELFORMAT_DEPTH;
desc.sample_count = 1;
_depth = sg_make_image(&desc);
if (sg_query_image_state(_depth) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer depth image");
return;
}
RM_INFO("Created depth buffer");
}
{
sg_pass_desc desc = {};
desc.color_attachments[0].image = _target;
desc.depth_stencil_attachment.image = _depth;
_pass = sg_make_pass(&desc);
if (sg_query_pass_state(_pass) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer pass");
return;
}
}
}
The render target is created but now I get an error when trying to render into it:
[ERROR] sokol_gfx.h:16131: VALIDATE_APIP_COLOR_FORMAT: sg_apply_pipeline: pipeline color attachment pixel format doesn't match pass color attachment pixel format
[ERROR] sokol_gfx.h:16132: VALIDATE_APIP_SAMPLE_COUNT: sg_apply_pipeline: pipeline MSAA sample count doesn't match render pass attachment sample count
[ERROR] sokol_gfx.h:16136: VALIDATE_APIP_DEPTH_FORMAT: sg_apply_pipeline: pipeline depth pixel_format doesn't match pass depth attachment pixel format
[FATAL] sokol_gfx.h:15603: VALIDATION_FAILED: validation layer checks failed
On Android, with the same code, I'm also getting a validation failure when trying to render into the render target:
sokol_gfx.h:16136: VALIDATE_APIP_DEPTH_FORMAT: sg_apply_pipeline: pipeline depth pixel_format doesn't match pass depth attachment pixel format
sokol_gfx.h:15603: VALIDATION_FAILED: validation layer checks failed
Thanks for the time you're putting into this issue, and please let me know if you need any other tests.
Ah ok, now it's clashing with sokol_gp.h pipeline creation code.
It looks like sokol_gp.h expects the depth-pixel-format to be identical with the default framebuffer, and doesn't have enough options to inject a completely custom pipeline object (e.g. this is all you can change: https://github.com/edubart/sokol_gp/blob/f3a4ec845c782157c4182c39e5a13c49f4858a60/sokol_gp.h#L530-L535).
On the other hand you can inject "any" pipeline here as long as it is compatible with what sokol_gp.h expects (e.g. you don't have to use sgp_make_pipeline()
:
There are two options now, either make your render pass compatible, with the default framebuffer, and switch off multisampling in the default framebuffer:
_target
and _depth
need to be changed back to be identical with the default framebuffer...or you create your own pipeline object with sg_make_pipeline()
(NOT sgp_make_pipeline()
) which is compatible with your render pass and a duplicate of the sokol_gp.h shader.
The third option is to ask the sokol_gp.h author (or to patch this in your own copy) to add more configuration options to sgp_make_pipeline()
, at least the depth pixel format and sample count.
I can now create a render target and use it without any issues on Android using this:
SokolRenderTarget(long const width, long const height) : rm::RenderTarget(width, height) {
sg_desc sgdesc = sg_query_desc();
{
sg_image_desc desc = {};
desc.render_target = true;
desc.width = width;
desc.height = height;
desc.pixel_format = sgdesc.context.color_format;
desc.sample_count = sgdesc.context.sample_count;
_target = sg_make_image(&desc);
if (sg_query_image_state(_target) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer image");
return;
}
RM_INFO("Created color attachment");
desc.pixel_format = sgdesc.context.depth_format;
_depth = sg_make_image(&desc);
if (sg_query_image_state(_depth) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer depth image");
return;
}
RM_INFO("Created depth buffer");
}
{
sg_pass_desc desc = {};
desc.color_attachments[0].image = _target;
desc.depth_stencil_attachment.image = _depth;
_pass = sg_make_pass(&desc);
if (sg_query_pass_state(_pass) != SG_RESOURCESTATE_VALID) {
RM_FATAL("Failed to create frame buffer pass");
return;
}
}
}
On Windows, the render target is correctly created, but all I get is a gray screen. This is on me though, since I can't even render a colored quad. I'm probably doing something wrong.
Thanks for all the help!
The third option is to ask the sokol_gp.h author (or to patch this in your own copy) to add more configuration options to sgp_make_pipeline(), at least the depth pixel format and sample count.
sokol_gp.h author here, I will probably expose both later to help with this issue.
But about the depth pixel format, the library is intended for 2D, so it does no care about depth-stencil format, that's why I created the issue https://github.com/floooh/sokol/issues/632 in the past. Ideally he should be not be using depth stencil for 2D stuff, maybe Sokol could have a "dont care" pixel format for depth-stencil, and then I advise users of Sokol GP to use that everywhere.
I updated sokol_gp.h
to be able to specify depth_format
and sample_count
in its pipelines, and also on context creation. So I think this issue can be closed.
Thanks!
I forgot to thank you guys for solving this, so thank you!
I'm having trouble creating a render target on Windows with the D3D11 backend.
I had code working fine on Android using the GLES3 backend, but it refused to create the render target on Windows:
There's a validation error when creating the depth buffer:
The best I could come up with is this:
It's a red flag for me, the fact that I'm testing the platform there tells me that I'd doing something wrong, but that got me past the render target creation. However, I then I get this error when rendering:
I'm using sokol_gp to render the game since it's 2D. I recon that the issue may be in it, but I'd appreciate some assurance that I'm correctly creating the render target.
Thanks in advance!