--- src/mesa/drivers/dri/i965/brw_vec4.h | 1 + src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 76 ++++++++++++++++++++++++++ 2 files changed, 77 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h index 870946b..d5f5ef9 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.h +++ b/src/mesa/drivers/dri/i965/brw_vec4.h @@ -384,6 +384,7 @@ public: void visit_atomic_counter_intrinsic(ir_call *ir); void visit_store_ssbo_intrinsic(ir_call *ir); + void visit_load_ssbo_intrinsic(ir_call *ir); protected: void emit_vertex(); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index dbdfdd3..a5591e6 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -2649,6 +2649,80 @@ vec4_visitor::visit_store_ssbo_intrinsic(ir_call *ir) } void +vec4_visitor::visit_load_ssbo_intrinsic(ir_call *ir) +{ + const glsl_type *type = ir->return_deref->var->type; + assert(type->is_vector() || type->is_scalar()); + + /* Block */ + exec_node *param = ir->actual_parameters.get_head(); + ir_rvalue *block_param = ((ir_instruction *)param)->as_rvalue(); + ir_constant *const_uniform_block = block_param->as_constant(); + src_reg surf_index; + + /* Storage for our result. Ideally for an assignment we'd be using + * the actual storage for the result here, instead. + */ + dst_reg result_dst = get_assignment_lhs(ir->return_deref, this); + src_reg result_src(result_dst); + this->result = result_src; + + if (const_uniform_block) { + /* The block index is a constant, so just emit the binding table entry + * as an immediate. + */ + unsigned index = prog_data->base.binding_table.ubo_start + + const_uniform_block->value.u[0]; + surf_index = src_reg(index); + + brw_mark_surface_used(&prog_data->base, index); + } else { + /* The block index is not a constant. Evaluate the index expression + * per-channel and add the base UBO index; we have to select a value + * from any live channel. + */ + block_param->accept(this); + src_reg block_reg = this->result; + + surf_index = src_reg(this, glsl_type::uint_type); + emit(ADD(dst_reg(surf_index), block_reg, + src_reg(prog_data->base.binding_table.ubo_start))); + emit_uniformize(dst_reg(surf_index), 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.ubo_start + + shader_prog->NumUniformBlocks - 1); + } + + /* Offset */ + param = param->get_next(); + ir_rvalue *offset_param = ((ir_instruction *)param)->as_rvalue(); + offset_param->accept(this); + src_reg offset = src_reg(this, glsl_type::uint_type); + emit(MOV(dst_reg(offset), this->result)); + + /* Read the vector */ + const vec4_builder bld = vec4_builder(this).at_end() + .annotate(current_annotation, base_ir); + + src_reg read_result = emit_untyped_read(bld, surf_index, offset, + 1 /* dims */, 4 /* size*/, + BRW_PREDICATE_NONE); + read_result.type = result_dst.type; + read_result.swizzle = brw_swizzle_for_size(type->vector_elements); + + /* SSBO/UBO bools are any nonzero int. We need to convert them to 0/~0. */ + if (type->base_type == GLSL_TYPE_BOOL) { + emit(CMP(result_dst, read_result, src_reg(0u), BRW_CONDITIONAL_NZ)); + } else { + emit(MOV(result_dst, read_result)); + } +} + +void vec4_visitor::visit(ir_call *ir) { const char *callee = ir->callee->function_name(); @@ -2659,6 +2733,8 @@ vec4_visitor::visit(ir_call *ir) visit_atomic_counter_intrinsic(ir); } else if (!strcmp("__intrinsic_store_ssbo", callee)) { visit_store_ssbo_intrinsic(ir); + } else if (!strcmp("__intrinsic_load_ssbo", callee)) { + visit_load_ssbo_intrinsic(ir); } else { unreachable("Unsupported intrinsic."); } -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev