diff options
author | Samuel Pitoiset <[email protected]> | 2016-01-16 23:15:42 +0100 |
---|---|---|
committer | Samuel Pitoiset <[email protected]> | 2016-02-13 16:01:00 +0100 |
commit | dfa58f0ff08c97f7f13775726c1fedda223aacc6 (patch) | |
tree | f98fa7ae91df9323618b7f5406c84021515ac32c /src/mesa | |
parent | 44e04dc809659323ae0b5e32b97fcfccc5db66f1 (diff) |
st/mesa: add intrinsics for shared variables
This adds GLSL intrinsics for load/store and atomic operations.
Changes from v2:
- use PROGRAM_MEMORY instead of PROGRAM_BUFFER
Signed-off-by: Samuel Pitoiset <[email protected]>
Reviewed-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/state_tracker/st_extensions.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 91 |
2 files changed, 94 insertions, 0 deletions
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 556cd65afa1..6736ebc53bf 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -264,6 +264,9 @@ void st_init_limits(struct pipe_screen *screen, options->LowerClipDistance = true; options->LowerBufferInterfaceBlocks = true; + + if (sh == PIPE_SHADER_COMPUTE) + options->LowerShaderSharedVariables = true; } c->LowerTessLevel = true; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 1d2d482fb12..741b8d8d05f 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -451,6 +451,7 @@ public: void visit_atomic_counter_intrinsic(ir_call *); void visit_ssbo_intrinsic(ir_call *); void visit_membar_intrinsic(ir_call *); + void visit_shared_intrinsic(ir_call *); st_src_reg result; @@ -3341,6 +3342,82 @@ glsl_to_tgsi_visitor::visit_membar_intrinsic(ir_call *ir) } void +glsl_to_tgsi_visitor::visit_shared_intrinsic(ir_call *ir) +{ + const char *callee = ir->callee->function_name(); + exec_node *param = ir->actual_parameters.get_head(); + + ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue(); + + st_src_reg buffer(PROGRAM_MEMORY, 0, GLSL_TYPE_UINT); + + /* Calculate the surface offset */ + offset->accept(this); + st_src_reg off = this->result; + + st_dst_reg dst = undef_dst; + if (ir->return_deref) { + ir->return_deref->accept(this); + dst = st_dst_reg(this->result); + dst.writemask = (1 << ir->return_deref->type->vector_elements) - 1; + } + + glsl_to_tgsi_instruction *inst; + + if (!strcmp("__intrinsic_load_shared", callee)) { + inst = emit_asm(ir, TGSI_OPCODE_LOAD, dst, off); + inst->buffer = buffer; + } else if (!strcmp("__intrinsic_store_shared", callee)) { + param = param->get_next(); + ir_rvalue *val = ((ir_instruction *)param)->as_rvalue(); + val->accept(this); + + param = param->get_next(); + ir_constant *write_mask = ((ir_instruction *)param)->as_constant(); + assert(write_mask); + dst.writemask = write_mask->value.u[0]; + + dst.type = this->result.type; + inst = emit_asm(ir, TGSI_OPCODE_STORE, dst, off, this->result); + inst->buffer = buffer; + } else { + param = param->get_next(); + ir_rvalue *val = ((ir_instruction *)param)->as_rvalue(); + val->accept(this); + + st_src_reg data = this->result, data2 = undef_src; + unsigned opcode; + if (!strcmp("__intrinsic_atomic_add_shared", callee)) + opcode = TGSI_OPCODE_ATOMUADD; + else if (!strcmp("__intrinsic_atomic_min_shared", callee)) + opcode = TGSI_OPCODE_ATOMIMIN; + else if (!strcmp("__intrinsic_atomic_max_shared", callee)) + opcode = TGSI_OPCODE_ATOMIMAX; + else if (!strcmp("__intrinsic_atomic_and_shared", callee)) + opcode = TGSI_OPCODE_ATOMAND; + else if (!strcmp("__intrinsic_atomic_or_shared", callee)) + opcode = TGSI_OPCODE_ATOMOR; + else if (!strcmp("__intrinsic_atomic_xor_shared", callee)) + opcode = TGSI_OPCODE_ATOMXOR; + else if (!strcmp("__intrinsic_atomic_exchange_shared", callee)) + opcode = TGSI_OPCODE_ATOMXCHG; + else if (!strcmp("__intrinsic_atomic_comp_swap_shared", callee)) { + opcode = TGSI_OPCODE_ATOMCAS; + param = param->get_next(); + val = ((ir_instruction *)param)->as_rvalue(); + val->accept(this); + data2 = this->result; + } else { + assert(!"Unexpected intrinsic"); + return; + } + + inst = emit_asm(ir, opcode, dst, off, data, data2); + inst->buffer = buffer; + } +} + +void glsl_to_tgsi_visitor::visit(ir_call *ir) { glsl_to_tgsi_instruction *call_inst; @@ -3381,6 +3458,20 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) return; } + if (!strcmp("__intrinsic_load_shared", callee) || + !strcmp("__intrinsic_store_shared", callee) || + !strcmp("__intrinsic_atomic_add_shared", callee) || + !strcmp("__intrinsic_atomic_min_shared", callee) || + !strcmp("__intrinsic_atomic_max_shared", callee) || + !strcmp("__intrinsic_atomic_and_shared", callee) || + !strcmp("__intrinsic_atomic_or_shared", callee) || + !strcmp("__intrinsic_atomic_xor_shared", callee) || + !strcmp("__intrinsic_atomic_exchange_shared", callee) || + !strcmp("__intrinsic_atomic_comp_swap_shared", callee)) { + visit_shared_intrinsic(ir); + return; + } + entry = get_function_signature(sig); /* Process in parameters. */ foreach_two_lists(formal_node, &sig->parameters, |