mesa: (more) correctly handle incomplete depth textures
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 <emma@anholt.net> Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20817>
This commit is contained in:

committed by
Marge Bot

parent
818cc30852
commit
0c6e56c391
@@ -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
|
||||
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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 =
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user