gallium: implement modern sampling scheme

largely a merge of the previously discussed origin/gallium-resource-sampling
but updated.
the idea is to allow arbitrary binding of resources, the way opencl, new gl
versions and dx10+ require, i.e.
    DCL RES[0], 2D, FLOAT

    LOAD DST[0], SRC[0], RES[0]
    SAMPLE DST[0], SRC[0], RES[0], SAMP[0]
This commit is contained in:
Zack Rusin
2011-01-24 17:47:10 -05:00
parent b066983780
commit bdbe77f9c6
17 changed files with 770 additions and 37 deletions

View File

@@ -26,6 +26,7 @@
**************************************************************************/ **************************************************************************/
#include "util/u_debug.h" #include "util/u_debug.h"
#include "pipe/p_format.h"
#include "pipe/p_shader_tokens.h" #include "pipe/p_shader_tokens.h"
#include "tgsi_build.h" #include "tgsi_build.h"
#include "tgsi_parse.h" #include "tgsi_parse.h"
@@ -226,6 +227,45 @@ tgsi_build_declaration_semantic(
return ds; return ds;
} }
static struct tgsi_declaration_resource
tgsi_default_declaration_resource(void)
{
struct tgsi_declaration_resource declaration_resource;
declaration_resource.Resource = TGSI_TEXTURE_UNKNOWN;
declaration_resource.ReturnTypeX = PIPE_TYPE_UNORM;
declaration_resource.ReturnTypeY = PIPE_TYPE_UNORM;
declaration_resource.ReturnTypeZ = PIPE_TYPE_UNORM;
declaration_resource.ReturnTypeW = PIPE_TYPE_UNORM;
return declaration_resource;
}
static struct tgsi_declaration_resource
tgsi_build_declaration_resource(unsigned texture,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_resource declaration_resource;
declaration_resource = tgsi_default_declaration_resource();
declaration_resource.Resource = texture;
declaration_resource.ReturnTypeX = return_type_x;
declaration_resource.ReturnTypeY = return_type_y;
declaration_resource.ReturnTypeZ = return_type_z;
declaration_resource.ReturnTypeW = return_type_w;
declaration_grow(declaration, header);
return declaration_resource;
}
struct tgsi_full_declaration struct tgsi_full_declaration
tgsi_default_full_declaration( void ) tgsi_default_full_declaration( void )
{ {
@@ -235,6 +275,7 @@ tgsi_default_full_declaration( void )
full_declaration.Range = tgsi_default_declaration_range(); full_declaration.Range = tgsi_default_declaration_range();
full_declaration.Semantic = tgsi_default_declaration_semantic(); full_declaration.Semantic = tgsi_default_declaration_semantic();
full_declaration.ImmediateData.u = NULL; full_declaration.ImmediateData.u = NULL;
full_declaration.Resource = tgsi_default_declaration_resource();
return full_declaration; return full_declaration;
} }
@@ -324,6 +365,24 @@ tgsi_build_full_declaration(
} }
} }
if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) {
struct tgsi_declaration_resource *dr;
if (maxsize <= size) {
return 0;
}
dr = (struct tgsi_declaration_resource *)&tokens[size];
size++;
*dr = tgsi_build_declaration_resource(full_decl->Resource.Resource,
full_decl->Resource.ReturnTypeX,
full_decl->Resource.ReturnTypeY,
full_decl->Resource.ReturnTypeZ,
full_decl->Resource.ReturnTypeW,
declaration,
header);
}
return size; return size;
} }

View File

@@ -104,7 +104,8 @@ tgsi_file_names[TGSI_FILE_COUNT] =
"PRED", "PRED",
"SV", "SV",
"IMMX", "IMMX",
"TEMPX" "TEMPX",
"RES"
}; };
static const char *interpolate_names[] = static const char *interpolate_names[] =
@@ -170,6 +171,15 @@ const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
"FS_COLOR0_WRITES_ALL_CBUFS", "FS_COLOR0_WRITES_ALL_CBUFS",
}; };
static const char *tgsi_type_names[] =
{
"UNORM",
"SNORM",
"SINT",
"UINT",
"FLOAT"
};
const char *tgsi_primitive_names[PIPE_PRIM_MAX] = const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
{ {
"POINTS", "POINTS",
@@ -393,6 +403,26 @@ iter_declaration(
} }
} }
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
TXT(", ");
ENM(decl->Resource.Resource, tgsi_texture_names);
TXT(", ");
if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) &&
(decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) &&
(decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) {
ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
} else {
ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
TXT(", ");
ENM(decl->Resource.ReturnTypeY, tgsi_type_names);
TXT(", ");
ENM(decl->Resource.ReturnTypeZ, tgsi_type_names);
TXT(", ");
ENM(decl->Resource.ReturnTypeW, tgsi_type_names);
}
}
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT && if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
decl->Declaration.File == TGSI_FILE_INPUT) decl->Declaration.File == TGSI_FILE_INPUT)
{ {

View File

@@ -1843,6 +1843,164 @@ exec_txd(struct tgsi_exec_machine *mach,
} }
static void
exec_sample(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
uint modifier)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4];
const union tgsi_exec_channel *lod = &ZeroVec;
enum tgsi_sampler_control control;
uint chan;
if (modifier != TEX_MODIFIER_NONE) {
if (modifier == TEX_MODIFIER_LOD_BIAS)
FETCH(&r[3], 3, CHAN_X);
else /*TEX_MODIFIER_LOD*/
FETCH(&r[3], 0, CHAN_W);
if (modifier != TEX_MODIFIER_PROJECTED) {
lod = &r[3];
}
}
if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
control = tgsi_sampler_lod_explicit;
} else {
control = tgsi_sampler_lod_bias;
}
switch (mach->Resources[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
FETCH(&r[0], 0, CHAN_X);
if (modifier == TEX_MODIFIER_PROJECTED) {
micro_div(&r[0], &r[0], &r[3]);
}
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &ZeroVec, &ZeroVec, lod, /* S, T, P, LOD */
control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
FETCH(&r[0], 0, CHAN_X);
FETCH(&r[1], 0, CHAN_Y);
FETCH(&r[2], 0, CHAN_Z);
if (modifier == TEX_MODIFIER_PROJECTED) {
micro_div(&r[0], &r[0], &r[3]);
micro_div(&r[1], &r[1], &r[3]);
micro_div(&r[2], &r[2], &r[3]);
}
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &r[1], &r[2], lod, /* S, T, P, LOD */
control,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
FETCH(&r[0], 0, CHAN_X);
FETCH(&r[1], 0, CHAN_Y);
FETCH(&r[2], 0, CHAN_Z);
if (modifier == TEX_MODIFIER_PROJECTED) {
micro_div(&r[0], &r[0], &r[3]);
micro_div(&r[1], &r[1], &r[3]);
micro_div(&r[2], &r[2], &r[3]);
}
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &r[1], &r[2], lod,
control,
&r[0], &r[1], &r[2], &r[3]);
break;
default:
assert(0);
}
for (chan = 0; chan < NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
static void
exec_sample_d(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4];
uint chan;
/*
* XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet.
*/
switch (mach->Resources[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
FETCH(&r[0], 0, CHAN_X);
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, BIAS */
tgsi_sampler_lod_bias,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
FETCH(&r[0], 0, CHAN_X);
FETCH(&r[1], 0, CHAN_Y);
FETCH(&r[2], 0, CHAN_Z);
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &r[1], &r[2], &ZeroVec, /* inputs */
tgsi_sampler_lod_bias,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
FETCH(&r[0], 0, CHAN_X);
FETCH(&r[1], 0, CHAN_Y);
FETCH(&r[2], 0, CHAN_Z);
fetch_texel(mach->Samplers[sampler_unit],
&r[0], &r[1], &r[2], &ZeroVec,
tgsi_sampler_lod_bias,
&r[0], &r[1], &r[2], &r[3]);
break;
default:
assert(0);
}
for (chan = 0; chan < NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
/** /**
* Evaluate a constant-valued coefficient at the position of the * Evaluate a constant-valued coefficient at the position of the
* current quad. * current quad.
@@ -1914,6 +2072,11 @@ static void
exec_declaration(struct tgsi_exec_machine *mach, exec_declaration(struct tgsi_exec_machine *mach,
const struct tgsi_full_declaration *decl) const struct tgsi_full_declaration *decl)
{ {
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
mach->Resources[decl->Range.First] = decl->Resource;
return;
}
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
if (decl->Declaration.File == TGSI_FILE_INPUT) { if (decl->Declaration.File == TGSI_FILE_INPUT) {
uint first, last, mask; uint first, last, mask;
@@ -3688,6 +3851,54 @@ exec_instruction(
exec_endswitch(mach); exec_endswitch(mach);
break; break;
case TGSI_OPCODE_LOAD:
assert(0);
break;
case TGSI_OPCODE_LOAD_MS:
assert(0);
break;
case TGSI_OPCODE_SAMPLE:
exec_sample(mach, inst, TEX_MODIFIER_NONE);
break;
case TGSI_OPCODE_SAMPLE_B:
exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
break;
case TGSI_OPCODE_SAMPLE_C:
exec_sample(mach, inst, TEX_MODIFIER_NONE);
break;
case TGSI_OPCODE_SAMPLE_C_LZ:
exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
break;
case TGSI_OPCODE_SAMPLE_D:
exec_sample_d(mach, inst);
break;
case TGSI_OPCODE_SAMPLE_L:
exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD);
break;
case TGSI_OPCODE_GATHER4:
assert(0);
break;
case TGSI_OPCODE_RESINFO:
assert(0);
break;
case TGSI_OPCODE_SAMPLE_POS:
assert(0);
break;
case TGSI_OPCODE_SAMPLE_INFO:
assert(0);
break;
default: default:
assert( 0 ); assert( 0 );
} }

View File

@@ -308,6 +308,7 @@ struct tgsi_exec_machine
struct tgsi_full_declaration *Declarations; struct tgsi_full_declaration *Declarations;
uint NumDeclarations; uint NumDeclarations;
struct tgsi_declaration_resource Resources[PIPE_MAX_SHADER_RESOURCES];
}; };
struct tgsi_exec_machine * struct tgsi_exec_machine *

View File

@@ -175,7 +175,20 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{ 0, 1, 0, 0, 0, 0, "SWITCH", TGSI_OPCODE_SWITCH }, { 0, 1, 0, 0, 0, 0, "SWITCH", TGSI_OPCODE_SWITCH },
{ 0, 1, 0, 0, 0, 0, "CASE", TGSI_OPCODE_CASE }, { 0, 1, 0, 0, 0, 0, "CASE", TGSI_OPCODE_CASE },
{ 0, 0, 0, 0, 0, 0, "DEFAULT", TGSI_OPCODE_DEFAULT }, { 0, 0, 0, 0, 0, 0, "DEFAULT", TGSI_OPCODE_DEFAULT },
{ 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH } { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH },
{ 1, 2, 0, 0, 0, 0, "LOAD", TGSI_OPCODE_LOAD },
{ 1, 2, 0, 0, 0, 0, "LOAD_MS", TGSI_OPCODE_LOAD_MS },
{ 1, 3, 0, 0, 0, 0, "SAMPLE", TGSI_OPCODE_SAMPLE },
{ 1, 4, 0, 0, 0, 0, "SAMPLE_B", TGSI_OPCODE_SAMPLE_B },
{ 1, 4, 0, 0, 0, 0, "SAMPLE_C", TGSI_OPCODE_SAMPLE_C },
{ 1, 4, 0, 0, 0, 0, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ },
{ 1, 5, 0, 0, 0, 0, "SAMPLE_D", TGSI_OPCODE_SAMPLE_D },
{ 1, 3, 0, 0, 0, 0, "SAMPLE_L", TGSI_OPCODE_SAMPLE_L },
{ 1, 3, 0, 0, 0, 0, "GATHER4", TGSI_OPCODE_GATHER4 },
{ 1, 2, 0, 0, 0, 0, "RESINFO", TGSI_OPCODE_RESINFO },
{ 1, 2, 0, 0, 0, 0, "SAMPLE_POS", TGSI_OPCODE_SAMPLE_POS },
{ 1, 2, 0, 0, 0, 0, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO },
}; };
const struct tgsi_opcode_info * const struct tgsi_opcode_info *

View File

@@ -168,6 +168,19 @@ OP01(CASE)
OP00(DEFAULT) OP00(DEFAULT)
OP00(ENDSWITCH) OP00(ENDSWITCH)
OP12(LOAD)
OP12(LOAD_MS)
OP13(SAMPLE)
OP14(SAMPLE_B)
OP14(SAMPLE_C)
OP14(SAMPLE_C_LZ)
OP15(SAMPLE_D)
OP13(SAMPLE_L)
OP13(GATHER4)
OP12(RESINFO)
OP13(SAMPLE_POS)
OP12(SAMPLE_INFO)
#undef OP00 #undef OP00
#undef OP01 #undef OP01
@@ -180,6 +193,10 @@ OP00(ENDSWITCH)
#undef OP14 #undef OP14
#endif #endif
#ifdef OP15
#undef OP15
#endif
#undef OP00_LBL #undef OP00_LBL
#undef OP01_LBL #undef OP01_LBL

View File

@@ -128,6 +128,10 @@ tgsi_parse_token(
} }
} }
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
next_token(ctx, &decl->Resource);
}
break; break;
} }

View File

@@ -69,6 +69,7 @@ struct tgsi_full_declaration
struct tgsi_declaration_dimension Dim; struct tgsi_declaration_dimension Dim;
struct tgsi_declaration_semantic Semantic; struct tgsi_declaration_semantic Semantic;
struct tgsi_immediate_array_data ImmediateData; struct tgsi_immediate_array_data ImmediateData;
struct tgsi_declaration_resource Resource;
}; };
struct tgsi_full_immediate struct tgsi_full_immediate
@@ -84,7 +85,7 @@ struct tgsi_full_property
}; };
#define TGSI_FULL_MAX_DST_REGISTERS 2 #define TGSI_FULL_MAX_DST_REGISTERS 2
#define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */ #define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */
struct tgsi_full_instruction struct tgsi_full_instruction
{ {

View File

@@ -258,7 +258,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"PRED", "PRED",
"SV", "SV",
"IMMX", "IMMX",
"TEMPX" "TEMPX",
"RES"
}; };
static boolean static boolean

View File

@@ -283,7 +283,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"PRED", "PRED",
"SV", "SV",
"IMMX", "IMMX",
"TEMPX" "TEMPX",
"RES"
}; };
static boolean static boolean
@@ -828,6 +829,15 @@ static const char *texture_names[TGSI_TEXTURE_COUNT] =
"SHADOWRECT" "SHADOWRECT"
}; };
static const char *type_names[] =
{
"UNORM",
"SNORM",
"SINT",
"UINT",
"FLOAT"
};
static boolean static boolean
match_inst_mnemonic(const char **pcur, match_inst_mnemonic(const char **pcur,
const struct tgsi_opcode_info *info) const struct tgsi_opcode_info *info)
@@ -1104,10 +1114,80 @@ static boolean parse_declaration( struct translate_ctx *ctx )
cur = ctx->cur; cur = ctx->cur;
eat_opt_white( &cur ); eat_opt_white( &cur );
if (*cur == ',' && !is_vs_input) { if (*cur == ',' && !is_vs_input) {
uint i; uint i, j;
cur++; cur++;
eat_opt_white( &cur ); eat_opt_white( &cur );
if (file == TGSI_FILE_RESOURCE) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
if (str_match_no_case(&cur, texture_names[i])) {
if (!is_digit_alpha_underscore(cur)) {
decl.Resource.Resource = i;
break;
}
}
}
if (i == TGSI_TEXTURE_COUNT) {
report_error(ctx, "Expected texture target");
return FALSE;
}
eat_opt_white( &cur );
if (*cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
++cur;
eat_opt_white( &cur );
for (j = 0; j < 4; ++j) {
for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
if (str_match_no_case(&cur, type_names[i])) {
if (!is_digit_alpha_underscore(cur)) {
switch (j) {
case 0:
decl.Resource.ReturnTypeX = i;
break;
case 1:
decl.Resource.ReturnTypeY = i;
break;
case 2:
decl.Resource.ReturnTypeZ = i;
break;
case 3:
decl.Resource.ReturnTypeW = i;
break;
default:
assert(0);
}
break;
}
}
}
if (i == PIPE_TYPE_COUNT) {
if (j == 0 || j > 2) {
report_error(ctx, "Expected type name");
return FALSE;
}
break;
} else {
const char *cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == ',') {
cur2++;
eat_opt_white( &cur2 );
cur = cur2;
continue;
} else
break;
}
}
if (j < 4) {
decl.Resource.ReturnTypeY =
decl.Resource.ReturnTypeZ =
decl.Resource.ReturnTypeW =
decl.Resource.ReturnTypeX;
}
ctx->cur = cur;
} else {
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
if (str_match_no_case( &cur, semantic_names[i] )) { if (str_match_no_case( &cur, semantic_names[i] )) {
const char *cur2 = cur; const char *cur2 = cur;
@@ -1142,6 +1222,7 @@ static boolean parse_declaration( struct translate_ctx *ctx )
break; break;
} }
} }
}
} else if (is_imm_array) { } else if (is_imm_array) {
unsigned i; unsigned i;
float *vals_itr; float *vals_itr;

View File

@@ -1,6 +1,6 @@
/************************************************************************** /**************************************************************************
* *
* Copyright 2009 VMware, Inc. * Copyright 2009-2010 VMware, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@@ -47,6 +47,7 @@ union tgsi_any_token {
struct tgsi_declaration_range decl_range; struct tgsi_declaration_range decl_range;
struct tgsi_declaration_dimension decl_dim; struct tgsi_declaration_dimension decl_dim;
struct tgsi_declaration_semantic decl_semantic; struct tgsi_declaration_semantic decl_semantic;
struct tgsi_declaration_resource decl_resource;
struct tgsi_immediate imm; struct tgsi_immediate imm;
union tgsi_immediate_data imm_data; union tgsi_immediate_data imm_data;
struct tgsi_instruction insn; struct tgsi_instruction insn;
@@ -137,6 +138,16 @@ struct ureg_program
struct ureg_src sampler[PIPE_MAX_SAMPLERS]; struct ureg_src sampler[PIPE_MAX_SAMPLERS];
unsigned nr_samplers; unsigned nr_samplers;
struct {
unsigned index;
unsigned target;
unsigned return_type_x;
unsigned return_type_y;
unsigned return_type_z;
unsigned return_type_w;
} resource[PIPE_MAX_SHADER_RESOURCES];
unsigned nr_resources;
unsigned temps_active[UREG_MAX_TEMP / 32]; unsigned temps_active[UREG_MAX_TEMP / 32];
unsigned nr_temps; unsigned nr_temps;
@@ -578,6 +589,41 @@ struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
return ureg->sampler[0]; return ureg->sampler[0];
} }
/*
* Allocate a new shader resource.
*/
struct ureg_src
ureg_DECL_resource(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w)
{
struct ureg_src reg = ureg_src_register(TGSI_FILE_RESOURCE, index);
uint i;
for (i = 0; i < ureg->nr_resources; i++) {
if (ureg->resource[i].index == index) {
return reg;
}
}
if (i < PIPE_MAX_SHADER_RESOURCES) {
ureg->resource[i].index = index;
ureg->resource[i].target = target;
ureg->resource[i].return_type_x = return_type_x;
ureg->resource[i].return_type_y = return_type_y;
ureg->resource[i].return_type_z = return_type_z;
ureg->resource[i].return_type_w = return_type_w;
ureg->nr_resources++;
return reg;
}
assert(0);
return reg;
}
static int static int
match_or_expand_immediate( const unsigned *v, match_or_expand_immediate( const unsigned *v,
@@ -821,6 +867,7 @@ ureg_emit_dst( struct ureg_program *ureg,
assert(dst.File != TGSI_FILE_CONSTANT); assert(dst.File != TGSI_FILE_CONSTANT);
assert(dst.File != TGSI_FILE_INPUT); assert(dst.File != TGSI_FILE_INPUT);
assert(dst.File != TGSI_FILE_SAMPLER); assert(dst.File != TGSI_FILE_SAMPLER);
assert(dst.File != TGSI_FILE_RESOURCE);
assert(dst.File != TGSI_FILE_IMMEDIATE); assert(dst.File != TGSI_FILE_IMMEDIATE);
assert(dst.File < TGSI_FILE_COUNT); assert(dst.File < TGSI_FILE_COUNT);
@@ -1205,6 +1252,36 @@ emit_decl_range2D(struct ureg_program *ureg,
out[2].decl_dim.Index2D = index2D; out[2].decl_dim.Index2D = index2D;
} }
static void
emit_decl_resource(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w )
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = TGSI_FILE_RESOURCE;
out[0].decl.UsageMask = 0xf;
out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
out[2].value = 0;
out[2].decl_resource.Resource = target;
out[2].decl_resource.ReturnTypeX = return_type_x;
out[2].decl_resource.ReturnTypeY = return_type_y;
out[2].decl_resource.ReturnTypeZ = return_type_z;
out[2].decl_resource.ReturnTypeW = return_type_w;
}
static void static void
emit_immediate( struct ureg_program *ureg, emit_immediate( struct ureg_program *ureg,
const unsigned *v, const unsigned *v,
@@ -1341,6 +1418,16 @@ static void emit_decls( struct ureg_program *ureg )
ureg->sampler[i].Index, 1 ); ureg->sampler[i].Index, 1 );
} }
for (i = 0; i < ureg->nr_resources; i++) {
emit_decl_resource(ureg,
ureg->resource[i].index,
ureg->resource[i].target,
ureg->resource[i].return_type_x,
ureg->resource[i].return_type_y,
ureg->resource[i].return_type_z,
ureg->resource[i].return_type_w);
}
if (ureg->const_decls.nr_constant_ranges) { if (ureg->const_decls.nr_constant_ranges) {
for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
emit_decl_range(ureg, emit_decl_range(ureg,

View File

@@ -270,6 +270,15 @@ struct ureg_src
ureg_DECL_sampler( struct ureg_program *, ureg_DECL_sampler( struct ureg_program *,
unsigned index ); unsigned index );
struct ureg_src
ureg_DECL_resource(struct ureg_program *,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w );
static INLINE struct ureg_src static INLINE struct ureg_src
ureg_imm4f( struct ureg_program *ureg, ureg_imm4f( struct ureg_program *ureg,
@@ -733,6 +742,66 @@ static INLINE void ureg_##op( struct ureg_program *ureg, \
} }
#define OP14( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
#define OP15( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3, \
struct ureg_src src4 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
5).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_emit_src( ureg, src4 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
/* Use a template include to generate a correctly-typed ureg_OP() /* Use a template include to generate a correctly-typed ureg_OP()
* function for each TGSI opcode: * function for each TGSI opcode:
*/ */

View File

@@ -1250,6 +1250,110 @@ This opcode is the inverse of :opcode:`DFRACEXP`.
dst.zw = \sqrt{src.zw} dst.zw = \sqrt{src.zw}
.. _resourceopcodes:
Resource Access Opcodes
^^^^^^^^^^^^^^^^^^^^^^^^
Those opcodes follow very closely semantics of the respective Direct3D
instructions. If in doubt double check Direct3D documentation.
.. opcode:: LOAD - Simplified alternative to the "SAMPLE" instruction.
Using the provided integer address, LOAD fetches data
from the specified buffer/texture without any filtering.
The source data may come from any resource type other
than CUBE.
LOAD dst, address, resource
e.g.
LOAD TEMP[0], TEMP[1], RES[0]
.. opcode:: LOAD_MS - Just like LOAD but allows fetch data from
multi-sampled surfaces.
.. opcode:: SAMPLE - Using provided address, sample data from the
specified texture using the filtering mode identified
by the gven sampler. The source data may come from
any resource type other than buffers.
SAMPLE dst, address, resource, sampler
e.g.
SAMPLE TEMP[0], TEMP[1], RES[0], SAMP[0]
.. opcode:: SAMPLE_B - Just like the SAMPLE instruction with the
exception that an additiona bias is applied to the
level of detail computed as part of the instruction
execution.
SAMPLE_B dst, address, resource, sampler, lod_bias
e.g.
SAMPLE_B TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2].x
.. opcode:: SAMPLE_C - Similar to the SAMPLE instruction but it
performs a comparison filter. The operands to SAMPLE_C
are identical to SAMPLE, except that tere is an additional
float32 operand, reference value, which must be a register
with single-component, or a scalar literal.
SAMPLE_C makes the hardware use the current samplers
compare_func (in pipe_sampler_state) to compare
reference value against the red component value for the
surce resource at each texel that the currently configured
texture filter covers based on the provided coordinates.
SAMPLE_C dst, address, resource.r, sampler, ref_value
e.g.
SAMPLE_C TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
.. opcode:: SAMPLE_C_LZ - Same as SAMPLE_C, but LOD is 0 and derivatives
are ignored. The LZ stands for level-zero.
SAMPLE_C_LZ dst, address, resource.r, sampler, ref_value
e.g.
SAMPLE_C_LZ TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
.. opcode:: SAMPLE_D - SAMPLE_D is identical to the SAMPLE opcode except
that the derivatives for the source address in the x
direction and the y direction are provided by extra
parameters.
SAMPLE_D dst, address, resource, sampler, der_x, der_y
e.g.
SAMPLE_D TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2], TEMP[3]
.. opcode:: SAMPLE_L - SAMPLE_L is identical to the SAMPLE opcode except
that the LOD is provided directly as a scalar value,
representing no anisotropy. Source addresses A channel
is used as the LOD.
SAMPLE_L dst, address, resource, sampler
e.g.
SAMPLE_L TEMP[0], TEMP[1], RES[0], SAMP[0]
.. opcode:: GATHER4 - Gathers the four texels to be used in a bi-linear
filtering operation and packs them into a single register.
Only woth with 2D, 2D array, cubemaps, and cubemaps arrays.
For 2D textures, only the addressing modes of the sampler and
the top level of any mip pyramid are used. Set W to zero.
It behaves like the SAMPLE instruction, but a filtered
sample is not generated. The four samples that contribute
to filtering are places into xyzw in cunter-clockwise order,
starting with the (u,v) texture coordinate delta at the
following locations (-, +), (+, +), (+, -), (-, -), where
the magnitude of the deltas are half a texel.
.. opcode:: RESINFO - query the dimentions of a given input buffer.
dst receives width, height, depth or array size and
total mip count (also can be slected by writemask).
RESINFO dst, src_mip_level, resource
e.g.
RESINFO TEMP[0], TEMP[1].x, RES[0]
.. opcode:: SAMPLE_POS - query the position of a given sample.
dst receives float4 (x, y, 0, 0) indicated where the
sample is located. If the resource is not a multi-sample
resource and not a render target, the result is 0.
.. opcode:: SAMPLE_INFO - dst receives number of components in x.
If the resource is not a multi-sample resource and
not a render target, the result is 0.
Explanation of symbols used Explanation of symbols used
------------------------------ ------------------------------
@@ -1332,6 +1436,8 @@ wrapping when interpolating by the rasteriser. If TGSI_CYLINDRICAL_WRAP_X
is set to 1, the X component should be interpolated according to cylindrical is set to 1, the X component should be interpolated according to cylindrical
wrapping rules. wrapping rules.
If file is TGSI_FILE_RESOURCE, a Declaration Resource token follows.
Declaration Semantic Declaration Semantic
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1475,6 +1581,23 @@ is a writable stencil reference value. Only the Y component is writable.
This allows the fragment shader to change the fragments stencilref value. This allows the fragment shader to change the fragments stencilref value.
Declaration Resource
^^^^^^^^^^^^^^^^^^^^^^^^
Follows Declaration token if file is TGSI_FILE_RESOURCE.
DCL RES[#], resource, type(s)
Declares a shader input resource and assigns it to a RES[#]
register.
resource can be one of BUFFER, 1D, 2D, 3D, CUBE, 1DArray and
2DArray.
type must be 1 or 4 entries (if specifying on a per-component
level) out of UNORM, SNORM, SINT, UINT and FLOAT.
Properties Properties
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -33,6 +33,16 @@
extern "C" { extern "C" {
#endif #endif
enum pipe_type {
PIPE_TYPE_UNORM = 0,
PIPE_TYPE_SNORM,
PIPE_TYPE_SINT,
PIPE_TYPE_UINT,
PIPE_TYPE_FLOAT,
PIPE_TYPE_COUNT
};
/** /**
* Texture/surface image formats (preliminary) * Texture/surface image formats (preliminary)
*/ */

View File

@@ -75,6 +75,7 @@ enum tgsi_file_type {
TGSI_FILE_SYSTEM_VALUE =9, TGSI_FILE_SYSTEM_VALUE =9,
TGSI_FILE_IMMEDIATE_ARRAY =10, TGSI_FILE_IMMEDIATE_ARRAY =10,
TGSI_FILE_TEMPORARY_ARRAY =11, TGSI_FILE_TEMPORARY_ARRAY =11,
TGSI_FILE_RESOURCE =12,
TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */ TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */
}; };
@@ -153,6 +154,14 @@ struct tgsi_declaration_semantic
unsigned Padding : 8; unsigned Padding : 8;
}; };
struct tgsi_declaration_resource {
unsigned Resource : 8; /**< one of TGSI_TEXTURE_ */
unsigned ReturnTypeX : 6; /**< one of enum pipe_type */
unsigned ReturnTypeY : 6; /**< one of enum pipe_type */
unsigned ReturnTypeZ : 6; /**< one of enum pipe_type */
unsigned ReturnTypeW : 6; /**< one of enum pipe_type */
};
#define TGSI_IMM_FLOAT32 0 #define TGSI_IMM_FLOAT32 0
#define TGSI_IMM_UINT32 1 #define TGSI_IMM_UINT32 1
#define TGSI_IMM_INT32 2 #define TGSI_IMM_INT32 2
@@ -339,7 +348,22 @@ struct tgsi_property_data {
#define TGSI_OPCODE_CASE 142 #define TGSI_OPCODE_CASE 142
#define TGSI_OPCODE_DEFAULT 143 #define TGSI_OPCODE_DEFAULT 143
#define TGSI_OPCODE_ENDSWITCH 144 #define TGSI_OPCODE_ENDSWITCH 144
#define TGSI_OPCODE_LAST 145
/* resource related opcodes */
#define TGSI_OPCODE_LOAD 145
#define TGSI_OPCODE_LOAD_MS 146
#define TGSI_OPCODE_SAMPLE 147
#define TGSI_OPCODE_SAMPLE_B 148
#define TGSI_OPCODE_SAMPLE_C 149
#define TGSI_OPCODE_SAMPLE_C_LZ 150
#define TGSI_OPCODE_SAMPLE_D 151
#define TGSI_OPCODE_SAMPLE_L 152
#define TGSI_OPCODE_GATHER4 153
#define TGSI_OPCODE_RESINFO 154
#define TGSI_OPCODE_SAMPLE_POS 155
#define TGSI_OPCODE_SAMPLE_INFO 156
#define TGSI_OPCODE_LAST 157
#define TGSI_SAT_NONE 0 /* do not saturate */ #define TGSI_SAT_NONE 0 /* do not saturate */
#define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */ #define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */

View File

@@ -62,6 +62,7 @@ extern "C" {
#define PIPE_MAX_GEOMETRY_SAMPLERS 16 #define PIPE_MAX_GEOMETRY_SAMPLERS 16
#define PIPE_MAX_SHADER_INPUTS 32 #define PIPE_MAX_SHADER_INPUTS 32
#define PIPE_MAX_SHADER_OUTPUTS 32 #define PIPE_MAX_SHADER_OUTPUTS 32
#define PIPE_MAX_SHADER_RESOURCES 32
#define PIPE_MAX_TEXTURE_LEVELS 16 #define PIPE_MAX_TEXTURE_LEVELS 16
#define PIPE_MAX_SO_BUFFERS 4 #define PIPE_MAX_SO_BUFFERS 4

View File

@@ -24,6 +24,7 @@ progs = [
'gs-test', 'gs-test',
'shader-leak', 'shader-leak',
'tri-gs', 'tri-gs',
'quad-sample',
] ]
for name in progs: for name in progs: