floooh / sokol

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

Sampling a depth texture using `SG_IMAGESAMPLETYPE_FLOAT` in order to copy it to the main framebuffer's depth buffer #1008

Closed kcbanner closed 3 months ago

kcbanner commented 3 months ago

I'm trying to copy my depth buffer from my deferred rendering stage into the back buffer's depth buffer, so that I can depth test the forward rendering steps against it. However, I'm running into this issue:

                        const _sg_pixelformat_info_t* info = &_sg.formats[img->cmn.pixel_format];
                        switch (stage->images[i].sample_type) {
                            case SG_IMAGESAMPLETYPE_FLOAT:
                                _SG_VALIDATE(info->filter, VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE);
                                break;
                            case SG_IMAGESAMPLETYPE_DEPTH:
                                _SG_VALIDATE(info->depth, VALIDATE_ABND_VS_EXPECTED_DEPTH_IMAGE);
                                break;

I"m hitting the VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE assert, because the .DEPTH format doesn't set the filter flag. I know it's possible to use shadow samplers to sample this texture and do comparisons, but I don't want to compare anything here, just copy the raw depth values into gl_FragDepth at the end of my tone mapping pass.

Is this possible currently? I think I could work around the issue with manual glBlitFramebuffer calls, but that's only going to work for OpenGL.

floooh commented 3 months ago

You can check how the https://floooh.github.io/sokol-html5/shadows-depthtex-sapp.html sample renders the shadow map visualization in the bottom right corner. The texture and sampler to sample the depth-texture like a regular float texture need to be annotated in the shader code like this:

https://github.com/floooh/sokol-samples/blob/801de1f6ef8acc7f824efe259293eb88a4476479/sapp/shadows-depthtex-sapp.glsl#L118-L121

...alternatively, if you don't use sokol-shdc, you need to pass that information in the sg_shader_desc:

    .images[X].sample_type = SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT;
    .samplers[Y].sampler_type = SG_SAMPLERTYPE_NONFILTERING

...this is a WebGPU backend requirement, basically WebGPU needs to know upfront how a texture and associated sampler is being used in the shader. In most cases this information can be extracted by the shader compiler from the shader code, but not for this specific combination of unfilterable-float/non-filtering.

There's more info here: https://floooh.github.io/2023/10/16/sokol-webgpu.html#the-unfilterable-float-texture--nonfiltering-sampler-conundrum

kcbanner commented 3 months ago

Ah! I went as far as to look at the source of sokol-shdc to see how it decided to use depth sampling, but completely missed image_sample_type :D

It's working perfectly now, thanks!