mesa: track format swizzles on teximage objects

this will only very rarely change, so stop calculating it during sampler update

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17687>
This commit is contained in:
Mike Blumenkrantz
2022-08-01 10:00:01 -04:00
committed by Marge Bot
parent 206aad7c5c
commit e713a9a982
4 changed files with 127 additions and 1 deletions

View File

@@ -789,6 +789,9 @@ struct gl_texture_image
/** Cube map face: index into gl_texture_object::Image[] array */
GLuint Face;
unsigned FormatSwizzle;
unsigned FormatSwizzleGLSL130; //for depth formats
/** GL_ARB_texture_multisample */
GLuint NumSamples; /**< Sample count, or 0 for non-multisample */
GLboolean FixedSampleLocations; /**< Same sample locations for all pixels? */

View File

@@ -60,6 +60,8 @@
#include "util/u_memory.h"
#include "program/prog_instruction.h"
#include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_format.h"
@@ -803,6 +805,100 @@ clear_teximage_fields(struct gl_texture_image *img)
img->FixedSampleLocations = GL_TRUE;
}
/**
* Given a user-specified texture base format, the actual gallium texture
* format and the current GL_DEPTH_MODE, return a texture swizzle.
*
* Consider the case where the user requests a GL_RGB internal texture
* format the driver actually uses an RGBA format. The A component should
* be ignored and sampling from the texture should always return (r,g,b,1).
* But if we rendered to the texture we might have written A values != 1.
* By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
* This function computes the texture swizzle needed to get the expected
* values.
*
* In the case of depth textures, the GL_DEPTH_MODE state determines the
* texture swizzle.
*
* This result must be composed with the user-specified swizzle to get
* the final swizzle.
*/
static unsigned
compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
bool glsl130_or_later)
{
switch (baseFormat) {
case GL_RGBA:
return SWIZZLE_XYZW;
case GL_RGB:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
case GL_RG:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
case GL_RED:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
SWIZZLE_ZERO, SWIZZLE_ONE);
case GL_ALPHA:
return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
SWIZZLE_ZERO, SWIZZLE_W);
case GL_LUMINANCE:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
case GL_LUMINANCE_ALPHA:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
case GL_INTENSITY:
return SWIZZLE_XXXX;
case GL_STENCIL_INDEX:
case GL_DEPTH_STENCIL:
case GL_DEPTH_COMPONENT:
/* Now examine the depth mode */
switch (depthMode) {
case GL_LUMINANCE:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
case GL_INTENSITY:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
case GL_ALPHA:
/* The texture(sampler*Shadow) functions from GLSL 1.30 ignore
* the depth mode and return float, while older shadow* functions
* and ARB_fp instructions return vec4 according to the depth mode.
*
* The problem with the GLSL 1.30 functions is that GL_ALPHA forces
* them to return 0, breaking them completely.
*
* A proper fix would increase code complexity and that's not worth
* it for a rarely used feature such as the GL_ALPHA depth mode
* in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all
* shaders that use GLSL 1.30 or later.
*
* BTW, it's required that sampler views are updated when
* shaders change (check_sampler_swizzle takes care of that).
*/
if (glsl130_or_later)
return SWIZZLE_XXXX;
else
return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
SWIZZLE_ZERO, SWIZZLE_X);
case GL_RED:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
SWIZZLE_ZERO, SWIZZLE_ONE);
default:
assert(!"Unexpected depthMode");
return SWIZZLE_XYZW;
}
default:
assert(!"Unexpected baseFormat");
return SWIZZLE_XYZW;
}
}
void
_mesa_update_teximage_format_swizzle(struct gl_context *ctx,
struct gl_texture_image *img,
GLenum depth_mode)
{
if (!img)
return;
img->FormatSwizzle = compute_texture_format_swizzle(img->_BaseFormat, depth_mode, false);
img->FormatSwizzleGLSL130 = compute_texture_format_swizzle(img->_BaseFormat, depth_mode, true);
}
/**
* Initialize basic fields of the gl_texture_image struct.
@@ -845,6 +941,22 @@ _mesa_init_teximage_fields_ms(struct gl_context *ctx,
img->Height = height;
img->Depth = depth;
GLenum depth_mode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
/* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures
* with depth component data specified with a sized internal format.
*/
if (_mesa_is_gles3(ctx) &&
(base_format == GL_DEPTH_COMPONENT ||
base_format == GL_DEPTH_STENCIL ||
base_format == GL_STENCIL_INDEX)) {
if (internalFormat != GL_DEPTH_COMPONENT &&
internalFormat != GL_DEPTH_STENCIL &&
internalFormat != GL_STENCIL_INDEX)
depth_mode = GL_RED;
}
_mesa_update_teximage_format_swizzle(ctx, img, depth_mode);
img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
img->WidthLog2 = util_logbase2(img->Width2);
@@ -3172,6 +3284,10 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
_mesa_update_fbo_texture(ctx, texObj, face, level);
_mesa_dirty_texobj(ctx, texObj);
/* only apply depthMode swizzle if it was explicitly changed */
GLenum depth_mode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
if (texObj->Attrib.DepthMode != depth_mode)
_mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode);
}
}
_mesa_unlock_texture(ctx, texObj);

View File

@@ -139,7 +139,10 @@ _mesa_init_teximage_fields_ms(struct gl_context *ctx,
GLuint numSamples,
GLboolean fixedSampleLocations);
void
_mesa_update_teximage_format_swizzle(struct gl_context *ctx,
struct gl_texture_image *img,
GLenum depth_mode);
extern mesa_format
_mesa_choose_texture_format(struct gl_context *ctx,
struct gl_texture_object *texObj,

View File

@@ -415,6 +415,8 @@ set_tex_parameteri(struct gl_context *ctx,
texObj->Attrib.BaseLevel = MIN2(texObj->Attrib.ImmutableLevels - 1, params[0]);
else
texObj->Attrib.BaseLevel = params[0];
if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS)
_mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode);
return GL_TRUE;
@@ -518,6 +520,8 @@ set_tex_parameteri(struct gl_context *ctx,
(ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
flush(ctx);
texObj->Attrib.DepthMode = params[0];
if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS)
_mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode);
return GL_TRUE;
}
goto invalid_param;