[Mesa-dev] [PATCH 26/74] mesa: Add new IR node ir_ssbo_store

Iago Toral Quiroga itoral at igalia.com
Thu May 14 07:06:29 PDT 2015


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



More information about the mesa-dev mailing list