diff options
Diffstat (limited to 'src/gallium/auxiliary/tgsi/tgsi_ureg.c')
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_ureg.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index b26434ccbde..4f3ac97ad4d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -80,6 +80,7 @@ struct ureg_tokens { #define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS #define UREG_MAX_OUTPUT (4 * PIPE_MAX_SHADER_OUTPUTS) #define UREG_MAX_CONSTANT_RANGE 32 +#define UREG_MAX_HW_ATOMIC_RANGE 32 #define UREG_MAX_IMMEDIATE 4096 #define UREG_MAX_ADDR 3 #define UREG_MAX_ARRAY_TEMPS 256 @@ -92,6 +93,15 @@ struct const_decl { unsigned nr_constant_ranges; }; +struct hw_atomic_decl { + struct { + unsigned first; + unsigned last; + unsigned array_id; + } hw_atomic_range[UREG_MAX_HW_ATOMIC_RANGE]; + unsigned nr_hw_atomic_ranges; +}; + #define DOMAIN_DECL 0 #define DOMAIN_INSN 1 @@ -182,6 +192,8 @@ struct ureg_program struct const_decl const_decls[PIPE_MAX_CONSTANT_BUFFERS]; + struct hw_atomic_decl hw_atomic_decls[PIPE_MAX_HW_ATOMIC_BUFFERS]; + unsigned properties[TGSI_PROPERTY_COUNT]; unsigned nr_addrs; @@ -583,6 +595,30 @@ out: return ureg_src_dimension(src, 0); } + +/* Returns a new hw atomic register. Keep track of which have been + * referred to so that we can emit decls later. + */ +void +ureg_DECL_hw_atomic(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned buffer_id, + unsigned array_id) +{ + struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[buffer_id]; + + if (decl->nr_hw_atomic_ranges < UREG_MAX_HW_ATOMIC_RANGE) { + uint i = decl->nr_hw_atomic_ranges++; + + decl->hw_atomic_range[i].first = first; + decl->hw_atomic_range[i].last = last; + decl->hw_atomic_range[i].array_id = array_id; + } else { + set_bad(ureg); + } +} + static struct ureg_dst alloc_temporary( struct ureg_program *ureg, boolean local ) { @@ -1501,6 +1537,35 @@ emit_decl_semantic(struct ureg_program *ureg, } } +static void +emit_decl_atomic_2d(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned index2D, + unsigned array_id) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = TGSI_FILE_HW_ATOMIC; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; + out[0].decl.Dimension = 1; + out[0].decl.Array = array_id != 0; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = last; + + out[2].value = 0; + out[2].decl_dim.Index2D = index2D; + + if (array_id) { + out[3].value = 0; + out[3].array.ArrayID = array_id; + } +} static void emit_decl_fs(struct ureg_program *ureg, @@ -1908,6 +1973,22 @@ static void emit_decls( struct ureg_program *ureg ) } } + for (i = 0; i < PIPE_MAX_HW_ATOMIC_BUFFERS; i++) { + struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[i]; + + if (decl->nr_hw_atomic_ranges) { + uint j; + + for (j = 0; j < decl->nr_hw_atomic_ranges; j++) { + emit_decl_atomic_2d(ureg, + decl->hw_atomic_range[j].first, + decl->hw_atomic_range[j].last, + i, + decl->hw_atomic_range[j].array_id); + } + } + } + if (ureg->nr_temps) { unsigned array = 0; for (i = 0; i < ureg->nr_temps;) { |