Shader storage buffer objects (SSBO) require special handling: when we detect writes to any channel of a shader buffer variable we need to emit the corresponding write to memory. We will later add a lowering pass that detects these writes and injects ir_ssbo_store nodes in the IR so drivers can generate code for the memory writes. --- src/glsl/ir.h | 38 ++++++++++++++++++++++++++ src/glsl/ir_hierarchical_visitor.cpp | 18 ++++++++++++ src/glsl/ir_hierarchical_visitor.h | 2 ++ src/glsl/ir_hv_accept.cpp | 23 ++++++++++++++++ src/glsl/ir_print_visitor.cpp | 12 ++++++++ src/glsl/ir_print_visitor.h | 1 + src/glsl/ir_rvalue_visitor.cpp | 21 ++++++++++++++ src/glsl/ir_rvalue_visitor.h | 3 ++ src/glsl/ir_visitor.h | 2 ++ src/glsl/nir/glsl_to_nir.cpp | 7 +++++ src/mesa/drivers/dri/i965/brw_fs.h | 1 + src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 6 ++++ src/mesa/drivers/dri/i965/brw_vec4.h | 1 + src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 6 ++++ src/mesa/program/ir_to_mesa.cpp | 7 +++++ src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 7 +++++ 16 files changed, 155 insertions(+)
diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 093d9ad..6c326b3 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -78,6 +78,7 @@ enum ir_node_type { ir_type_discard, ir_type_emit_vertex, ir_type_end_primitive, + ir_type_ssbo_store, ir_type_max, /**< maximum ir_type enum number, for validation */ ir_type_unset = ir_type_max }; @@ -2406,6 +2407,43 @@ public: ir_rvalue *stream; }; +/** + * IR instruction to write to a shader storage buffer object (SSBO) + */ +class ir_ssbo_store : public ir_instruction { +public: + ir_ssbo_store(ir_rvalue *block, ir_rvalue *offset, ir_rvalue *val, + unsigned write_mask) + : ir_instruction(ir_type_ssbo_store), + block(block), offset(offset), val(val), write_mask(write_mask) + { + assert(block); + assert(offset); + assert(val); + assert(write_mask != 0); + } + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_ssbo_store *clone(void *mem_ctx, struct hash_table *ht) const + { + return new(mem_ctx) ir_ssbo_store(this->block->clone(mem_ctx, ht), + this->offset->clone(mem_ctx, ht), + this->val->clone(mem_ctx, ht), + this->write_mask); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + ir_rvalue *block; + ir_rvalue *offset; + ir_rvalue *val; + unsigned write_mask; +}; + /*@}*/ /** diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp index adb6294..1aa5cc0 100644 --- a/src/glsl/ir_hierarchical_visitor.cpp +++ b/src/glsl/ir_hierarchical_visitor.cpp @@ -349,6 +349,24 @@ ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir) return visit_continue; } +ir_visitor_status +ir_hierarchical_visitor::visit_enter(ir_ssbo_store *ir) +{ + if (this->callback_enter != NULL) + this->callback_enter(ir, this->data_enter); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit_leave(ir_ssbo_store *ir) +{ + if (this->callback_leave != NULL) + this->callback_leave(ir, this->data_leave); + + return visit_continue; +} + void ir_hierarchical_visitor::run(exec_list *instructions) { diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h index faa52fd..49dc37e 100644 --- a/src/glsl/ir_hierarchical_visitor.h +++ b/src/glsl/ir_hierarchical_visitor.h @@ -139,6 +139,8 @@ public: virtual ir_visitor_status visit_leave(class ir_emit_vertex *); virtual ir_visitor_status visit_enter(class ir_end_primitive *); virtual ir_visitor_status visit_leave(class ir_end_primitive *); + virtual ir_visitor_status visit_enter(class ir_ssbo_store *); + virtual ir_visitor_status visit_leave(class ir_ssbo_store *); /*@}*/ diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index be5b3ea..500ce4b 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -429,3 +429,26 @@ ir_end_primitive::accept(ir_hierarchical_visitor *v) return (s == visit_stop) ? s : v->visit_leave(this); } + + +ir_visitor_status +ir_ssbo_store::accept(ir_hierarchical_visitor *v) +{ + ir_visitor_status s = v->visit_enter(this); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + s = this->block->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + s = this->offset->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + s = this->val->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + + return (s == visit_stop) ? s : v->visit_leave(this); +} diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index ce411f2..be35a1d 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -576,3 +576,15 @@ ir_print_visitor::visit(ir_end_primitive *ir) fprintf(f, ")\n"); } + +void +ir_print_visitor::visit(ir_ssbo_store *ir) +{ + fprintf(f, "(ssbo_store "); + ir->block->accept(this); + ir->offset->accept(this); + ir->val->accept(this); + fprintf(f, "(writemask=0x%x)", ir->write_mask); + fprintf(f, ")\n"); + +} diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h index 98f041d..2e2a177 100644 --- a/src/glsl/ir_print_visitor.h +++ b/src/glsl/ir_print_visitor.h @@ -71,6 +71,7 @@ public: virtual void visit(ir_loop_jump *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_ssbo_store *); /*@}*/ private: diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp index 2eee3da..d5a586b 100644 --- a/src/glsl/ir_rvalue_visitor.cpp +++ b/src/glsl/ir_rvalue_visitor.cpp @@ -170,6 +170,15 @@ ir_rvalue_base_visitor::rvalue_visit(ir_end_primitive *ir) } ir_visitor_status +ir_rvalue_base_visitor::rvalue_visit(ir_ssbo_store *ir) +{ + handle_rvalue(&ir->block); + handle_rvalue(&ir->offset); + handle_rvalue(&ir->val); + return visit_continue; +} + +ir_visitor_status ir_rvalue_visitor::visit_leave(ir_expression *ir) { return rvalue_visit(ir); @@ -242,6 +251,12 @@ ir_rvalue_visitor::visit_leave(ir_end_primitive *ir) } ir_visitor_status +ir_rvalue_visitor::visit_leave(ir_ssbo_store *ir) +{ + return rvalue_visit(ir); +} + +ir_visitor_status ir_rvalue_enter_visitor::visit_enter(ir_expression *ir) { return rvalue_visit(ir); @@ -312,3 +327,9 @@ ir_rvalue_enter_visitor::visit_enter(ir_end_primitive *ir) { return rvalue_visit(ir); } + +ir_visitor_status +ir_rvalue_enter_visitor::visit_enter(ir_ssbo_store *ir) +{ + return rvalue_visit(ir); +} diff --git a/src/glsl/ir_rvalue_visitor.h b/src/glsl/ir_rvalue_visitor.h index 185c72a..a209b78 100644 --- a/src/glsl/ir_rvalue_visitor.h +++ b/src/glsl/ir_rvalue_visitor.h @@ -44,6 +44,7 @@ public: ir_visitor_status rvalue_visit(ir_texture *); ir_visitor_status rvalue_visit(ir_emit_vertex *); ir_visitor_status rvalue_visit(ir_end_primitive *); + ir_visitor_status rvalue_visit(ir_ssbo_store *); virtual void handle_rvalue(ir_rvalue **rvalue) = 0; }; @@ -63,6 +64,7 @@ public: virtual ir_visitor_status visit_leave(ir_texture *); virtual ir_visitor_status visit_leave(ir_emit_vertex *); virtual ir_visitor_status visit_leave(ir_end_primitive *); + virtual ir_visitor_status visit_leave(ir_ssbo_store *); }; class ir_rvalue_enter_visitor : public ir_rvalue_base_visitor { @@ -80,4 +82,5 @@ public: virtual ir_visitor_status visit_enter(ir_texture *); virtual ir_visitor_status visit_enter(ir_emit_vertex *); virtual ir_visitor_status visit_enter(ir_end_primitive *); + virtual ir_visitor_status visit_enter(ir_ssbo_store *); }; diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h index 40f96ff..3a68c27 100644 --- a/src/glsl/ir_visitor.h +++ b/src/glsl/ir_visitor.h @@ -65,6 +65,7 @@ public: virtual void visit(class ir_loop_jump *) = 0; virtual void visit(class ir_emit_vertex *) = 0; virtual void visit(class ir_end_primitive *) = 0; + virtual void visit(class ir_ssbo_store *) {}; /*@}*/ }; @@ -85,6 +86,7 @@ public: virtual void visit(class ir_call *) {} virtual void visit(class ir_emit_vertex *) {} virtual void visit(class ir_end_primitive *) {} + virtual void visit(class ir_ssbo_store *) {} }; #endif /* __cplusplus */ diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp index af758ce..261571b 100644 --- a/src/glsl/nir/glsl_to_nir.cpp +++ b/src/glsl/nir/glsl_to_nir.cpp @@ -58,6 +58,7 @@ public: virtual void visit(ir_assignment *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_ssbo_store *); virtual void visit(ir_expression *); virtual void visit(ir_swizzle *); virtual void visit(ir_texture *); @@ -570,6 +571,12 @@ nir_visitor::visit(ir_end_primitive *ir) } void +nir_visitor::visit(ir_ssbo_store *ir) +{ + assert("Not implemented yet"); +} + +void nir_visitor::visit(ir_loop_jump *ir) { nir_jump_type type; diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 1d7de2e..67d2df4 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -126,6 +126,7 @@ public: void visit(ir_function_signature *ir); void visit(ir_emit_vertex *); void visit(ir_end_primitive *); + void visit(ir_ssbo_store *); uint32_t gather_channel(int orig_chan, uint32_t sampler); void swizzle_result(ir_texture_opcode op, int dest_components, diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index a7c27d9..9c82aa3 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -3248,6 +3248,12 @@ fs_visitor::visit(ir_end_primitive *) } void +fs_visitor::visit(ir_ssbo_store *) +{ + unreachable("not implemented yet"); +} + +void fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, fs_reg dst, fs_reg offset, fs_reg src0, fs_reg src1) diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h index 628c631..f24107c 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.h +++ b/src/mesa/drivers/dri/i965/brw_vec4.h @@ -160,6 +160,7 @@ public: virtual void visit(ir_if *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_ssbo_store *); /*@}*/ src_reg result; diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 1298152..807e5df 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -2954,6 +2954,12 @@ vec4_visitor::visit(ir_end_primitive *) } void +vec4_visitor::visit(ir_ssbo_store *) +{ + unreachable("not implemented yet"); +} + +void vec4_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, dst_reg dst, src_reg offset, src_reg src0, src_reg src1) diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b86718c..8cdb704 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -262,6 +262,7 @@ public: virtual void visit(ir_if *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_ssbo_store *); /*@}*/ src_reg result; @@ -2118,6 +2119,12 @@ ir_to_mesa_visitor::visit(ir_end_primitive *) assert(!"Geometry shaders not supported."); } +void +ir_to_mesa_visitor::visit(ir_ssbo_store *) +{ + assert(!"Shader storage buffer object (SSBO) writes not supported."); +} + ir_to_mesa_visitor::ir_to_mesa_visitor() { result.file = PROGRAM_UNDEFINED; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 9c1089e..8265a8b 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -372,6 +372,7 @@ public: virtual void visit(ir_if *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_ssbo_store *); /*@}*/ st_src_reg result; @@ -3344,6 +3345,12 @@ glsl_to_tgsi_visitor::visit(ir_end_primitive *ir) emit(ir, TGSI_OPCODE_ENDPRIM, undef_dst, this->result); } +void +glsl_to_tgsi_visitor::visit(ir_ssbo_store *ir) +{ + assert(!"Not implemented yet"); +} + glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() { result.file = PROGRAM_UNDEFINED; -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev