mesa: add support for glUniformHandleui64*ARB()
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 24 Feb 2017 18:24:56 +0000 (19:24 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Wed, 14 Jun 2017 08:04:36 +0000 (10:04 +0200)
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 <samuel.pitoiset@gmail.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/compiler/glsl/ir_uniform.h
src/compiler/glsl/link_uniforms.cpp
src/compiler/glsl/shader_cache.cpp
src/mesa/main/uniform_query.cpp
src/mesa/main/uniforms.c
src/mesa/main/uniforms.h

index b6aec7fc4affb8fe09eba613189e5cb6a91c82c5..9841df8cde11e9192daabf3298e99928ba5be231 100644 (file)
@@ -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
index b11739ce78a8a1ce37c9c5e2c1c5cd5bc70cb4b9..7c3ca75416d2b10b6424f3e8bfb6b10f51b930f6 100644 (file)
@@ -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 &&
index dd56501258c1e7b1139cebfa482719005eccf8d5..1ad8fdd62a408215e6593de1772fde67665965be 100644 (file)
@@ -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);
index e6c78bf69c3276f966f1b82b11466da1ecb01ef3..c0e3ca45e5616104909efdc880b4d52737762039 100644 (file)
@@ -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,
index a9e7cda17c27c63bad56400efac614a247ffbfd8..67c238e4f376f672c31ebe22c7eb7bc4fc917f2b 100644 (file)
@@ -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);
 }
 
 
index 553e8717ba0244f9aa0653d7e48f9fa2ef96a8c7..bd42b4f03605cc4976db9778681d96234984e67a 100644 (file)
@@ -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,