glsl: lower the precision of imageLoad
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Reviewed-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5002>
This commit is contained in:
parent
1192989533
commit
0c0803c32f
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue