X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fshaderimage.c;h=b0ff09f256dc80f15728769d7db895d460226a2e;hb=42842306d3c7ba71f89022a1ebb09a4454a1b6e0;hp=c4ebf4201fbf8efd50d54aa8d9318f3d01fbc85c;hpb=958fc04dc51a2561c8598f42df59e3d9139e56a7;p=mesa.git diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c index c4ebf4201fb..b0ff09f256d 100644 --- a/src/mesa/main/shaderimage.c +++ b/src/mesa/main/shaderimage.c @@ -30,34 +30,12 @@ #include "mtypes.h" #include "formats.h" #include "errors.h" +#include "hash.h" #include "context.h" #include "texobj.h" #include "teximage.h" #include "enums.h" -/* - * Define endian-invariant aliases for some mesa formats that are - * defined in terms of their channel layout from LSB to MSB in a - * 32-bit word. The actual byte offsets matter here because the user - * is allowed to bit-cast one format into another and get predictable - * results. - */ -#ifdef MESA_BIG_ENDIAN -# define MESA_FORMAT_RGBA_8 MESA_FORMAT_A8B8G8R8_UNORM -# define MESA_FORMAT_RG_16 MESA_FORMAT_G16R16_UNORM -# define MESA_FORMAT_RG_8 MESA_FORMAT_G8R8_UNORM -# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_A8B8G8R8_SNORM -# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_G16R16_SNORM -# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_G8R8_SNORM -#else -# define MESA_FORMAT_RGBA_8 MESA_FORMAT_R8G8B8A8_UNORM -# define MESA_FORMAT_RG_16 MESA_FORMAT_R16G16_UNORM -# define MESA_FORMAT_RG_8 MESA_FORMAT_R8G8_UNORM -# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_R8G8B8A8_SNORM -# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_R16G16_SNORM -# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM -#endif - mesa_format _mesa_get_shader_image_format(GLenum format) { @@ -147,13 +125,13 @@ _mesa_get_shader_image_format(GLenum format) return MESA_FORMAT_R10G10B10A2_UNORM; case GL_RGBA8: - return MESA_FORMAT_RGBA_8; + return MESA_FORMAT_RGBA_UNORM8; case GL_RG16: - return MESA_FORMAT_RG_16; + return MESA_FORMAT_RG_UNORM16; case GL_RG8: - return MESA_FORMAT_RG_8; + return MESA_FORMAT_RG_UNORM8; case GL_R16: return MESA_FORMAT_R_UNORM16; @@ -165,13 +143,13 @@ _mesa_get_shader_image_format(GLenum format) return MESA_FORMAT_RGBA_SNORM16; case GL_RGBA8_SNORM: - return MESA_FORMAT_SIGNED_RGBA_8; + return MESA_FORMAT_RGBA_SNORM8; case GL_RG16_SNORM: - return MESA_FORMAT_SIGNED_RG_16; + return MESA_FORMAT_RG_SNORM16; case GL_RG8_SNORM: - return MESA_FORMAT_SIGNED_RG_8; + return MESA_FORMAT_RG_SNORM8; case GL_R16_SNORM: return MESA_FORMAT_R_SNORM16; @@ -293,13 +271,13 @@ get_image_format_class(mesa_format format) case MESA_FORMAT_R10G10B10A2_UNORM: return IMAGE_FORMAT_CLASS_2_10_10_10; - case MESA_FORMAT_RGBA_8: + case MESA_FORMAT_RGBA_UNORM8: return IMAGE_FORMAT_CLASS_4X8; - case MESA_FORMAT_RG_16: + case MESA_FORMAT_RG_UNORM16: return IMAGE_FORMAT_CLASS_2X16; - case MESA_FORMAT_RG_8: + case MESA_FORMAT_RG_UNORM8: return IMAGE_FORMAT_CLASS_2X8; case MESA_FORMAT_R_UNORM16: @@ -311,13 +289,13 @@ get_image_format_class(mesa_format format) case MESA_FORMAT_RGBA_SNORM16: return IMAGE_FORMAT_CLASS_4X16; - case MESA_FORMAT_SIGNED_RGBA_8: + case MESA_FORMAT_RGBA_SNORM8: return IMAGE_FORMAT_CLASS_4X8; - case MESA_FORMAT_SIGNED_RG_16: + case MESA_FORMAT_RG_SNORM16: return IMAGE_FORMAT_CLASS_2X16; - case MESA_FORMAT_SIGNED_RG_8: + case MESA_FORMAT_RG_SNORM8: return IMAGE_FORMAT_CLASS_2X8; case MESA_FORMAT_R_SNORM16: @@ -331,12 +309,54 @@ get_image_format_class(mesa_format format) } } -/** - * Return whether an image format should be supported based on the current API - * version of the context. - */ -static bool -is_image_format_supported(const struct gl_context *ctx, GLenum format) +static GLenum +_image_format_class_to_glenum(enum image_format_class class) +{ + switch (class) { + case IMAGE_FORMAT_CLASS_NONE: + return GL_NONE; + case IMAGE_FORMAT_CLASS_1X8: + return GL_IMAGE_CLASS_1_X_8; + case IMAGE_FORMAT_CLASS_1X16: + return GL_IMAGE_CLASS_1_X_16; + case IMAGE_FORMAT_CLASS_1X32: + return GL_IMAGE_CLASS_1_X_32; + case IMAGE_FORMAT_CLASS_2X8: + return GL_IMAGE_CLASS_2_X_8; + case IMAGE_FORMAT_CLASS_2X16: + return GL_IMAGE_CLASS_2_X_16; + case IMAGE_FORMAT_CLASS_2X32: + return GL_IMAGE_CLASS_2_X_32; + case IMAGE_FORMAT_CLASS_10_11_11: + return GL_IMAGE_CLASS_11_11_10; + case IMAGE_FORMAT_CLASS_4X8: + return GL_IMAGE_CLASS_4_X_8; + case IMAGE_FORMAT_CLASS_4X16: + return GL_IMAGE_CLASS_4_X_16; + case IMAGE_FORMAT_CLASS_4X32: + return GL_IMAGE_CLASS_4_X_32; + case IMAGE_FORMAT_CLASS_2_10_10_10: + return GL_IMAGE_CLASS_10_10_10_2; + default: + assert(!"Invalid image_format_class"); + return GL_NONE; + } +} + +GLenum +_mesa_get_image_format_class(GLenum format) +{ + mesa_format tex_format = _mesa_get_shader_image_format(format); + if (tex_format == MESA_FORMAT_NONE) + return GL_NONE; + + enum image_format_class class = get_image_format_class(tex_format); + return _image_format_class_to_glenum(class); +} + +bool +_mesa_is_shader_image_format_supported(const struct gl_context *ctx, + GLenum format) { switch (format) { /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the @@ -359,7 +379,7 @@ is_image_format_supported(const struct gl_context *ctx, GLenum format) /* Formats supported on unextended desktop GL and the original * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2 - * specification. + * specification or by GLES 3.1 with GL_NV_image_formats extension. */ case GL_RG32F: case GL_RG16F: @@ -376,18 +396,27 @@ is_image_format_supported(const struct gl_context *ctx, GLenum format) case GL_RG8I: case GL_R16I: case GL_R8I: - case GL_RGBA16: case GL_RGB10_A2: - case GL_RG16: case GL_RG8: - case GL_R16: case GL_R8: + case GL_RG8_SNORM: + case GL_R8_SNORM: + return true; + + /* Formats supported on unextended desktop GL and the original + * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2 + * specification. + * + * Following formats are supported by GLES 3.1 with GL_NV_image_formats & + * GL_EXT_texture_norm16 extensions. + */ + case GL_RGBA16: case GL_RGBA16_SNORM: + case GL_RG16: case GL_RG16_SNORM: - case GL_RG8_SNORM: + case GL_R16: case GL_R16_SNORM: - case GL_R8_SNORM: - return _mesa_is_desktop_gl(ctx); + return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx); default: return false; @@ -411,10 +440,22 @@ _mesa_init_image_units(struct gl_context *ctx) { unsigned i; + ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT); + for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) ctx->ImageUnits[i] = _mesa_default_image_unit(ctx); } + +void +_mesa_free_image_textures(struct gl_context *ctx) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) + _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL); +} + GLboolean _mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u) { @@ -476,8 +517,8 @@ _mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u) static GLboolean validate_bind_image_texture(struct gl_context *ctx, GLuint unit, - GLuint texture, GLint level, GLboolean layered, - GLint layer, GLenum access, GLenum format) + GLuint texture, GLint level, GLint layer, + GLenum access, GLenum format, bool check_level_layer) { assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS); @@ -486,14 +527,19 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit, return GL_FALSE; } - if (level < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)"); - return GL_FALSE; - } + if (check_level_layer) { + /* EXT_shader_image_load_store doesn't throw an error if level or + * layer is negative. + */ + if (level < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)"); + return GL_FALSE; + } - if (layer < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)"); - return GL_FALSE; + if (layer < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)"); + return GL_FALSE; + } } if (access != GL_READ_ONLY && @@ -503,7 +549,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit, return GL_FALSE; } - if (!is_image_format_supported(ctx, format)) { + if (!_mesa_is_shader_image_format_supported(ctx, format)) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); return GL_FALSE; } @@ -511,27 +557,75 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit, return GL_TRUE; } +static void +set_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj, + GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format) +{ + u->Level = level; + u->Access = access; + u->Format = format; + u->_ActualFormat = _mesa_get_shader_image_format(format); + + if (texObj && _mesa_tex_target_is_layered(texObj->Target)) { + u->Layered = layered; + u->Layer = layer; + } else { + u->Layered = GL_FALSE; + u->Layer = 0; + } + u->_Layer = (u->Layered ? 0 : u->Layer); + + _mesa_reference_texobj(&u->TexObj, texObj); +} + +static void +bind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj, + GLuint unit, GLint level, GLboolean layered, GLint layer, + GLenum access, GLenum format) +{ + struct gl_image_unit *u; + + u = &ctx->ImageUnits[unit]; + + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; + + set_image_binding(u, texObj, level, layered, layer, access, format); +} + +void GLAPIENTRY +_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level, + GLboolean layered, GLint layer, GLenum access, + GLenum format) +{ + struct gl_texture_object *texObj = NULL; + + GET_CURRENT_CONTEXT(ctx); + + if (texture) + texObj = _mesa_lookup_texture(ctx, texture); + + bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format); +} + void GLAPIENTRY _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { + struct gl_texture_object *texObj = NULL; + GET_CURRENT_CONTEXT(ctx); - struct gl_image_unit *u; - if (!validate_bind_image_texture(ctx, unit, texture, level, - layered, layer, access, format)) + if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access, + format, true)) return; - u = &ctx->ImageUnits[unit]; - - FLUSH_VERTICES(ctx, 0); - ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; - if (texture) { - struct gl_texture_object *t = _mesa_lookup_texture(ctx, texture); + texObj = _mesa_lookup_texture(ctx, texture); - if (!t) { + if (!texObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); return; } @@ -541,58 +635,57 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, * * "An INVALID_OPERATION error is generated if texture is not the name * of an immutable texture object." + * + * However note that issue 7 of the GL_OES_texture_buffer spec + * recognizes that there is no way to create immutable buffer textures, + * so those are excluded from this requirement. + * + * Additionally, issue 10 of the OES_EGL_image_external_essl3 spec + * states that glBindImageTexture must accept external textures. */ - if (_mesa_is_gles(ctx) && !t->Immutable) { + if (_mesa_is_gles(ctx) && !texObj->Immutable && + texObj->Target != GL_TEXTURE_BUFFER && + texObj->Target != GL_TEXTURE_EXTERNAL_OES) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTexture(!immutable)"); return; } - - _mesa_reference_texobj(&u->TexObj, t); - } else { - _mesa_reference_texobj(&u->TexObj, NULL); } - u->Level = level; - u->Access = access; - u->Format = format; - u->_ActualFormat = _mesa_get_shader_image_format(format); - - if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) { - u->Layered = layered; - u->Layer = layer; - u->_Layer = (u->Layered ? 0 : u->Layer); - } else { - u->Layered = GL_FALSE; - u->Layer = 0; - } + bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format); } void GLAPIENTRY -_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) +_mesa_BindImageTextureEXT(GLuint index, GLuint texture, GLint level, + GLboolean layered, GLint layer, GLenum access, + GLint format) { + struct gl_texture_object *texObj = NULL; + GET_CURRENT_CONTEXT(ctx); - int i; - if (!ctx->Extensions.ARB_shader_image_load_store) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()"); + if (!validate_bind_image_texture(ctx, index, texture, level, layer, access, + format, false)) return; - } - if (first + count > ctx->Const.MaxImageUnits) { - /* The ARB_multi_bind spec says: - * - * "An INVALID_OPERATION error is generated if + - * is greater than the number of image units supported by - * the implementation." - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindImageTextures(first=%u + count=%d > the value of " - "GL_MAX_IMAGE_UNITS=%u)", - first, count, ctx->Const.MaxImageUnits); - return; + if (texture) { + texObj = _mesa_lookup_texture(ctx, texture); + + if (!texObj) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTextureEXT(texture)"); + return; + } } + bind_image_texture(ctx, texObj, index, level, layered, layer, access, format); +} + +static ALWAYS_INLINE void +bind_image_textures(struct gl_context *ctx, GLuint first, GLuint count, + const GLuint *textures, bool no_error) +{ + int i; + /* Assume that at least one binding will be changed */ FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; @@ -616,19 +709,19 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) * their parameters are valid and no other error occurs." */ - _mesa_begin_texture_lookups(ctx); + _mesa_HashLockMutex(ctx->Shared->TexObjects); for (i = 0; i < count; i++) { struct gl_image_unit *u = &ctx->ImageUnits[first + i]; const GLuint texture = textures ? textures[i] : 0; - if (texture != 0) { - struct gl_texture_object *texObj; + if (texture) { + struct gl_texture_object *texObj = u->TexObj; GLenum tex_format; - if (!u->TexObj || u->TexObj->Name != texture) { + if (!texObj || texObj->Name != texture) { texObj = _mesa_lookup_texture_locked(ctx, texture); - if (!texObj) { + if (!no_error && !texObj) { /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if any value @@ -641,8 +734,6 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) "object)", i, texture); continue; } - } else { - texObj = u->TexObj; } if (texObj->Target == GL_TEXTURE_BUFFER) { @@ -650,8 +741,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) } else { struct gl_texture_image *image = texObj->Image[0][0]; - if (!image || image->Width == 0 || image->Height == 0 || - image->Depth == 0) { + if (!no_error && (!image || image->Width == 0 || + image->Height == 0 || image->Depth == 0)) { /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if the width, @@ -668,7 +759,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) tex_format = image->InternalFormat; } - if (!is_image_format_supported(ctx, tex_format)) { + if (!no_error && + !_mesa_is_shader_image_format_supported(ctx, tex_format)) { /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if the internal @@ -685,73 +777,50 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) } /* Update the texture binding */ - _mesa_reference_texobj(&u->TexObj, texObj); - u->Level = 0; - u->Layered = _mesa_tex_target_is_layered(texObj->Target); - u->_Layer = u->Layer = 0; - u->Access = GL_READ_WRITE; - u->Format = tex_format; - u->_ActualFormat = _mesa_get_shader_image_format(tex_format); + set_image_binding(u, texObj, 0, + _mesa_tex_target_is_layered(texObj->Target), + 0, GL_READ_WRITE, tex_format); } else { /* Unbind the texture from the unit */ - _mesa_reference_texobj(&u->TexObj, NULL); - u->Level = 0; - u->Layered = GL_FALSE; - u->_Layer = u->Layer = 0; - u->Access = GL_READ_ONLY; - u->Format = GL_R8; - u->_ActualFormat = MESA_FORMAT_R_UNORM8; + set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); } } - _mesa_end_texture_lookups(ctx); + _mesa_HashUnlockMutex(ctx->Shared->TexObjects); } void GLAPIENTRY -_mesa_MemoryBarrier(GLbitfield barriers) +_mesa_BindImageTextures_no_error(GLuint first, GLsizei count, + const GLuint *textures) { GET_CURRENT_CONTEXT(ctx); - if (ctx->Driver.MemoryBarrier) - ctx->Driver.MemoryBarrier(ctx, barriers); + bind_image_textures(ctx, first, count, textures, true); } void GLAPIENTRY -_mesa_MemoryBarrierByRegion(GLbitfield barriers) +_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) { GET_CURRENT_CONTEXT(ctx); - GLbitfield all_allowed_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | - GL_FRAMEBUFFER_BARRIER_BIT | - GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | - GL_SHADER_STORAGE_BARRIER_BIT | - GL_TEXTURE_FETCH_BARRIER_BIT | - GL_UNIFORM_BARRIER_BIT; - - if (ctx->Driver.MemoryBarrier) { - /* From section 7.11.2 of the OpenGL ES 3.1 specification: - * - * "When barriers is ALL_BARRIER_BITS, shader memory accesses will be - * synchronized relative to all these barrier bits, but not to other - * barrier bits specific to MemoryBarrier." - * - * That is, if barriers is the special value GL_ALL_BARRIER_BITS, then all - * barriers allowed by glMemoryBarrierByRegion should be activated." - */ - if (barriers == GL_ALL_BARRIER_BITS) - return ctx->Driver.MemoryBarrier(ctx, all_allowed_bits); + if (!ctx->Extensions.ARB_shader_image_load_store) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()"); + return; + } - /* From section 7.11.2 of the OpenGL ES 3.1 specification: + if (first + count > ctx->Const.MaxImageUnits) { + /* The ARB_multi_bind spec says: * - * "An INVALID_VALUE error is generated if barriers is not the special - * value ALL_BARRIER_BITS, and has any bits set other than those - * described above." + * "An INVALID_OPERATION error is generated if + + * is greater than the number of image units supported by + * the implementation." */ - if ((barriers & ~all_allowed_bits) != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glMemoryBarrierByRegion(unsupported barrier bit"); - } - - ctx->Driver.MemoryBarrier(ctx, barriers); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(first=%u + count=%d > the value of " + "GL_MAX_IMAGE_UNITS=%u)", + first, count, ctx->Const.MaxImageUnits); + return; } + + bind_image_textures(ctx, first, count, textures, false); }