X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fshaderimage.c;h=040e9fd6e3ce0ea75706787c50055f9c06995a35;hb=ffd9c7fd74622b3c4271ea31df9e09b4180d4a5a;hp=a348cdb04058840698dff09c1394ae1f0aa5f829;hpb=2f11e92cef51c88a09bc778e2ceca4ab50cf0017;p=mesa.git diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c index a348cdb0405..040e9fd6e3c 100644 --- a/src/mesa/main/shaderimage.c +++ b/src/mesa/main/shaderimage.c @@ -331,21 +331,92 @@ 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) +{ + switch (format) { + /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the + * OpenGL ES 3.1 specification. + */ + case GL_RGBA32F: + case GL_RGBA16F: + case GL_R32F: + case GL_RGBA32UI: + case GL_RGBA16UI: + case GL_RGBA8UI: + case GL_R32UI: + case GL_RGBA32I: + case GL_RGBA16I: + case GL_RGBA8I: + case GL_R32I: + case GL_RGBA8: + case GL_RGBA8_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. + */ + case GL_RG32F: + case GL_RG16F: + case GL_R11F_G11F_B10F: + case GL_R16F: + case GL_RGB10_A2UI: + case GL_RG32UI: + case GL_RG16UI: + case GL_RG8UI: + case GL_R16UI: + case GL_R8UI: + case GL_RG32I: + case GL_RG16I: + 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_RGBA16_SNORM: + case GL_RG16_SNORM: + case GL_RG8_SNORM: + case GL_R16_SNORM: + case GL_R8_SNORM: + return _mesa_is_desktop_gl(ctx); + + default: + return false; + } +} + +struct gl_image_unit +_mesa_default_image_unit(struct gl_context *ctx) +{ + const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI; + const struct gl_image_unit u = { + .Access = GL_READ_ONLY, + .Format = format, + ._ActualFormat = _mesa_get_shader_image_format(format) + }; + return u; +} + void _mesa_init_image_units(struct gl_context *ctx) { unsigned i; - for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) { - struct gl_image_unit *u = &ctx->ImageUnits[i]; - u->Access = GL_READ_ONLY; - u->Format = GL_R8; - u->_ActualFormat = _mesa_get_shader_image_format(u->Format); - } + for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) + ctx->ImageUnits[i] = _mesa_default_image_unit(ctx); } -static GLboolean -validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) +GLboolean +_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u) { struct gl_texture_object *t = u->TexObj; mesa_format tex_format; @@ -353,7 +424,8 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) if (!t) return GL_FALSE; - _mesa_test_texobj_completeness(ctx, t); + if (!t->_BaseComplete && !t->_MipmapComplete) + _mesa_test_texobj_completeness(ctx, t); if (u->Level < t->BaseLevel || u->Level > t->_MaxLevel || @@ -362,7 +434,7 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) return GL_FALSE; if (_mesa_tex_target_is_layered(t->Target) && - u->Layer >= _mesa_get_texture_layers(t, u->Level)) + u->_Layer >= _mesa_get_texture_layers(t, u->Level)) return GL_FALSE; if (t->Target == GL_TEXTURE_BUFFER) { @@ -370,7 +442,7 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) } else { struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ? - t->Image[u->Layer][u->Level] : + t->Image[u->_Layer][u->Level] : t->Image[0][u->Level]); if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples) @@ -402,17 +474,6 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) return GL_TRUE; } -void -_mesa_validate_image_units(struct gl_context *ctx) -{ - unsigned i; - - for (i = 0; i < ctx->Const.MaxImageUnits; ++i) { - struct gl_image_unit *u = &ctx->ImageUnits[i]; - u->_Valid = validate_image_unit(ctx, u); - } -} - static GLboolean validate_bind_image_texture(struct gl_context *ctx, GLuint unit, GLuint texture, GLint level, GLboolean layered, @@ -442,7 +503,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit, return GL_FALSE; } - if (!_mesa_get_shader_image_format(format)) { + if (!is_image_format_supported(ctx, format)) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); return GL_FALSE; } @@ -475,6 +536,18 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, return; } + /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES + * 3.1 spec: + * + * "An INVALID_OPERATION error is generated if texture is not the name + * of an immutable texture object." + */ + if (_mesa_is_gles(ctx) && !t->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTexture(!immutable)"); + return; + } + _mesa_reference_texobj(&u->TexObj, t); } else { _mesa_reference_texobj(&u->TexObj, NULL); @@ -484,19 +557,15 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, u->Access = access; u->Format = format; u->_ActualFormat = _mesa_get_shader_image_format(format); - u->_Valid = validate_image_unit(ctx, u); if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) { u->Layered = layered; - u->Layer = (layered ? 0 : layer); + u->Layer = layer; + u->_Layer = (u->Layered ? 0 : u->Layer); } else { u->Layered = GL_FALSE; u->Layer = 0; } - - if (ctx->Driver.BindImageTexture) - ctx->Driver.BindImageTexture(ctx, u, u->TexObj, level, layered, - layer, access, format); } void GLAPIENTRY @@ -599,7 +668,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) tex_format = image->InternalFormat; } - if (_mesa_get_shader_image_format(tex_format) == MESA_FORMAT_NONE) { + if (!is_image_format_supported(ctx, tex_format)) { /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if the internal @@ -619,27 +688,20 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) _mesa_reference_texobj(&u->TexObj, texObj); u->Level = 0; u->Layered = _mesa_tex_target_is_layered(texObj->Target); - u->Layer = 0; + u->_Layer = u->Layer = 0; u->Access = GL_READ_WRITE; u->Format = tex_format; u->_ActualFormat = _mesa_get_shader_image_format(tex_format); - u->_Valid = validate_image_unit(ctx, u); } else { /* Unbind the texture from the unit */ _mesa_reference_texobj(&u->TexObj, NULL); u->Level = 0; u->Layered = GL_FALSE; - u->Layer = 0; + u->_Layer = u->Layer = 0; u->Access = GL_READ_ONLY; u->Format = GL_R8; u->_ActualFormat = MESA_FORMAT_R_UNORM8; - u->_Valid = GL_FALSE; } - - /* Pass the BindImageTexture call down to the device driver */ - if (ctx->Driver.BindImageTexture) - ctx->Driver.BindImageTexture(ctx, u, u->TexObj, u->Level, u->Layered, - u->Layer, u->Access, u->Format); } _mesa_end_texture_lookups(ctx); @@ -653,3 +715,45 @@ _mesa_MemoryBarrier(GLbitfield barriers) if (ctx->Driver.MemoryBarrier) ctx->Driver.MemoryBarrier(ctx, barriers); } + +void GLAPIENTRY +_mesa_MemoryBarrierByRegion(GLbitfield barriers) +{ + 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) { + ctx->Driver.MemoryBarrier(ctx, all_allowed_bits); + return; + } + + /* From section 7.11.2 of the OpenGL ES 3.1 specification: + * + * "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." + */ + if ((barriers & ~all_allowed_bits) != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glMemoryBarrierByRegion(unsupported barrier bit"); + } + + ctx->Driver.MemoryBarrier(ctx, barriers); + } +}