From 326a82a255c1a72376ce2b7f3d878bfff5cb9621 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 24 Feb 2017 19:24:56 +0100 Subject: [PATCH] mesa: add support for glUniformHandleui64*ARB() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Bindless sampler/image handles are represented using 64-bit unsigned integers. The ARB_bindless_texture spec says: "The error INVALID_OPERATION is generated by UniformHandleui64{v}ARB if the sampler or image uniform being updated has the "bound_sampler" or "bound_image" layout qualifier"." Signed-off-by: Samuel Pitoiset Reviewed-by: Nicolai Hähnle --- src/compiler/glsl/ir_uniform.h | 6 +++ src/compiler/glsl/link_uniforms.cpp | 1 + src/compiler/glsl/shader_cache.cpp | 2 + src/mesa/main/uniform_query.cpp | 64 +++++++++++++++++++++++++++++ src/mesa/main/uniforms.c | 15 +++++++ src/mesa/main/uniforms.h | 4 ++ 6 files changed, 92 insertions(+) diff --git a/src/compiler/glsl/ir_uniform.h b/src/compiler/glsl/ir_uniform.h index b6aec7fc4af..9841df8cde1 100644 --- a/src/compiler/glsl/ir_uniform.h +++ b/src/compiler/glsl/ir_uniform.h @@ -201,6 +201,12 @@ struct gl_uniform_storage { * top-level shader storage block member. (GL_TOP_LEVEL_ARRAY_STRIDE). */ unsigned top_level_array_stride; + + /** + * Whether this uniform variable has the bindless_sampler or bindless_image + * layout qualifier as specified by ARB_bindless_texture. + */ + bool is_bindless; }; #ifdef __cplusplus diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index b11739ce78a..7c3ca75416d 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -754,6 +754,7 @@ private: this->uniforms[id].is_shader_storage = current_var->is_in_shader_storage_block(); + this->uniforms[id].is_bindless = current_var->data.bindless; /* Do not assign storage if the uniform is a builtin or buffer object */ if (!this->uniforms[id].builtin && diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp index dd56501258c..1ad8fdd62a4 100644 --- a/src/compiler/glsl/shader_cache.cpp +++ b/src/compiler/glsl/shader_cache.cpp @@ -578,6 +578,7 @@ write_uniforms(struct blob *metadata, struct gl_shader_program *prog) blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage); blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride); blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major); + blob_write_uint32(metadata, prog->data->UniformStorage[i].is_bindless); blob_write_uint32(metadata, prog->data->UniformStorage[i].num_compatible_subroutines); blob_write_uint32(metadata, @@ -642,6 +643,7 @@ read_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog) uniforms[i].is_shader_storage = blob_read_uint32(metadata); uniforms[i].matrix_stride = blob_read_uint32(metadata); uniforms[i].row_major = blob_read_uint32(metadata); + uniforms[i].is_bindless = blob_read_uint32(metadata); uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata); uniforms[i].top_level_array_size = blob_read_uint32(metadata); uniforms[i].top_level_array_stride = blob_read_uint32(metadata); diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index e6c78bf69c3..c0e3ca45e56 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -1274,6 +1274,70 @@ _mesa_uniform_matrix(GLint location, GLsizei count, _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); } +/** + * Called via glUniformHandleui64*ARB() functions. + */ +extern "C" void +_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values, + struct gl_context *ctx, struct gl_shader_program *shProg) +{ + unsigned offset; + struct gl_uniform_storage *const uni = + validate_uniform_parameters(location, count, &offset, + ctx, shProg, "glUniformHandleui64*ARB"); + if (uni == NULL) + return; + + if (!uni->is_bindless) { + /* From section "Errors" of the ARB_bindless_texture spec: + * + * "The error INVALID_OPERATION is generated by + * UniformHandleui64{v}ARB if the sampler or image uniform being + * updated has the "bound_sampler" or "bound_image" layout qualifier." + * + * From section 4.4.6 of the ARB_bindless_texture spec: + * + * "In the absence of these qualifiers, sampler and image uniforms are + * considered "bound". Additionally, if GL_ARB_bindless_texture is not + * enabled, these uniforms are considered "bound"." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniformHandleui64*ARB(non-bindless sampler/image uniform)"); + return; + } + + const unsigned components = uni->type->vector_elements; + const int size_mul = 2; + + if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) { + log_uniform(values, GLSL_TYPE_UINT64, components, 1, count, + false, shProg, location, uni); + } + + /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says: + * + * "When loading N elements starting at an arbitrary position k in a + * uniform declared as an array, elements k through k + N - 1 in the + * array will be replaced with the new values. Values for any array + * element that exceeds the highest array element index used, as + * reported by GetActiveUniform, will be ignored by the GL." + * + * Clamp 'count' to a valid value. Note that for non-arrays a count > 1 + * will have already generated an error. + */ + if (uni->array_elements != 0) { + count = MIN2(count, (int) (uni->array_elements - offset)); + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); + + /* Store the data in the "actual type" backing storage for the uniform. + */ + memcpy(&uni->storage[size_mul * components * offset], values, + sizeof(uni->storage[0]) * components * count * size_mul); + + _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); +} extern "C" bool _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index a9e7cda17c2..67c238e4f37 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -297,12 +297,17 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value) void GLAPIENTRY _mesa_UniformHandleui64ARB(GLint location, GLuint64 value) { + GET_CURRENT_CONTEXT(ctx); + _mesa_uniform_handle(location, 1, &value, ctx, ctx->_Shader->ActiveProgram); } void GLAPIENTRY _mesa_UniformHandleui64vARB(GLint location, GLsizei count, const GLuint64 *value) { + GET_CURRENT_CONTEXT(ctx); + _mesa_uniform_handle(location, count, value, ctx, + ctx->_Shader->ActiveProgram); } @@ -501,12 +506,22 @@ void GLAPIENTRY _mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location, GLuint64 value) { + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformHandleui64ARB"); + _mesa_uniform_handle(location, 1, &value, ctx, shProg); } void GLAPIENTRY _mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location, GLsizei count, const GLuint64 *values) { + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformHandleui64vARB"); + _mesa_uniform_handle(location, count, values, ctx, shProg); } diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h index 553e8717ba0..bd42b4f0360 100644 --- a/src/mesa/main/uniforms.h +++ b/src/mesa/main/uniforms.h @@ -452,6 +452,10 @@ _mesa_uniform_matrix(GLint location, GLsizei count, struct gl_context *, struct gl_shader_program *, GLuint cols, GLuint rows, enum glsl_base_type basicType); +void +_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values, + struct gl_context *, struct gl_shader_program *); + void _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, GLsizei bufSize, enum glsl_base_type returnType, -- 2.30.2