[Mesa-dev] [PATCH 38/74] i965/fs: Implement unsized array's length calculation
Iago Toral Quiroga
itoral at igalia.com
Thu May 14 07:06:41 PDT 2015
From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
---
src/mesa/drivers/dri/i965/brw_defines.h | 1 +
src/mesa/drivers/dri/i965/brw_fs.cpp | 1 +
src/mesa/drivers/dri/i965/brw_fs.h | 3 ++
.../dri/i965/brw_fs_channel_expressions.cpp | 2 +
src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 47 +++++++++++++++++++
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 54 ++++++++++++++++++++++
src/mesa/drivers/dri/i965/brw_shader.cpp | 3 ++
7 files changed, 111 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index bb2c12d..9e6e35a 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -953,6 +953,7 @@ enum opcode {
FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7,
FS_OPCODE_VARYING_PULL_CONSTANT_LOAD,
FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7,
+ FS_OPCODE_UNSIZED_ARRAY_LENGTH,
FS_OPCODE_MOV_DISPATCH_TO_FLAGS,
FS_OPCODE_DISCARD_JUMP,
FS_OPCODE_SET_OMASK,
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 1019670..e6f176c 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -1050,6 +1050,7 @@ fs_visitor::implied_mrf_writes(fs_inst *inst)
return 1;
case FS_OPCODE_FB_WRITE:
return 2;
+ case FS_OPCODE_UNSIZED_ARRAY_LENGTH:
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
case SHADER_OPCODE_GEN4_SCRATCH_READ:
return 1;
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 67d2df4..40b7ec2 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -578,6 +578,9 @@ private:
struct brw_reg *src);
void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
struct brw_reg sampler_index);
+ void generate_unsized_array_length(fs_inst *inst, struct brw_reg dst,
+ struct brw_reg src,
+ struct brw_reg surf_index);
void generate_math_gen6(fs_inst *inst,
struct brw_reg dst,
struct brw_reg src0,
diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
index b8ed6b6..7ffddc4 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
@@ -430,6 +430,8 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
case ir_triop_vector_insert:
case ir_quadop_bitfield_insert:
case ir_quadop_vector:
+ case ir_unop_ssbo_unsized_array_length:
+ case ir_triop_ssbo_unsized_array_length:
unreachable("should have been lowered");
case ir_unop_unpack_half_2x16_split_x:
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
index 5a71a9b..eb98b4b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
@@ -530,6 +530,50 @@ fs_generator::generate_math_g45(fs_inst *inst,
}
void
+fs_generator::generate_unsized_array_length(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg src,
+ struct brw_reg surf_index)
+{
+ assert(brw->gen >= 7);
+ assert(surf_index.file == BRW_IMMEDIATE_VALUE);
+
+ uint32_t simd_mode;
+ int rlen = 4;
+
+ switch (inst->exec_size) {
+ case 8:
+ simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
+ break;
+ case 16:
+ simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
+ break;
+ default:
+ unreachable("Invalid width for texture instruction");
+ }
+
+ if (simd_mode == BRW_SAMPLER_SIMD_MODE_SIMD16) {
+ rlen = 8;
+ dst = vec16(dst);
+ }
+
+ brw_SAMPLE(p,
+ retype(dst, BRW_REGISTER_TYPE_UW),
+ inst->base_mrf,
+ src,
+ surf_index.dw1.ud,
+ 0,
+ GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO,
+ rlen, /* response length */
+ inst->mlen,
+ inst->header_size > 0,
+ simd_mode,
+ BRW_SAMPLER_RETURN_FORMAT_SINT32);
+
+ brw_mark_surface_used(prog_data, surf_index.dw1.ud);
+}
+
+void
fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
struct brw_reg sampler_index)
{
@@ -1935,6 +1979,9 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
src[0].subnr = 4 * type_sz(src[0].type);
brw_MOV(p, dst, stride(src[0], 8, 4, 1));
break;
+ case FS_OPCODE_UNSIZED_ARRAY_LENGTH:
+ generate_unsized_array_length(inst, dst, src[0], src[1]);
+ break;
case SHADER_OPCODE_TEX:
case FS_OPCODE_TXB:
case SHADER_OPCODE_TXD:
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index a3c10cb..179b5af 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -1288,6 +1288,57 @@ fs_visitor::visit(ir_expression *ir)
emit_lrp(this->result, op[0], op[1], op[2]);
break;
+ case ir_triop_ssbo_unsized_array_length: {
+ ir_constant *const_uniform_block = ir->operands[0]->as_constant();
+ unsigned ubo_index = const_uniform_block->value.u[0];
+ ir_constant *const_offset_ir = ir->operands[1]->as_constant();
+ int const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0;
+ ir_constant *const_stride_ir = ir->operands[2]->as_constant();
+ unsigned unsized_array_stride = const_stride_ir ? const_stride_ir->value.u[0] : 1;
+ int reg_width = dispatch_width / 8;
+
+ assert(shader->base.UniformBlocks[ubo_index].IsBuffer);
+
+ /* Set LOD = 0 */
+ fs_reg source = fs_reg(0);
+
+ int mlen = 1 * reg_width;
+ fs_reg src_payload = fs_reg(GRF, alloc.allocate(mlen),
+ BRW_REGISTER_TYPE_UD, dispatch_width);
+ emit(LOAD_PAYLOAD(src_payload, &source, 1, 0));
+
+ fs_reg surf_index = fs_reg(prog_data->binding_table.ubo_start + ubo_index);
+ fs_reg buffer_size = vgrf(glsl_type::int_type);
+
+ fs_inst *inst = emit(FS_OPCODE_UNSIZED_ARRAY_LENGTH, buffer_size,
+ src_payload, surf_index);
+ inst->header_size = 0;
+ inst->base_mrf = -1;
+ inst->mlen = mlen;
+ inst->regs_written = 4 * reg_width;
+ emit(inst);
+
+ /* array.length() =
+ max((buffer_object_size - offset_of_array) / stride_of_array, 0) */
+ fs_reg temp = vgrf(glsl_type::float_type);
+ emit(ADD(buffer_size, buffer_size, fs_reg(-const_offset)));
+
+ emit(MOV(temp, buffer_size));
+
+ assert(unsized_array_stride > 0);
+
+ fs_reg stride = fs_reg((float)1/unsized_array_stride);
+ emit(MUL(temp, temp, stride));
+ emit(MOV(this->result, fs_reg(0)));
+ emit(CMP(reg_null_f, temp, fs_reg(0), BRW_CONDITIONAL_G));
+ emit(IF(BRW_PREDICATE_NORMAL));
+ {
+ emit(MOV(this->result, temp));
+ }
+ emit(BRW_OPCODE_ENDIF);
+ break;
+ }
+
case ir_triop_csel:
case ir_unop_interpolate_at_centroid:
case ir_binop_interpolate_at_offset:
@@ -1308,6 +1359,9 @@ fs_visitor::visit(ir_expression *ir)
case ir_unop_frexp_exp:
unreachable("fp64 todo");
break;
+ case ir_unop_ssbo_unsized_array_length:
+ unreachable("not reached: should be handled by lower_ubo_reference");
+ break;
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index ff95afa..4872b63 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -548,6 +548,9 @@ brw_instruction_name(enum opcode op)
case FS_OPCODE_PIXEL_Y:
return "pixel_y";
+ case FS_OPCODE_UNSIZED_ARRAY_LENGTH:
+ return "fs_unsized_array_length";
+
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
return "uniform_pull_const";
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7:
--
1.9.1
More information about the mesa-dev
mailing list