From 0c6e56c391a262bef2d20037b4ca77d60948f3e7 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 20 Jan 2023 14:53:32 -0500 Subject: [PATCH] mesa: (more) correctly handle incomplete depth textures MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit according to GL spec, incomplete shadow samplers should return 0 this is technically possible for drivers to do using a RGBA texture in the sense that somehow it's been working, but it's broken at the gallium-level for what drivers should be expecting to see in such circumstances given that such scenarios have been binding a RGBA texture to use with shadow samplers instead, we can give drivers a fallback Z32 texture to avoid format/sampler mismatches and complying with expected behavior see also KHR-GL46.incomplete_texture_access.sampler for driver-specific testing Reviewed-by: Emma Anholt Reviewed-by: Marek Olšák Part-of: --- src/mesa/main/mtypes.h | 2 +- src/mesa/main/shared.c | 6 ++++-- src/mesa/main/texobj.c | 35 +++++++++++++++++++++++------------ src/mesa/main/texobj.h | 2 +- src/mesa/main/texstate.c | 4 ++-- src/mesa/state_tracker/st_context.c | 10 ++++++---- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 80ce5f9..210c128 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2413,7 +2413,7 @@ struct gl_shared_state struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS]; /** Fallback texture used when a bound texture is incomplete */ - struct gl_texture_object *FallbackTex[NUM_TEXTURE_TARGETS]; + struct gl_texture_object *FallbackTex[NUM_TEXTURE_TARGETS][2]; /**< [color, depth] */ /** * \name Thread safety and statechange notification for texture diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index b62c01c..c4904f6 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -335,8 +335,10 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) /* Free the dummy/fallback texture objects */ for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { - if (shared->FallbackTex[i]) - _mesa_delete_texture_object(ctx, shared->FallbackTex[i]); + for (unsigned j = 0; j < ARRAY_SIZE(shared->FallbackTex[0]); j++) { + if (shared->FallbackTex[i][j]) + _mesa_delete_texture_object(ctx, shared->FallbackTex[i][j]); + } } /* diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index ada2097..a8dc37e 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -974,14 +974,15 @@ _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj) /** * Return pointer to a default/fallback texture of the given type/target. - * The texture is an RGBA texture with all texels = (0,0,0,1). + * The texture is an RGBA texture with all texels = (0,0,0,1) OR + * a depth texture that returns 0. * That's the value a GLSL sampler should get when sampling from an * incomplete texture. */ struct gl_texture_object * -_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) +_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex, bool is_depth) { - if (!ctx->Shared->FallbackTex[tex]) { + if (!ctx->Shared->FallbackTex[tex][is_depth]) { /* create fallback texture now */ const GLsizei width = 1, height = 1; GLsizei depth = 1; @@ -1067,9 +1068,14 @@ _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) texObj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; texObj->Sampler.Attrib.state.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - texFormat = st_ChooseTextureFormat(ctx, target, - GL_RGBA, GL_RGBA, - GL_UNSIGNED_BYTE); + if (is_depth) + texFormat = st_ChooseTextureFormat(ctx, target, + GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, + GL_NONE); + else + texFormat = st_ChooseTextureFormat(ctx, target, + GL_RGBA, GL_RGBA, + GL_UNSIGNED_BYTE); /* need a loop here just for cube maps */ for (face = 0; face < numFaces; face++) { @@ -1083,24 +1089,29 @@ _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) (dims > 1) ? height : 1, (dims > 2) ? depth : 1, 0, /* border */ - GL_RGBA, texFormat); + is_depth ? GL_DEPTH_COMPONENT : GL_RGBA, texFormat); _mesa_update_texture_object_swizzle(ctx, texObj); - st_TexImage(ctx, dims, texImage, - GL_RGBA, GL_UNSIGNED_BYTE, texel, - &ctx->DefaultPacking); + if (is_depth) + st_TexImage(ctx, dims, texImage, + GL_DEPTH_COMPONENT, GL_FLOAT, texel, + &ctx->DefaultPacking); + else + st_TexImage(ctx, dims, texImage, + GL_RGBA, GL_UNSIGNED_BYTE, texel, + &ctx->DefaultPacking); } _mesa_test_texobj_completeness(ctx, texObj); assert(texObj->_BaseComplete); assert(texObj->_MipmapComplete); - ctx->Shared->FallbackTex[tex] = texObj; + ctx->Shared->FallbackTex[tex][is_depth] = texObj; /* Complete the driver's operation in case another context will also * use the same fallback texture. */ st_glFinish(ctx); } - return ctx->Shared->FallbackTex[tex]; + return ctx->Shared->FallbackTex[tex][is_depth]; } diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index fe66c46..5e51665 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -186,7 +186,7 @@ extern void _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj); extern struct gl_texture_object * -_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex); +_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex, bool is_depth); extern GLuint _mesa_total_texture_memory(struct gl_context *ctx); diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 49cfd5d..a78fa4d6 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -704,7 +704,7 @@ update_single_program_texture(struct gl_context *ctx, struct gl_program *prog, * Mesa implements this by creating a hidden texture object with a pixel of * that value. */ - texObj = _mesa_get_fallback_texture(ctx, target_index); + texObj = _mesa_get_fallback_texture(ctx, target_index, !!(prog->ShadowSamplers & BITFIELD_BIT(unit))); assert(texObj); return texObj; @@ -870,7 +870,7 @@ fix_missing_textures_for_atifs(struct gl_context *ctx, if (!ctx->Texture.Unit[unit]._Current) { struct gl_texture_object *texObj = - _mesa_get_fallback_texture(ctx, target_index); + _mesa_get_fallback_texture(ctx, target_index, false); _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj); BITSET_SET(enabled_texture_units, unit); ctx->Texture._MaxEnabledTexImageUnit = diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index a622605..cc0489c 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -944,10 +944,12 @@ st_destroy_context(struct st_context *st) * context. */ for (unsigned i = 0; i < NUM_TEXTURE_TARGETS; i++) { - struct gl_texture_object *stObj = - ctx->Shared->FallbackTex[i]; - if (stObj) { - st_texture_release_context_sampler_view(st, stObj); + for (unsigned j = 0; j < ARRAY_SIZE(ctx->Shared->FallbackTex[0]); j++) { + struct gl_texture_object *stObj = + ctx->Shared->FallbackTex[i][j]; + if (stObj) { + st_texture_release_context_sampler_view(st, stObj); + } } } -- 2.7.4