From 50b8488926c4fa45ed79148217b81e54252788e7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 7 Nov 2015 02:25:20 -0500 Subject: [PATCH] tgsi: provide a way to encode memory qualifiers for SSBO MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Each load/store on most hardware can specify what caching to do. Since SSBO allows individual variables to also have separate caching modes, allow loads/stores to have the qualifiers instead of attempting to encode them in declarations. Signed-off-by: Ilia Mirkin Reviewed-by: Marek Olšák --- src/gallium/auxiliary/tgsi/tgsi_build.c | 50 ++++++++++++++++++++- src/gallium/auxiliary/tgsi/tgsi_dump.c | 10 +++++ src/gallium/auxiliary/tgsi/tgsi_parse.c | 4 ++ src/gallium/auxiliary/tgsi/tgsi_parse.h | 1 + src/gallium/auxiliary/tgsi/tgsi_strings.c | 7 +++ src/gallium/auxiliary/tgsi/tgsi_strings.h | 2 + src/gallium/auxiliary/tgsi/tgsi_text.c | 27 +++++++++++ src/gallium/auxiliary/tgsi/tgsi_ureg.c | 52 ++++++++++++++++++++++ src/gallium/auxiliary/tgsi/tgsi_ureg.h | 13 ++++++ src/gallium/include/pipe/p_shader_tokens.h | 16 ++++++- 10 files changed, 180 insertions(+), 2 deletions(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index bb9d0cbe25d..ea207461d27 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -620,7 +620,8 @@ tgsi_default_instruction( void ) instruction.NumSrcRegs = 1; instruction.Label = 0; instruction.Texture = 0; - instruction.Padding = 0; + instruction.Memory = 0; + instruction.Padding = 0; return instruction; } @@ -766,6 +767,34 @@ tgsi_build_instruction_texture( return instruction_texture; } +static struct tgsi_instruction_memory +tgsi_default_instruction_memory( void ) +{ + struct tgsi_instruction_memory instruction_memory; + + instruction_memory.Qualifier = 0; + instruction_memory.Padding = 0; + + return instruction_memory; +} + +static struct tgsi_instruction_memory +tgsi_build_instruction_memory( + unsigned qualifier, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_memory instruction_memory; + + instruction_memory.Qualifier = qualifier; + instruction_memory.Padding = 0; + instruction->Memory = 1; + + instruction_grow( instruction, header ); + + return instruction_memory; +} static struct tgsi_texture_offset tgsi_default_texture_offset( void ) @@ -1012,6 +1041,7 @@ tgsi_default_full_instruction( void ) full_instruction.Predicate = tgsi_default_instruction_predicate(); full_instruction.Label = tgsi_default_instruction_label(); full_instruction.Texture = tgsi_default_instruction_texture(); + full_instruction.Memory = tgsi_default_instruction_memory(); for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) { full_instruction.TexOffsets[i] = tgsi_default_texture_offset(); } @@ -1123,6 +1153,24 @@ tgsi_build_full_instruction( prev_token = (struct tgsi_token *) texture_offset; } } + + if (full_inst->Instruction.Memory) { + struct tgsi_instruction_memory *instruction_memory; + + if( maxsize <= size ) + return 0; + instruction_memory = + (struct tgsi_instruction_memory *) &tokens[size]; + size++; + + *instruction_memory = tgsi_build_instruction_memory( + full_inst->Memory.Qualifier, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_memory; + } + for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) { const struct tgsi_full_dst_register *reg = &full_inst->Dst[i]; struct tgsi_dst_register *dst_register; diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index de3aae5337c..2ad29b9d49a 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -624,6 +624,16 @@ iter_instruction( } } + if (inst->Instruction.Memory) { + uint32_t qualifier = inst->Memory.Qualifier; + while (qualifier) { + int bit = ffs(qualifier) - 1; + qualifier &= ~(1U << bit); + TXT(", "); + ENM(bit, tgsi_memory_names); + } + } + switch (inst->Instruction.Opcode) { case TGSI_OPCODE_IF: case TGSI_OPCODE_UIF: diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 9a52bbbf5cb..ae95ebd82a4 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -195,6 +195,10 @@ tgsi_parse_token( } } + if (inst->Instruction.Memory) { + next_token(ctx, &inst->Memory); + } + assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); for (i = 0; i < inst->Instruction.NumDstRegs; i++) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 5ed1a83b027..4689fb797d0 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -91,6 +91,7 @@ struct tgsi_full_instruction struct tgsi_instruction_predicate Predicate; struct tgsi_instruction_label Label; struct tgsi_instruction_texture Texture; + struct tgsi_instruction_memory Memory; struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS]; struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS]; struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS]; diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.c b/src/gallium/auxiliary/tgsi/tgsi_strings.c index c0dd04497f7..f2d70d49839 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_strings.c +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.c @@ -208,6 +208,13 @@ const char *tgsi_immediate_type_names[4] = "FLT64" }; +const char *tgsi_memory_names[3] = +{ + "COHERENT", + "RESTRICT", + "VOLATILE", +}; + static inline void tgsi_strings_check(void) diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.h b/src/gallium/auxiliary/tgsi/tgsi_strings.h index 71e74372f22..031d32278cc 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_strings.h +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.h @@ -60,6 +60,8 @@ extern const char *tgsi_fs_coord_pixel_center_names[2]; extern const char *tgsi_immediate_type_names[4]; +extern const char *tgsi_memory_names[3]; + const char * tgsi_file_name(unsigned file); diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index d72d843951a..97b1869a66f 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -1039,6 +1039,12 @@ parse_instruction( inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; } + if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || + i == TGSI_OPCODE_RESQ) { + inst.Instruction.Memory = 1; + inst.Memory.Qualifier = 0; + } + /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { @@ -1090,6 +1096,27 @@ parse_instruction( } inst.Texture.NumOffsets = i; + cur = ctx->cur; + eat_opt_white(&cur); + for (i = 0; inst.Instruction.Memory && *cur == ','; i++) { + uint j; + cur++; + eat_opt_white(&cur); + ctx->cur = cur; + for (j = 0; j < 3; j++) { + if (str_match_nocase_whole(&ctx->cur, tgsi_memory_names[j])) { + inst.Memory.Qualifier |= 1U << j; + break; + } + } + if (j == 3) { + report_error(ctx, "Expected memory qualifier"); + return FALSE; + } + cur = ctx->cur; + eat_opt_white(&cur); + } + cur = ctx->cur; eat_opt_white( &cur ); if (info->is_branch && *cur == ':') { diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index 0ad23dd5e56..d6811501d16 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -60,6 +60,7 @@ union tgsi_any_token { struct tgsi_instruction_predicate insn_predicate; struct tgsi_instruction_label insn_label; struct tgsi_instruction_texture insn_texture; + struct tgsi_instruction_memory insn_memory; struct tgsi_texture_offset insn_texture_offset; struct tgsi_src_register src; struct tgsi_ind_register ind; @@ -1226,6 +1227,21 @@ ureg_emit_texture_offset(struct ureg_program *ureg, } +void +ureg_emit_memory(struct ureg_program *ureg, + unsigned extended_token, + unsigned qualifier) +{ + union tgsi_any_token *out, *insn; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); + + insn->insn.Memory = 1; + + out[0].value = 0; + out[0].insn_memory.Qualifier = qualifier; +} void ureg_fixup_insn_size(struct ureg_program *ureg, @@ -1378,6 +1394,42 @@ ureg_label_insn(struct ureg_program *ureg, } +void +ureg_memory_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src, + unsigned qualifier) +{ + struct ureg_emit_insn_result insn; + unsigned i; + + insn = ureg_emit_insn(ureg, + opcode, + FALSE, + FALSE, + FALSE, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_W, + nr_dst, + nr_src); + + ureg_emit_memory(ureg, insn.extended_token, qualifier); + + for (i = 0; i < nr_dst; i++) + ureg_emit_dst(ureg, dst[i]); + + for (i = 0; i < nr_src; i++) + ureg_emit_src(ureg, src[i]); + + ureg_fixup_insn_size(ureg, insn.insn_token); +} + + static void emit_decl_semantic(struct ureg_program *ureg, unsigned file, diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 4a411c66491..86e58a91343 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -531,6 +531,14 @@ ureg_label_insn(struct ureg_program *ureg, unsigned nr_src, unsigned *label); +void +ureg_memory_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src, + unsigned qualifier); /*********************************************************************** * Internal instruction helpers, don't call these directly: @@ -568,6 +576,11 @@ void ureg_emit_texture_offset(struct ureg_program *ureg, const struct tgsi_texture_offset *offset); +void +ureg_emit_memory(struct ureg_program *ureg, + unsigned insn_token, + unsigned qualifier); + void ureg_emit_dst( struct ureg_program *ureg, struct ureg_dst dst ); diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 815aff1dab3..43a5561882c 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -572,7 +572,8 @@ struct tgsi_instruction unsigned Predicate : 1; /* BOOL */ unsigned Label : 1; unsigned Texture : 1; - unsigned Padding : 2; + unsigned Memory : 1; + unsigned Padding : 1; }; /* @@ -729,6 +730,19 @@ struct tgsi_dst_register unsigned Padding : 6; }; +#define TGSI_MEMORY_COHERENT (1 << 0) +#define TGSI_MEMORY_RESTRICT (1 << 1) +#define TGSI_MEMORY_VOLATILE (1 << 2) + +/** + * Specifies the type of memory access to do for the LOAD/STORE instruction. + */ +struct tgsi_instruction_memory +{ + unsigned Qualifier : 3; /* TGSI_MEMORY_ */ + unsigned Padding : 29; +}; + #ifdef __cplusplus } -- 2.30.2