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:

committed by
Marge Bot

parent
206aad7c5c
commit
e713a9a982
@@ -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? */
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user