From 83e74d7dc14ee0f31652cd2a6c0bb66380458f2b Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 18 May 2017 11:43:53 +0200 Subject: [PATCH] mesa/main: Clamp GetUniformuiv values to be >= 0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Section 2.2.2 (Data Conversions For State Query Commands) of the OpenGL 4.5 October 24th 2016 specification says: "If a command returning unsigned integer data is called, such as GetSamplerParameterIuiv, negative values are clamped to zero." v2: uint to int conversion should clamp to INT_MAX (Nicolai) v3 (Iago) - Add conversions conversions from 64-bit integer paths - Rebase on master v4: - need unsigned rounding for float/double->uint conversions (Nicolai) - use round{f}() instead of IROUND() macros (Iago) Fixes: KHR-GL45.gpu_shader_fp64.state_query Reviewed-by: Nicolai Hähnle (v2) Reviewed-by: Matt Turner --- src/mesa/main/uniform_query.cpp | 62 +++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index e7010adeca0..314f7d8a1b0 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -353,16 +353,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, * slower convert-and-copy process. */ if (returnType == uni->type->base_type || - ((returnType == GLSL_TYPE_INT || - returnType == GLSL_TYPE_UINT) && - (uni->type->base_type == GLSL_TYPE_INT || - uni->type->base_type == GLSL_TYPE_UINT || - uni->type->is_sampler() || - uni->type->is_image())) || - ((returnType == GLSL_TYPE_UINT64 || - returnType == GLSL_TYPE_INT64) && - (uni->type->base_type == GLSL_TYPE_UINT64 || - uni->type->base_type == GLSL_TYPE_INT64))) { + ((returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT) && + (uni->type->is_sampler() || uni->type->is_image()))) { memcpy(paramsOut, src, bytes); } else { union gl_constant_value *const dst = @@ -460,7 +452,6 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, break; case GLSL_TYPE_INT: - case GLSL_TYPE_UINT: switch (uni->type->base_type) { case GLSL_TYPE_FLOAT: /* While the GL 3.2 core spec doesn't explicitly @@ -485,6 +476,9 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, case GLSL_TYPE_BOOL: dst[didx].i = src[sidx].i ? 1 : 0; break; + case GLSL_TYPE_UINT: + dst[didx].i = MIN2(src[sidx].i, INT_MAX); + break; case GLSL_TYPE_DOUBLE: { double tmp; memcpy(&tmp, &src[sidx].f, sizeof(tmp)); @@ -509,6 +503,52 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, } break; + case GLSL_TYPE_UINT: + switch (uni->type->base_type) { + case GLSL_TYPE_FLOAT: + /* The spec isn't terribly clear how to handle negative + * values with an unsigned return type. + * + * GL 4.5 section 2.2.2 ("Data Conversions for State + * Query Commands") says: + * + * "If a value is so large in magnitude that it cannot be + * represented by the returned data type, then the nearest + * value representable using the requested type is + * returned." + */ + dst[didx].u = src[sidx].f < 0.0f ? + 0u : (uint32_t) roundf(src[sidx].f); + break; + case GLSL_TYPE_BOOL: + dst[didx].i = src[sidx].i ? 1 : 0; + break; + case GLSL_TYPE_INT: + dst[didx].i = MAX2(src[sidx].i, 0); + break; + case GLSL_TYPE_DOUBLE: { + double tmp; + memcpy(&tmp, &src[sidx].f, sizeof(tmp)); + dst[didx].u = tmp < 0.0 ? 0u : (uint32_t) round(tmp); + break; + } + case GLSL_TYPE_UINT64: { + uint64_t tmp; + memcpy(&tmp, &src[sidx].u, sizeof(tmp)); + dst[didx].i = MIN2(tmp, INT_MAX); + break; + } + case GLSL_TYPE_INT64: { + int64_t tmp; + memcpy(&tmp, &src[sidx].i, sizeof(tmp)); + dst[didx].i = MAX2(tmp, 0); + break; + } + default: + unreachable("invalid uniform type"); + } + break; + case GLSL_TYPE_INT64: case GLSL_TYPE_UINT64: switch (uni->type->base_type) { -- 2.30.2