gallium: add new LOD opcode

The operation performed is all the same as LODQ, but with the usual
differences between dx10 and GL texture opcodes, that is separate resource
and sampler indices (plus result swizzling, and setting z/w channels
to zero).

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Acked-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
Roland Scheidegger 2017-09-28 03:45:04 +02:00
parent d5e7ce28b5
commit 740a1618c3
5 changed files with 74 additions and 5 deletions

View file

@ -3284,6 +3284,18 @@ sviewinfo_emit(
emit_size_query(bld, emit_data->inst, emit_data->output, TRUE);
}
static void
lod_emit(
const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
struct lp_build_emit_data * emit_data)
{
struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
emit_sample(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_NONE,
FALSE, LP_SAMPLER_OP_LODQ, emit_data->output);
}
static LLVMValueRef
mask_vec(struct lp_build_tgsi_context *bld_base)
{
@ -3898,6 +3910,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_L].emit = sample_l_emit;
bld.bld_base.op_actions[TGSI_OPCODE_GATHER4].emit = gather4_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SVIEWINFO].emit = sviewinfo_emit;
bld.bld_base.op_actions[TGSI_OPCODE_LOD].emit = lod_emit;
if (gs_iface) {
/* There's no specific value for this because it should always

View file

@ -2351,15 +2351,22 @@ static void
exec_lodq(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint unit;
uint resource_unit, sampler_unit;
int dim;
int i;
union tgsi_exec_channel coords[4];
const union tgsi_exec_channel *args[ARRAY_SIZE(coords)];
union tgsi_exec_channel r[2];
unit = fetch_sampler_unit(mach, inst, 1);
dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
resource_unit = fetch_sampler_unit(mach, inst, 1);
if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
uint target = mach->SamplerViews[resource_unit].Resource;
dim = tgsi_util_get_texture_coord_dim(target);
sampler_unit = fetch_sampler_unit(mach, inst, 2);
} else {
dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture);
sampler_unit = resource_unit;
}
assert(dim <= ARRAY_SIZE(coords));
/* fetch coordinates */
for (i = 0; i < dim; i++) {
@ -2369,7 +2376,7 @@ exec_lodq(struct tgsi_exec_machine *mach,
for (i = dim; i < ARRAY_SIZE(coords); i++) {
args[i] = &ZeroVec;
}
mach->Sampler->query_lod(mach->Sampler, unit, unit,
mach->Sampler->query_lod(mach->Sampler, resource_unit, sampler_unit,
args[0]->f,
args[1]->f,
args[2]->f,
@ -2386,6 +2393,35 @@ exec_lodq(struct tgsi_exec_machine *mach,
store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
TGSI_EXEC_DATA_FLOAT);
}
if (inst->Instruction.Opcode == TGSI_OPCODE_LOD) {
unsigned char swizzles[4];
unsigned chan;
swizzles[0] = inst->Src[1].Register.SwizzleX;
swizzles[1] = inst->Src[1].Register.SwizzleY;
swizzles[2] = inst->Src[1].Register.SwizzleZ;
swizzles[3] = inst->Src[1].Register.SwizzleW;
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
if (swizzles[chan] >= 2) {
store_dest(mach, &ZeroVec,
&inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
} else {
store_dest(mach, &r[swizzles[chan]],
&inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
} else {
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X,
TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Y,
TGSI_EXEC_DATA_FLOAT);
}
}
}
static void
@ -5718,6 +5754,10 @@ exec_instruction(
assert(0);
break;
case TGSI_OPCODE_LOD:
exec_lodq(mach, inst);
break;
case TGSI_OPCODE_UARL:
exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT);
break;

View file

@ -249,3 +249,4 @@ OPCODE(1, 2, COMP, U64DIV)
OPCODE(1, 2, COMP, I64MOD)
OPCODE(1, 2, COMP, U64MOD)
OPCODE(1, 2, COMP, DDIV)
OPCODE(1, 3, OTHR, LOD)

View file

@ -2479,6 +2479,18 @@ after lookup.
NOTE: no driver has implemented this opcode yet (and no state tracker
emits it). This information is subject to change.
.. opcode:: LOD - level of detail
Same syntax as the SAMPLE opcode but instead of performing an actual
texture lookup/filter, return the computed LOD information that the
texture pipe would use to access the texture. The Y component contains
the computed LOD lambda_prime. The X component contains the LOD that will
be accessed, based on min/max lod's and mipmap filters.
The Z and W components are set to 0.
Syntax: ``LOD dst, address, sampler_view, sampler``
.. _resourceopcodes:
Resource Access Opcodes

View file

@ -607,7 +607,9 @@ struct tgsi_property_data {
#define TGSI_OPCODE_DDIV 248
#define TGSI_OPCODE_LAST 249
#define TGSI_OPCODE_LOD 249
#define TGSI_OPCODE_LAST 250
/**
* Opcode is the operation code to execute. A given operation defines the