mesa: add support for glUniformHandleui64*ARB()
[mesa.git] / src / mesa / main / uniform_query.cpp
index 2fdbc83be24380ef4226561d2d06d32e081d2d66..c0e3ca45e5616104909efdc880b4d52737762039 100644 (file)
@@ -471,7 +471,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
                    *      a floating-point value is rounded to the
                    *      nearest integer..."
                    */
-                  dst[didx].i = IROUND(src[sidx].f);
+                  dst[didx].i = (int64_t) roundf(src[sidx].f);
                   break;
                case GLSL_TYPE_BOOL:
                   dst[didx].i = src[sidx].i ? 1 : 0;
@@ -482,7 +482,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
                case GLSL_TYPE_DOUBLE: {
                   double tmp;
                   memcpy(&tmp, &src[sidx].f, sizeof(tmp));
-                  dst[didx].i = IROUNDD(tmp);
+                  dst[didx].i = (int64_t) round(tmp);
                   break;
                }
                case GLSL_TYPE_UINT64: {
@@ -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,