tgsi: provide a way to encode memory qualifiers for SSBO
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 <imirkin@alum.mit.edu> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
@@ -620,6 +620,7 @@ tgsi_default_instruction( void )
|
|||||||
instruction.NumSrcRegs = 1;
|
instruction.NumSrcRegs = 1;
|
||||||
instruction.Label = 0;
|
instruction.Label = 0;
|
||||||
instruction.Texture = 0;
|
instruction.Texture = 0;
|
||||||
|
instruction.Memory = 0;
|
||||||
instruction.Padding = 0;
|
instruction.Padding = 0;
|
||||||
|
|
||||||
return instruction;
|
return instruction;
|
||||||
@@ -766,6 +767,34 @@ tgsi_build_instruction_texture(
|
|||||||
return 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
|
static struct tgsi_texture_offset
|
||||||
tgsi_default_texture_offset( void )
|
tgsi_default_texture_offset( void )
|
||||||
@@ -1012,6 +1041,7 @@ tgsi_default_full_instruction( void )
|
|||||||
full_instruction.Predicate = tgsi_default_instruction_predicate();
|
full_instruction.Predicate = tgsi_default_instruction_predicate();
|
||||||
full_instruction.Label = tgsi_default_instruction_label();
|
full_instruction.Label = tgsi_default_instruction_label();
|
||||||
full_instruction.Texture = tgsi_default_instruction_texture();
|
full_instruction.Texture = tgsi_default_instruction_texture();
|
||||||
|
full_instruction.Memory = tgsi_default_instruction_memory();
|
||||||
for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) {
|
for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) {
|
||||||
full_instruction.TexOffsets[i] = tgsi_default_texture_offset();
|
full_instruction.TexOffsets[i] = tgsi_default_texture_offset();
|
||||||
}
|
}
|
||||||
@@ -1123,6 +1153,24 @@ tgsi_build_full_instruction(
|
|||||||
prev_token = (struct tgsi_token *) texture_offset;
|
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++ ) {
|
for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) {
|
||||||
const struct tgsi_full_dst_register *reg = &full_inst->Dst[i];
|
const struct tgsi_full_dst_register *reg = &full_inst->Dst[i];
|
||||||
struct tgsi_dst_register *dst_register;
|
struct tgsi_dst_register *dst_register;
|
||||||
|
@@ -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) {
|
switch (inst->Instruction.Opcode) {
|
||||||
case TGSI_OPCODE_IF:
|
case TGSI_OPCODE_IF:
|
||||||
case TGSI_OPCODE_UIF:
|
case TGSI_OPCODE_UIF:
|
||||||
|
@@ -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 );
|
assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
|
||||||
|
|
||||||
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
|
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
|
||||||
|
@@ -91,6 +91,7 @@ struct tgsi_full_instruction
|
|||||||
struct tgsi_instruction_predicate Predicate;
|
struct tgsi_instruction_predicate Predicate;
|
||||||
struct tgsi_instruction_label Label;
|
struct tgsi_instruction_label Label;
|
||||||
struct tgsi_instruction_texture Texture;
|
struct tgsi_instruction_texture Texture;
|
||||||
|
struct tgsi_instruction_memory Memory;
|
||||||
struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS];
|
struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS];
|
||||||
struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS];
|
struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS];
|
||||||
struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS];
|
struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS];
|
||||||
|
@@ -208,6 +208,13 @@ const char *tgsi_immediate_type_names[4] =
|
|||||||
"FLT64"
|
"FLT64"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *tgsi_memory_names[3] =
|
||||||
|
{
|
||||||
|
"COHERENT",
|
||||||
|
"RESTRICT",
|
||||||
|
"VOLATILE",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tgsi_strings_check(void)
|
tgsi_strings_check(void)
|
||||||
|
@@ -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_immediate_type_names[4];
|
||||||
|
|
||||||
|
extern const char *tgsi_memory_names[3];
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
tgsi_file_name(unsigned file);
|
tgsi_file_name(unsigned file);
|
||||||
|
@@ -1039,6 +1039,12 @@ parse_instruction(
|
|||||||
inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
|
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.
|
/* Parse instruction operands.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
|
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
|
||||||
@@ -1090,6 +1096,27 @@ parse_instruction(
|
|||||||
}
|
}
|
||||||
inst.Texture.NumOffsets = i;
|
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;
|
cur = ctx->cur;
|
||||||
eat_opt_white( &cur );
|
eat_opt_white( &cur );
|
||||||
if (info->is_branch && *cur == ':') {
|
if (info->is_branch && *cur == ':') {
|
||||||
|
@@ -60,6 +60,7 @@ union tgsi_any_token {
|
|||||||
struct tgsi_instruction_predicate insn_predicate;
|
struct tgsi_instruction_predicate insn_predicate;
|
||||||
struct tgsi_instruction_label insn_label;
|
struct tgsi_instruction_label insn_label;
|
||||||
struct tgsi_instruction_texture insn_texture;
|
struct tgsi_instruction_texture insn_texture;
|
||||||
|
struct tgsi_instruction_memory insn_memory;
|
||||||
struct tgsi_texture_offset insn_texture_offset;
|
struct tgsi_texture_offset insn_texture_offset;
|
||||||
struct tgsi_src_register src;
|
struct tgsi_src_register src;
|
||||||
struct tgsi_ind_register ind;
|
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
|
void
|
||||||
ureg_fixup_insn_size(struct ureg_program *ureg,
|
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
|
static void
|
||||||
emit_decl_semantic(struct ureg_program *ureg,
|
emit_decl_semantic(struct ureg_program *ureg,
|
||||||
unsigned file,
|
unsigned file,
|
||||||
|
@@ -531,6 +531,14 @@ ureg_label_insn(struct ureg_program *ureg,
|
|||||||
unsigned nr_src,
|
unsigned nr_src,
|
||||||
unsigned *label);
|
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:
|
* Internal instruction helpers, don't call these directly:
|
||||||
@@ -568,6 +576,11 @@ void
|
|||||||
ureg_emit_texture_offset(struct ureg_program *ureg,
|
ureg_emit_texture_offset(struct ureg_program *ureg,
|
||||||
const struct tgsi_texture_offset *offset);
|
const struct tgsi_texture_offset *offset);
|
||||||
|
|
||||||
|
void
|
||||||
|
ureg_emit_memory(struct ureg_program *ureg,
|
||||||
|
unsigned insn_token,
|
||||||
|
unsigned qualifier);
|
||||||
|
|
||||||
void
|
void
|
||||||
ureg_emit_dst( struct ureg_program *ureg,
|
ureg_emit_dst( struct ureg_program *ureg,
|
||||||
struct ureg_dst dst );
|
struct ureg_dst dst );
|
||||||
|
@@ -572,7 +572,8 @@ struct tgsi_instruction
|
|||||||
unsigned Predicate : 1; /* BOOL */
|
unsigned Predicate : 1; /* BOOL */
|
||||||
unsigned Label : 1;
|
unsigned Label : 1;
|
||||||
unsigned Texture : 1;
|
unsigned Texture : 1;
|
||||||
unsigned Padding : 2;
|
unsigned Memory : 1;
|
||||||
|
unsigned Padding : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -729,6 +730,19 @@ struct tgsi_dst_register
|
|||||||
unsigned Padding : 6;
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user