intel/fs,vec4: Clean up a repeated pattern with SSBOs

Everywhere we handle SSBO intrinsics, we have exactly the same pattern
for computing the index so we may as well make a helper for it.  We also
add a get_nir_src_imm to vec4 and use it for SSBO offsets.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Jason Ekstrand
2018-10-20 10:05:33 -05:00
parent c472ad82e4
commit 6b2918709a
4 changed files with 85 additions and 166 deletions

View File

@@ -218,6 +218,8 @@ public:
nir_intrinsic_instr *instr); nir_intrinsic_instr *instr);
fs_reg get_nir_image_intrinsic_image(const brw::fs_builder &bld, fs_reg get_nir_image_intrinsic_image(const brw::fs_builder &bld,
nir_intrinsic_instr *instr); nir_intrinsic_instr *instr);
fs_reg get_nir_ssbo_intrinsic_index(const brw::fs_builder &bld,
nir_intrinsic_instr *instr);
void nir_emit_intrinsic(const brw::fs_builder &bld, void nir_emit_intrinsic(const brw::fs_builder &bld,
nir_intrinsic_instr *instr); nir_intrinsic_instr *instr);
void nir_emit_tes_intrinsic(const brw::fs_builder &bld, void nir_emit_tes_intrinsic(const brw::fs_builder &bld,

View File

@@ -3762,6 +3762,37 @@ fs_visitor::get_nir_image_intrinsic_image(const brw::fs_builder &bld,
return bld.emit_uniformize(image); return bld.emit_uniformize(image);
} }
fs_reg
fs_visitor::get_nir_ssbo_intrinsic_index(const brw::fs_builder &bld,
nir_intrinsic_instr *instr)
{
/* SSBO stores are weird in that their index is in src[1] */
const unsigned src = instr->intrinsic == nir_intrinsic_store_ssbo ? 1 : 0;
nir_const_value *const_uniform_block =
nir_src_as_const_value(instr->src[src]);
fs_reg surf_index;
if (const_uniform_block) {
unsigned index = stage_prog_data->binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(prog_data, index);
} else {
surf_index = vgrf(glsl_type::uint_type);
bld.ADD(surf_index, get_nir_src(instr->src[src]),
brw_imm_ud(stage_prog_data->binding_table.ssbo_start));
/* Assume this may touch any UBO. It would be nice to provide
* a tighter bound, but the array information is already lowered away.
*/
brw_mark_surface_used(prog_data,
stage_prog_data->binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
return surf_index;
}
static unsigned static unsigned
image_intrinsic_coord_components(nir_intrinsic_instr *instr) image_intrinsic_coord_components(nir_intrinsic_instr *instr)
{ {
@@ -4139,35 +4170,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
case nir_intrinsic_load_ssbo: { case nir_intrinsic_load_ssbo: {
assert(devinfo->gen >= 7); assert(devinfo->gen >= 7);
nir_const_value *const_uniform_block = fs_reg surf_index = get_nir_ssbo_intrinsic_index(bld, instr);
nir_src_as_const_value(instr->src[0]); fs_reg offset_reg = get_nir_src_imm(instr->src[1]);
fs_reg surf_index;
if (const_uniform_block) {
unsigned index = stage_prog_data->binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(prog_data, index);
} else {
surf_index = vgrf(glsl_type::uint_type);
bld.ADD(surf_index, get_nir_src(instr->src[0]),
brw_imm_ud(stage_prog_data->binding_table.ssbo_start));
/* Assume this may touch any UBO. It would be nice to provide
* a tighter bound, but the array information is already lowered away.
*/
brw_mark_surface_used(prog_data,
stage_prog_data->binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
fs_reg offset_reg;
nir_const_value *const_offset = nir_src_as_const_value(instr->src[1]);
if (const_offset) {
offset_reg = brw_imm_ud(const_offset->u32[0]);
} else {
offset_reg = retype(get_nir_src(instr->src[1]), BRW_REGISTER_TYPE_UD);
}
/* Read the vector */ /* Read the vector */
do_untyped_vector_read(bld, dest, surf_index, offset_reg, do_untyped_vector_read(bld, dest, surf_index, offset_reg,
@@ -4182,24 +4186,7 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
if (stage == MESA_SHADER_FRAGMENT) if (stage == MESA_SHADER_FRAGMENT)
brw_wm_prog_data(prog_data)->has_side_effects = true; brw_wm_prog_data(prog_data)->has_side_effects = true;
/* Block index */ fs_reg surf_index = get_nir_ssbo_intrinsic_index(bld, instr);
fs_reg surf_index;
nir_const_value *const_uniform_block =
nir_src_as_const_value(instr->src[1]);
if (const_uniform_block) {
unsigned index = stage_prog_data->binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(prog_data, index);
} else {
surf_index = vgrf(glsl_type::uint_type);
bld.ADD(surf_index, get_nir_src(instr->src[1]),
brw_imm_ud(stage_prog_data->binding_table.ssbo_start));
brw_mark_surface_used(prog_data,
stage_prog_data->binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
/* Value */ /* Value */
fs_reg val_reg = get_nir_src(instr->src[0]); fs_reg val_reg = get_nir_src(instr->src[0]);
@@ -4836,26 +4823,7 @@ fs_visitor::nir_emit_ssbo_atomic(const fs_builder &bld,
if (nir_intrinsic_infos[instr->intrinsic].has_dest) if (nir_intrinsic_infos[instr->intrinsic].has_dest)
dest = get_nir_dest(instr->dest); dest = get_nir_dest(instr->dest);
fs_reg surface; fs_reg surface = get_nir_ssbo_intrinsic_index(bld, instr);
nir_const_value *const_surface = nir_src_as_const_value(instr->src[0]);
if (const_surface) {
unsigned surf_index = stage_prog_data->binding_table.ssbo_start +
const_surface->u32[0];
surface = brw_imm_ud(surf_index);
brw_mark_surface_used(prog_data, surf_index);
} else {
surface = vgrf(glsl_type::uint_type);
bld.ADD(surface, get_nir_src(instr->src[0]),
brw_imm_ud(stage_prog_data->binding_table.ssbo_start));
/* Assume this may touch any SSBO. This is the same we do for other
* UBO/SSBO accesses with non-constant surface.
*/
brw_mark_surface_used(prog_data,
stage_prog_data->binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
fs_reg offset = get_nir_src(instr->src[1]); fs_reg offset = get_nir_src(instr->src[1]);
fs_reg data1; fs_reg data1;
if (op != BRW_AOP_INC && op != BRW_AOP_DEC && op != BRW_AOP_PREDEC) if (op != BRW_AOP_INC && op != BRW_AOP_DEC && op != BRW_AOP_PREDEC)
@@ -4886,26 +4854,7 @@ fs_visitor::nir_emit_ssbo_atomic_float(const fs_builder &bld,
if (nir_intrinsic_infos[instr->intrinsic].has_dest) if (nir_intrinsic_infos[instr->intrinsic].has_dest)
dest = get_nir_dest(instr->dest); dest = get_nir_dest(instr->dest);
fs_reg surface; fs_reg surface = get_nir_ssbo_intrinsic_index(bld, instr);
nir_const_value *const_surface = nir_src_as_const_value(instr->src[0]);
if (const_surface) {
unsigned surf_index = stage_prog_data->binding_table.ssbo_start +
const_surface->u32[0];
surface = brw_imm_ud(surf_index);
brw_mark_surface_used(prog_data, surf_index);
} else {
surface = vgrf(glsl_type::uint_type);
bld.ADD(surface, get_nir_src(instr->src[0]),
brw_imm_ud(stage_prog_data->binding_table.ssbo_start));
/* Assume this may touch any SSBO. This is the same we do for other
* UBO/SSBO accesses with non-constant surface.
*/
brw_mark_surface_used(prog_data,
stage_prog_data->binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
fs_reg offset = get_nir_src(instr->src[1]); fs_reg offset = get_nir_src(instr->src[1]);
fs_reg data1 = get_nir_src(instr->src[2]); fs_reg data1 = get_nir_src(instr->src[2]);
fs_reg data2; fs_reg data2;

View File

@@ -338,6 +338,7 @@ public:
virtual void nir_emit_block(nir_block *block); virtual void nir_emit_block(nir_block *block);
virtual void nir_emit_instr(nir_instr *instr); virtual void nir_emit_instr(nir_instr *instr);
virtual void nir_emit_load_const(nir_load_const_instr *instr); virtual void nir_emit_load_const(nir_load_const_instr *instr);
src_reg get_nir_ssbo_intrinsic_index(nir_intrinsic_instr *instr);
virtual void nir_emit_intrinsic(nir_intrinsic_instr *instr); virtual void nir_emit_intrinsic(nir_intrinsic_instr *instr);
virtual void nir_emit_alu(nir_alu_instr *instr); virtual void nir_emit_alu(nir_alu_instr *instr);
virtual void nir_emit_jump(nir_jump_instr *instr); virtual void nir_emit_jump(nir_jump_instr *instr);
@@ -354,6 +355,7 @@ public:
unsigned num_components = 4); unsigned num_components = 4);
src_reg get_nir_src(const nir_src &src, src_reg get_nir_src(const nir_src &src,
unsigned num_components = 4); unsigned num_components = 4);
src_reg get_nir_src_imm(const nir_src &src);
src_reg get_indirect_offset(nir_intrinsic_instr *instr); src_reg get_indirect_offset(nir_intrinsic_instr *instr);
dst_reg *nir_locals; dst_reg *nir_locals;

View File

@@ -252,6 +252,16 @@ vec4_visitor::get_nir_src(const nir_src &src, unsigned num_components)
return get_nir_src(src, nir_type_int32, num_components); return get_nir_src(src, nir_type_int32, num_components);
} }
src_reg
vec4_visitor::get_nir_src_imm(const nir_src &src)
{
assert(nir_src_num_components(src) == 1);
assert(nir_src_bit_size(src) == 32);
nir_const_value *const_val = nir_src_as_const_value(src);
return const_val ? src_reg(brw_imm_d(const_val->i32[0])) :
get_nir_src(src, 1);
}
src_reg src_reg
vec4_visitor::get_indirect_offset(nir_intrinsic_instr *instr) vec4_visitor::get_indirect_offset(nir_intrinsic_instr *instr)
{ {
@@ -368,6 +378,34 @@ vec4_visitor::nir_emit_load_const(nir_load_const_instr *instr)
nir_ssa_values[instr->def.index] = reg; nir_ssa_values[instr->def.index] = reg;
} }
src_reg
vec4_visitor::get_nir_ssbo_intrinsic_index(nir_intrinsic_instr *instr)
{
/* SSBO stores are weird in that their index is in src[1] */
const unsigned src = instr->intrinsic == nir_intrinsic_store_ssbo ? 1 : 0;
src_reg surf_index;
nir_const_value *const_uniform_block =
nir_src_as_const_value(instr->src[src]);
if (const_uniform_block) {
unsigned index = prog_data->base.binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(&prog_data->base, index);
} else {
surf_index = src_reg(this, glsl_type::uint_type);
emit(ADD(dst_reg(surf_index), get_nir_src(instr->src[src], 1),
brw_imm_ud(prog_data->base.binding_table.ssbo_start)));
surf_index = emit_uniformize(surf_index);
brw_mark_surface_used(&prog_data->base,
prog_data->base.binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
return surf_index;
}
void void
vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
{ {
@@ -470,34 +508,9 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
case nir_intrinsic_store_ssbo: { case nir_intrinsic_store_ssbo: {
assert(devinfo->gen >= 7); assert(devinfo->gen >= 7);
/* Block index */ src_reg surf_index = get_nir_ssbo_intrinsic_index(instr);
src_reg surf_index; src_reg offset_reg = retype(get_nir_src_imm(instr->src[2]),
nir_const_value *const_uniform_block = BRW_REGISTER_TYPE_UD);
nir_src_as_const_value(instr->src[1]);
if (const_uniform_block) {
unsigned index = prog_data->base.binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(&prog_data->base, index);
} else {
surf_index = src_reg(this, glsl_type::uint_type);
emit(ADD(dst_reg(surf_index), get_nir_src(instr->src[1], 1),
brw_imm_ud(prog_data->base.binding_table.ssbo_start)));
surf_index = emit_uniformize(surf_index);
brw_mark_surface_used(&prog_data->base,
prog_data->base.binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
/* Offset */
src_reg offset_reg;
nir_const_value *const_offset = nir_src_as_const_value(instr->src[2]);
if (const_offset) {
offset_reg = brw_imm_ud(const_offset->u32[0]);
} else {
offset_reg = get_nir_src(instr->src[2], 1);
}
/* Value */ /* Value */
src_reg val_reg = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_F, 4); src_reg val_reg = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_F, 4);
@@ -632,37 +645,9 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
case nir_intrinsic_load_ssbo: { case nir_intrinsic_load_ssbo: {
assert(devinfo->gen >= 7); assert(devinfo->gen >= 7);
nir_const_value *const_uniform_block = src_reg surf_index = get_nir_ssbo_intrinsic_index(instr);
nir_src_as_const_value(instr->src[0]); src_reg offset_reg = retype(get_nir_src_imm(instr->src[1]),
BRW_REGISTER_TYPE_UD);
src_reg surf_index;
if (const_uniform_block) {
unsigned index = prog_data->base.binding_table.ssbo_start +
const_uniform_block->u32[0];
surf_index = brw_imm_ud(index);
brw_mark_surface_used(&prog_data->base, index);
} else {
surf_index = src_reg(this, glsl_type::uint_type);
emit(ADD(dst_reg(surf_index), get_nir_src(instr->src[0], 1),
brw_imm_ud(prog_data->base.binding_table.ssbo_start)));
surf_index = emit_uniformize(surf_index);
/* Assume this may touch any UBO. It would be nice to provide
* a tighter bound, but the array information is already lowered away.
*/
brw_mark_surface_used(&prog_data->base,
prog_data->base.binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
src_reg offset_reg;
nir_const_value *const_offset = nir_src_as_const_value(instr->src[1]);
if (const_offset) {
offset_reg = brw_imm_ud(const_offset->u32[0]);
} else {
offset_reg = get_nir_src(instr->src[1], 1);
}
/* Read the vector */ /* Read the vector */
const vec4_builder bld = vec4_builder(this).at_end() const vec4_builder bld = vec4_builder(this).at_end()
@@ -922,26 +907,7 @@ vec4_visitor::nir_emit_ssbo_atomic(int op, nir_intrinsic_instr *instr)
if (nir_intrinsic_infos[instr->intrinsic].has_dest) if (nir_intrinsic_infos[instr->intrinsic].has_dest)
dest = get_nir_dest(instr->dest); dest = get_nir_dest(instr->dest);
src_reg surface; src_reg surface = get_nir_ssbo_intrinsic_index(instr);
nir_const_value *const_surface = nir_src_as_const_value(instr->src[0]);
if (const_surface) {
unsigned surf_index = prog_data->base.binding_table.ssbo_start +
const_surface->u32[0];
surface = brw_imm_ud(surf_index);
brw_mark_surface_used(&prog_data->base, surf_index);
} else {
surface = src_reg(this, glsl_type::uint_type);
emit(ADD(dst_reg(surface), get_nir_src(instr->src[0]),
brw_imm_ud(prog_data->base.binding_table.ssbo_start)));
/* Assume this may touch any UBO. This is the same we do for other
* UBO/SSBO accesses with non-constant surface.
*/
brw_mark_surface_used(&prog_data->base,
prog_data->base.binding_table.ssbo_start +
nir->info.num_ssbos - 1);
}
src_reg offset = get_nir_src(instr->src[1], 1); src_reg offset = get_nir_src(instr->src[1], 1);
src_reg data1; src_reg data1;
if (op != BRW_AOP_INC && op != BRW_AOP_DEC && op != BRW_AOP_PREDEC) if (op != BRW_AOP_INC && op != BRW_AOP_DEC && op != BRW_AOP_PREDEC)