aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2020-05-09 20:57:25 -0400
committerMarge Bot <[email protected]>2020-06-02 20:01:18 +0000
commit0c0803c32fd5b1c6cc037372990d2b6f84762135 (patch)
treea7856dac70d45d99c107866ee50ea18419799132 /src/compiler/glsl
parent11929895332213363628d632f7f9f6d79b5124d1 (diff)
glsl: lower the precision of imageLoad
Acked-by: Alyssa Rosenzweig <[email protected]> Reviewed-by: Rob Clark <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5002>
Diffstat (limited to 'src/compiler/glsl')
-rw-r--r--src/compiler/glsl/lower_builtins.cpp5
-rw-r--r--src/compiler/glsl/lower_precision.cpp54
-rw-r--r--src/compiler/glsl/tests/lower_precision_test.py72
3 files changed, 125 insertions, 6 deletions
diff --git a/src/compiler/glsl/lower_builtins.cpp b/src/compiler/glsl/lower_builtins.cpp
index e7130df7ac6..7b5ac204e65 100644
--- a/src/compiler/glsl/lower_builtins.cpp
+++ b/src/compiler/glsl/lower_builtins.cpp
@@ -52,7 +52,10 @@ lower_builtins(exec_list *instructions)
ir_visitor_status
lower_builtins_visitor::visit_leave(ir_call *ir)
{
- if (!ir->callee->is_builtin())
+ /* lower_precision() also inlines some intrinsics, which can't be inlined
+ * further.
+ */
+ if (!ir->callee->is_builtin() || ir->callee->is_intrinsic())
return visit_continue;
ir->generate_inline(ir);
diff --git a/src/compiler/glsl/lower_precision.cpp b/src/compiler/glsl/lower_precision.cpp
index b410e3290a2..faa990703e6 100644
--- a/src/compiler/glsl/lower_precision.cpp
+++ b/src/compiler/glsl/lower_precision.cpp
@@ -163,6 +163,7 @@ find_lowerable_rvalues_visitor::can_lower_type(const glsl_type *type) const
*/
case GLSL_TYPE_BOOL:
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
return true;
case GLSL_TYPE_FLOAT:
@@ -416,6 +417,38 @@ static bool
is_lowerable_builtin(ir_call *ir,
const struct set *lowerable_rvalues)
{
+ /* The intrinsic call is inside the wrapper imageLoad function that will
+ * be inlined. We have to handle both of them.
+ */
+ if (ir->callee->intrinsic_id == ir_intrinsic_image_load ||
+ (ir->callee->is_builtin() &&
+ !strcmp(ir->callee_name(), "imageLoad"))) {
+ ir_rvalue *param = (ir_rvalue*)ir->actual_parameters.get_head();
+ ir_variable *resource = param->variable_referenced();
+
+ assert(ir->callee->return_precision == GLSL_PRECISION_NONE);
+ assert(resource->type->without_array()->is_image());
+
+ /* GLSL ES 3.20 requires that images have a precision modifier, but if
+ * you set one, it doesn't do anything, because all intrinsics are
+ * defined with highp. This seems to be a spec bug.
+ *
+ * In theory we could set the return value to mediump if the image
+ * format has a lower precision. This appears to be the most sensible
+ * thing to do.
+ */
+ const struct util_format_description *desc =
+ util_format_description(resource->data.image_format);
+ unsigned i =
+ util_format_get_first_non_void_channel(resource->data.image_format);
+
+ if (desc->channel[i].pure_integer ||
+ desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
+ return desc->channel[i].size <= 16;
+ else
+ return desc->channel[i].size <= 10; /* unorm/snorm */
+ }
+
if (!ir->callee->is_builtin())
return false;
@@ -728,17 +761,28 @@ find_precision_visitor::visit_enter(ir_call *ir)
{
ir_rvalue_enter_visitor::visit_enter(ir);
+ ir_variable *return_var =
+ ir->return_deref ? ir->return_deref->variable_referenced() : NULL;
+
+ /* Don't do anything for image_load here. We have only changed the return
+ * value to mediump/lowp, so that following instructions can use reduced
+ * precision.
+ *
+ * The return value type of the intrinsic itself isn't changed here, but
+ * can be changed in NIR if all users use the *2*mp opcode.
+ */
+ if (ir->callee->intrinsic_id == ir_intrinsic_image_load)
+ return visit_continue;
+
/* If this is a call to a builtin and the find_lowerable_rvalues_visitor
* overrode the precision of the temporary return variable, then we can
* replace the builtin implementation with a lowered version.
*/
if (!ir->callee->is_builtin() ||
- ir->return_deref == NULL ||
- (ir->return_deref->variable_referenced()->data.precision !=
- GLSL_PRECISION_MEDIUM &&
- ir->return_deref->variable_referenced()->data.precision !=
- GLSL_PRECISION_LOW))
+ return_var == NULL ||
+ (return_var->data.precision != GLSL_PRECISION_MEDIUM &&
+ return_var->data.precision != GLSL_PRECISION_LOW))
return visit_continue;
ir->callee = map_builtin(ir->callee);
diff --git a/src/compiler/glsl/tests/lower_precision_test.py b/src/compiler/glsl/tests/lower_precision_test.py
index 3626d8d2a4b..45175262878 100644
--- a/src/compiler/glsl/tests/lower_precision_test.py
+++ b/src/compiler/glsl/tests/lower_precision_test.py
@@ -971,6 +971,78 @@ TESTS = [
}
""",
r'\(expression +u16vec4 +/.*\(tex +u16vec4 +'),
+ Test("f32 image array",
+ """
+ #version 320 es
+ precision mediump float;
+
+ layout(rgba16f) readonly uniform mediump image2D img[2];
+ // highp shouldn't affect the return value of imageLoad
+ uniform highp ivec2 coord;
+ uniform float divisor;
+
+ out highp vec4 color;
+
+ void main()
+ {
+ color = imageLoad(img[1], coord) / divisor;
+ }
+ """,
+ r'\(expression +f16vec4 +/'),
+ Test("f32 image load",
+ """
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ layout(rgba16f) readonly uniform mediump image2D img;
+ uniform ivec2 coord;
+ uniform float divisor;
+
+ out highp vec4 color;
+
+ void main()
+ {
+ color = imageLoad(img, coord) / divisor;
+ }
+ """,
+ r'\(expression +f16vec4 +/'),
+ Test("i32 image load",
+ """
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ layout(rgba16i) readonly uniform mediump iimage2D img;
+ uniform ivec2 coord;
+ uniform int divisor;
+
+ out highp ivec4 color;
+
+ void main()
+ {
+ color = imageLoad(img, coord) / divisor;
+ }
+ """,
+ r'\(expression +i16vec4 +/'),
+ Test("u32 image load",
+ """
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ layout(rgba16ui) readonly uniform mediump uimage2D img;
+ uniform ivec2 coord;
+ uniform uint divisor;
+
+ out highp uvec4 color;
+
+ void main()
+ {
+ color = imageLoad(img, coord) / divisor;
+ }
+ """,
+ r'\(expression +u16vec4 +/'),
Test("f32 expression in lvalue",
"""
uniform mediump float a, b;