mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-05 16:40:31 +01:00
tgsi: add support for image operations to tgsi_exec. (v2.1)
This adds support for load/store/atomic operations on images along with image tracking support. v2: add RESQ support. (Ilia) v2.1: constify interface (Brian) split get_image_coord_dim (Brian) Reviewed-by: Brian Paul <brianp@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
493eab7679
commit
22d1296013
5 changed files with 319 additions and 6 deletions
|
|
@ -681,7 +681,7 @@ void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
|
|||
if (!use_llvm && shader && shader->machine->Tokens != shader->state.tokens) {
|
||||
tgsi_exec_machine_bind_shader(shader->machine,
|
||||
shader->state.tokens,
|
||||
draw->gs.tgsi.sampler);
|
||||
draw->gs.tgsi.sampler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ vs_exec_prepare( struct draw_vertex_shader *shader,
|
|||
if (evs->machine->Tokens != shader->state.tokens) {
|
||||
tgsi_exec_machine_bind_shader(evs->machine,
|
||||
shader->state.tokens,
|
||||
draw->vs.tgsi.sampler);
|
||||
draw->vs.tgsi.sampler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -853,7 +853,8 @@ void
|
|||
tgsi_exec_machine_bind_shader(
|
||||
struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_token *tokens,
|
||||
struct tgsi_sampler *sampler)
|
||||
struct tgsi_sampler *sampler,
|
||||
struct tgsi_image *image)
|
||||
{
|
||||
uint k;
|
||||
struct tgsi_parse_context parse;
|
||||
|
|
@ -871,6 +872,7 @@ tgsi_exec_machine_bind_shader(
|
|||
|
||||
mach->Tokens = tokens;
|
||||
mach->Sampler = sampler;
|
||||
mach->Image = image;
|
||||
|
||||
if (!tokens) {
|
||||
/* unbind and free all */
|
||||
|
|
@ -3706,6 +3708,247 @@ exec_dfracexp(struct tgsi_exec_machine *mach,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_image_coord_dim(unsigned tgsi_tex)
|
||||
{
|
||||
int dim;
|
||||
switch (tgsi_tex) {
|
||||
case TGSI_TEXTURE_BUFFER:
|
||||
case TGSI_TEXTURE_1D:
|
||||
dim = 1;
|
||||
break;
|
||||
case TGSI_TEXTURE_2D:
|
||||
case TGSI_TEXTURE_RECT:
|
||||
case TGSI_TEXTURE_1D_ARRAY:
|
||||
case TGSI_TEXTURE_2D_MSAA:
|
||||
dim = 2;
|
||||
break;
|
||||
case TGSI_TEXTURE_3D:
|
||||
case TGSI_TEXTURE_CUBE:
|
||||
case TGSI_TEXTURE_2D_ARRAY:
|
||||
case TGSI_TEXTURE_2D_ARRAY_MSAA:
|
||||
case TGSI_TEXTURE_CUBE_ARRAY:
|
||||
dim = 3;
|
||||
break;
|
||||
default:
|
||||
assert(!"unknown texture target");
|
||||
dim = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
static int
|
||||
get_image_coord_sample(unsigned tgsi_tex)
|
||||
{
|
||||
int sample = 0;
|
||||
switch (tgsi_tex) {
|
||||
case TGSI_TEXTURE_2D_MSAA:
|
||||
sample = 3;
|
||||
break;
|
||||
case TGSI_TEXTURE_2D_ARRAY_MSAA:
|
||||
sample = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return sample;
|
||||
}
|
||||
|
||||
static void
|
||||
exec_load(struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_full_instruction *inst)
|
||||
{
|
||||
union tgsi_exec_channel r[4], sample_r;
|
||||
uint unit;
|
||||
int sample;
|
||||
int i, j;
|
||||
int dim;
|
||||
uint chan;
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
|
||||
struct tgsi_image_params params;
|
||||
int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
|
||||
|
||||
unit = fetch_sampler_unit(mach, inst, 0);
|
||||
dim = get_image_coord_dim(inst->Memory.Texture);
|
||||
sample = get_image_coord_sample(inst->Memory.Texture);
|
||||
assert(dim <= 3);
|
||||
|
||||
params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
|
||||
params.unit = unit;
|
||||
params.tgsi_tex_instr = inst->Memory.Texture;
|
||||
params.format = inst->Memory.Format;
|
||||
|
||||
for (i = 0; i < dim; i++) {
|
||||
IFETCH(&r[i], 1, TGSI_CHAN_X + i);
|
||||
}
|
||||
|
||||
if (sample)
|
||||
IFETCH(&sample_r, 1, TGSI_CHAN_X + sample);
|
||||
|
||||
mach->Image->load(mach->Image, ¶ms,
|
||||
r[0].i, r[1].i, r[2].i, sample_r.i,
|
||||
rgba);
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
r[0].f[j] = rgba[0][j];
|
||||
r[1].f[j] = rgba[1][j];
|
||||
r[2].f[j] = rgba[2][j];
|
||||
r[3].f[j] = rgba[3][j];
|
||||
}
|
||||
for (chan = 0; chan < TGSI_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_store(struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_full_instruction *inst)
|
||||
{
|
||||
union tgsi_exec_channel r[3], sample_r;
|
||||
union tgsi_exec_channel value[4];
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
|
||||
struct tgsi_image_params params;
|
||||
int dim;
|
||||
int sample;
|
||||
int i, j;
|
||||
uint unit;
|
||||
int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
|
||||
unit = inst->Dst[0].Register.Index;
|
||||
dim = get_image_coord_dim(inst->Memory.Texture);
|
||||
sample = get_image_coord_sample(inst->Memory.Texture);
|
||||
assert(dim <= 3);
|
||||
|
||||
params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
|
||||
params.unit = unit;
|
||||
params.tgsi_tex_instr = inst->Memory.Texture;
|
||||
params.format = inst->Memory.Format;
|
||||
|
||||
for (i = 0; i < dim; i++) {
|
||||
IFETCH(&r[i], 0, TGSI_CHAN_X + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
FETCH(&value[i], 1, TGSI_CHAN_X + i);
|
||||
}
|
||||
if (sample)
|
||||
IFETCH(&sample_r, 0, TGSI_CHAN_X + sample);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
rgba[0][j] = value[0].f[j];
|
||||
rgba[1][j] = value[1].f[j];
|
||||
rgba[2][j] = value[2].f[j];
|
||||
rgba[3][j] = value[3].f[j];
|
||||
}
|
||||
|
||||
mach->Image->store(mach->Image, ¶ms,
|
||||
r[0].i, r[1].i, r[2].i, sample_r.i,
|
||||
rgba);
|
||||
}
|
||||
|
||||
static void
|
||||
exec_atomop(struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_full_instruction *inst)
|
||||
{
|
||||
union tgsi_exec_channel r[3], sample_r;
|
||||
union tgsi_exec_channel value[4], value2[4];
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
|
||||
float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
|
||||
struct tgsi_image_params params;
|
||||
int dim;
|
||||
int sample;
|
||||
int i, j;
|
||||
uint unit, chan;
|
||||
int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
|
||||
unit = fetch_sampler_unit(mach, inst, 0);
|
||||
dim = get_image_coord_dim(inst->Memory.Texture);
|
||||
sample = get_image_coord_sample(inst->Memory.Texture);
|
||||
assert(dim <= 3);
|
||||
|
||||
params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
|
||||
params.unit = unit;
|
||||
params.tgsi_tex_instr = inst->Memory.Texture;
|
||||
params.format = inst->Memory.Format;
|
||||
|
||||
for (i = 0; i < dim; i++) {
|
||||
IFETCH(&r[i], 1, TGSI_CHAN_X + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
FETCH(&value[i], 2, TGSI_CHAN_X + i);
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS)
|
||||
FETCH(&value2[i], 3, TGSI_CHAN_X + i);
|
||||
}
|
||||
if (sample)
|
||||
IFETCH(&sample_r, 1, TGSI_CHAN_X + sample);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
rgba[0][j] = value[0].f[j];
|
||||
rgba[1][j] = value[1].f[j];
|
||||
rgba[2][j] = value[2].f[j];
|
||||
rgba[3][j] = value[3].f[j];
|
||||
}
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS) {
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
rgba2[0][j] = value2[0].f[j];
|
||||
rgba2[1][j] = value2[1].f[j];
|
||||
rgba2[2][j] = value2[2].f[j];
|
||||
rgba2[3][j] = value2[3].f[j];
|
||||
}
|
||||
}
|
||||
|
||||
mach->Image->op(mach->Image, ¶ms, inst->Instruction.Opcode,
|
||||
r[0].i, r[1].i, r[2].i, sample_r.i,
|
||||
rgba, rgba2);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
r[0].f[j] = rgba[0][j];
|
||||
r[1].f[j] = rgba[1][j];
|
||||
r[2].f[j] = rgba[2][j];
|
||||
r[3].f[j] = rgba[3][j];
|
||||
}
|
||||
for (chan = 0; chan < TGSI_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_resq(struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_full_instruction *inst)
|
||||
{
|
||||
int result[4];
|
||||
union tgsi_exec_channel r[4];
|
||||
uint unit;
|
||||
int i, chan, j;
|
||||
struct tgsi_image_params params;
|
||||
int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
|
||||
|
||||
unit = fetch_sampler_unit(mach, inst, 0);
|
||||
|
||||
params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
|
||||
params.unit = unit;
|
||||
params.tgsi_tex_instr = inst->Memory.Texture;
|
||||
params.format = inst->Memory.Format;
|
||||
|
||||
mach->Image->get_dims(mach->Image, ¶ms, result);
|
||||
|
||||
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
r[j].i[i] = result[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
|
||||
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
|
||||
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan,
|
||||
TGSI_EXEC_DATA_INT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
micro_i2f(union tgsi_exec_channel *dst,
|
||||
|
|
@ -5172,6 +5415,34 @@ exec_instruction(
|
|||
case TGSI_OPCODE_D2U:
|
||||
exec_d2u(mach, inst);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_LOAD:
|
||||
exec_load(mach, inst);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_STORE:
|
||||
exec_store(mach, inst);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ATOMUADD:
|
||||
case TGSI_OPCODE_ATOMXCHG:
|
||||
case TGSI_OPCODE_ATOMCAS:
|
||||
case TGSI_OPCODE_ATOMAND:
|
||||
case TGSI_OPCODE_ATOMOR:
|
||||
case TGSI_OPCODE_ATOMXOR:
|
||||
case TGSI_OPCODE_ATOMUMIN:
|
||||
case TGSI_OPCODE_ATOMUMAX:
|
||||
case TGSI_OPCODE_ATOMIMIN:
|
||||
case TGSI_OPCODE_ATOMIMAX:
|
||||
exec_atomop(mach, inst);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_RESQ:
|
||||
exec_resq(mach, inst);
|
||||
break;
|
||||
case TGSI_OPCODE_BARRIER:
|
||||
case TGSI_OPCODE_MEMBAR:
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,46 @@ enum tgsi_sampler_control
|
|||
TGSI_SAMPLER_GATHER,
|
||||
};
|
||||
|
||||
struct tgsi_image_params {
|
||||
unsigned unit;
|
||||
unsigned tgsi_tex_instr;
|
||||
enum pipe_format format;
|
||||
unsigned execmask;
|
||||
};
|
||||
|
||||
struct tgsi_image {
|
||||
/* image interfaces */
|
||||
void (*load)(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
|
||||
|
||||
void (*store)(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
|
||||
|
||||
void (*op)(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
unsigned opcode,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
|
||||
float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
|
||||
|
||||
void (*get_dims)(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
int dims[4]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Information for sampling textures, which must be implemented
|
||||
* by code outside the TGSI executor.
|
||||
|
|
@ -293,6 +333,7 @@ struct tgsi_exec_machine
|
|||
|
||||
struct tgsi_sampler *Sampler;
|
||||
|
||||
struct tgsi_image *Image;
|
||||
unsigned ImmLimit;
|
||||
|
||||
const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
|
||||
|
|
@ -382,7 +423,8 @@ void
|
|||
tgsi_exec_machine_bind_shader(
|
||||
struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_token *tokens,
|
||||
struct tgsi_sampler *sampler);
|
||||
struct tgsi_sampler *sampler,
|
||||
struct tgsi_image *image);
|
||||
|
||||
uint
|
||||
tgsi_exec_machine_run(
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ exec_prepare( const struct sp_fragment_shader_variant *var,
|
|||
*/
|
||||
tgsi_exec_machine_bind_shader(machine,
|
||||
var->tokens,
|
||||
sampler);
|
||||
sampler, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ exec_delete(struct sp_fragment_shader_variant *var,
|
|||
struct tgsi_exec_machine *machine)
|
||||
{
|
||||
if (machine->Tokens == var->tokens) {
|
||||
tgsi_exec_machine_bind_shader(machine, NULL, NULL);
|
||||
tgsi_exec_machine_bind_shader(machine, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
FREE( (void *) var->tokens );
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue