Discussion:
[PATCH 2/2] glsl: Add support for constant expression evaluation on round(), roundEven().
Eric Anholt
2011-10-18 19:31:11 UTC
Permalink
v2: Avoid the C99 rounding functions, because I don't trust
get/setting the C99 rounding mode from inside our library not having
other side effects. Instead, open-code roundEven() behavior around
Mesa's IROUND, which we're already testing for C99 rounding mode
safety.

Fixes glsl-1.30/compiler/built-in-functions/round*
---
src/glsl/ir_constant_expression.cpp | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index b3fe6cf..83f084d 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -39,6 +39,25 @@
#include "ir_visitor.h"
#include "glsl_types.h"

+/* Using C99 rounding functions for roundToEven() implementation is
+ * difficult, because round(), rint, and nearbyint() are affected by
+ * fesetenv(), which the application may have done for its own
+ * purposes. Mesa's IROUND macro is close to what we want, but it
+ * rounds away from 0 on n + 0.5.
+ */
+static int
+round_to_even(float val)
+{
+ int rounded = IROUND(val);
+
+ if (val - floor(val) == 0.5) {
+ if (rounded % 2 != 0)
+ rounded += val > 0 ? -1 : 1;
+ }
+
+ return rounded;
+}
+
static float
dot(ir_constant *op0, ir_constant *op1)
{
@@ -196,6 +215,13 @@ ir_expression::constant_expression_value()
}
break;

+ case ir_unop_round_even:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = round_to_even(op[0]->value.f[c]);
+ }
+ break;
+
case ir_unop_ceil:
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
for (unsigned c = 0; c < op[0]->type->components(); c++) {
@@ -1324,6 +1350,9 @@ ir_call::constant_expression_value()
* op[1]->value.f[c];
}
}
+ } else if (strcmp(callee, "round") == 0 ||
+ strcmp(callee, "roundEven") == 0) {
+ expr = new(mem_ctx) ir_expression(ir_unop_round_even, op[0]);
} else if (strcmp(callee, "sign") == 0) {
expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL);
} else if (strcmp(callee, "sin") == 0) {
--
1.7.7
Brian Paul
2011-10-18 19:48:10 UTC
Permalink
"The version of PixelStore that takes a floating-point value
may be used to set any type of parameter; if the parameter is
boolean, then it is set to FALSE if the passed value is 0.0
and TRUE otherwise, while if the parameter is an integer, then
the passed value is rounded to the nearest integer."
Fixes piglit roundmode-pixelstore.
---
src/mesa/main/pixelstore.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/mesa/main/pixelstore.c b/src/mesa/main/pixelstore.c
index d957950..8147449 100644
--- a/src/mesa/main/pixelstore.c
+++ b/src/mesa/main/pixelstore.c
@@ -214,7 +214,7 @@ _mesa_PixelStorei( GLenum pname, GLint param )
void GLAPIENTRY
_mesa_PixelStoref( GLenum pname, GLfloat param )
{
- _mesa_PixelStorei( pname, (GLint) param );
+ _mesa_PixelStorei( pname, IROUND(param) );
}
Maybe tag this as a candidate for the 7.11 branch (though it's pretty
obscure).

Reviewed-by: Brian Paul <***@vmware.com>
Kenneth Graunke
2011-10-23 00:39:53 UTC
Permalink
Post by Eric Anholt
v2: Avoid the C99 rounding functions, because I don't trust
get/setting the C99 rounding mode from inside our library not having
other side effects. Instead, open-code roundEven() behavior around
Mesa's IROUND, which we're already testing for C99 rounding mode
safety.
Fixes glsl-1.30/compiler/built-in-functions/round*
For the series:
Reviewed-by: Kenneth Graunke <***@whitecape.org>

Loading...