svga: add support for sample id, sample position

Sample ID is just a system value.  Sample position must be implemented
with the VGPU10_OPCODE_SAMPLE_POS instruction.

Reviewed-by: Charmaine Lee <charmainel@vmware.com>
This commit is contained in:
Brian Paul 2017-07-31 21:12:07 -06:00
parent ac4a0c0e82
commit 0a219dd918

View file

@ -185,6 +185,11 @@ struct svga_shader_emitter_v10
/** Which texture units are doing shadow comparison in the FS code */
unsigned shadow_compare_units;
unsigned sample_id_sys_index; /**< TGSI index of sample id sys value */
unsigned sample_pos_sys_index; /**< TGSI index of sample pos sys value */
unsigned sample_pos_tmp_index; /**< which temp reg has the sample pos */
} fs;
/* For geometry shaders only */
@ -644,6 +649,19 @@ translate_opcode(enum tgsi_opcode opcode)
return VGPU10_OPCODE_LT;
case TGSI_OPCODE_ROUND:
return VGPU10_OPCODE_ROUND_NE;
case TGSI_OPCODE_SAMPLE_POS:
/* Note: we never actually get this opcode because there's no GLSL
* function to query multisample resource sample positions. There's
* only the TGSI_SEMANTIC_SAMPLEPOS system value which contains the
* position of the current sample in the render target.
*/
/* FALL-THROUGH */
case TGSI_OPCODE_SAMPLE_INFO:
/* NOTE: we never actually get this opcode because the GLSL compiler
* implements the gl_NumSamples variable with a simple constant in the
* constant buffer.
*/
/* FALL-THROUGH */
default:
assert(!"Unexpected TGSI opcode in translate_opcode()");
return VGPU10_OPCODE_NOP;
@ -965,6 +983,9 @@ emit_dst_register(struct svga_shader_emitter_v10 *emit,
/**
* Translate a src register of a TGSI instruction and emit VGPU10 tokens.
* In quite a few cases, we do register substitution. For example, if
* the TGSI register is the front/back-face register, we replace that with
* a temp register containing a value we computed earlier.
*/
static void
emit_src_register(struct svga_shader_emitter_v10 *emit,
@ -1005,6 +1026,20 @@ emit_src_register(struct svga_shader_emitter_v10 *emit,
index = emit->linkage.input_map[index];
}
}
else if (file == TGSI_FILE_SYSTEM_VALUE) {
if (index == emit->fs.sample_pos_sys_index) {
assert(emit->version >= 41);
/* Current sample position is in a temp register */
file = TGSI_FILE_TEMPORARY;
index = emit->fs.sample_pos_tmp_index;
}
else {
/* Map the TGSI system value to a VGPU10 input register */
assert(index < ARRAY_SIZE(emit->system_value_indexes));
file = TGSI_FILE_INPUT;
index = emit->system_value_indexes[index];
}
}
}
else if (emit->unit == PIPE_SHADER_GEOMETRY) {
if (file == TGSI_FILE_INPUT) {
@ -1195,6 +1230,32 @@ emit_face_register(struct svga_shader_emitter_v10 *emit)
}
/**
* Emit tokens for the "rasterizer" register used by the SAMPLE_POS
* instruction.
*/
static void
emit_rasterizer_register(struct svga_shader_emitter_v10 *emit)
{
VGPU10OperandToken0 operand0;
/* init */
operand0.value = 0;
/* No register index for rasterizer index (there's only one) */
operand0.operandType = VGPU10_OPERAND_TYPE_RASTERIZER;
operand0.indexDimension = VGPU10_OPERAND_INDEX_0D;
operand0.numComponents = VGPU10_OPERAND_4_COMPONENT;
operand0.selectionMode = VGPU10_OPERAND_4_COMPONENT_SWIZZLE_MODE;
operand0.swizzleX = VGPU10_COMPONENT_X;
operand0.swizzleY = VGPU10_COMPONENT_Y;
operand0.swizzleZ = VGPU10_COMPONENT_Z;
operand0.swizzleW = VGPU10_COMPONENT_W;
emit_dword(emit, operand0.value);
}
/**
* Emit the token for a VGPU10 opcode.
* \param saturate clamp result to [0,1]?
@ -1384,6 +1445,29 @@ make_src_reg(enum tgsi_file_type file, unsigned index)
}
/**
* Create a tgsi_full_src_register with a swizzle such that all four
* vector components have the same scalar value.
*/
static struct tgsi_full_src_register
make_src_scalar_reg(enum tgsi_file_type file, unsigned index, unsigned component)
{
struct tgsi_full_src_register reg;
assert(component >= TGSI_SWIZZLE_X);
assert(component <= TGSI_SWIZZLE_W);
memset(&reg, 0, sizeof(reg));
reg.Register.File = file;
reg.Register.Index = index;
reg.Register.SwizzleX =
reg.Register.SwizzleY =
reg.Register.SwizzleZ =
reg.Register.SwizzleW = component;
return reg;
}
/**
* Create a tgsi_full_src_register for a temporary.
*/
@ -2074,6 +2158,7 @@ emit_input_declaration(struct svga_shader_emitter_v10 *emit,
assert(opcodeType == VGPU10_OPCODE_DCL_INPUT ||
opcodeType == VGPU10_OPCODE_DCL_INPUT_SIV ||
opcodeType == VGPU10_OPCODE_DCL_INPUT_PS ||
opcodeType == VGPU10_OPCODE_DCL_INPUT_PS_SIV ||
opcodeType == VGPU10_OPCODE_DCL_INPUT_PS_SGV);
assert(operandType == VGPU10_OPERAND_TYPE_INPUT ||
operandType == VGPU10_OPERAND_TYPE_INPUT_PRIMITIVEID);
@ -2085,7 +2170,9 @@ emit_input_declaration(struct svga_shader_emitter_v10 *emit,
name == VGPU10_NAME_INSTANCE_ID ||
name == VGPU10_NAME_VERTEX_ID ||
name == VGPU10_NAME_PRIMITIVE_ID ||
name == VGPU10_NAME_IS_FRONT_FACE);
name == VGPU10_NAME_IS_FRONT_FACE ||
name == VGPU10_NAME_SAMPLE_INDEX);
assert(interpMode == VGPU10_INTERPOLATION_UNDEFINED ||
interpMode == VGPU10_INTERPOLATION_CONSTANT ||
interpMode == VGPU10_INTERPOLATION_LINEAR ||
@ -2216,8 +2303,33 @@ emit_system_value_declaration(struct svga_shader_emitter_v10 *emit,
VGPU10_OPERAND_4_COMPONENT_MASK_X,
VGPU10_INTERPOLATION_UNDEFINED);
break;
case TGSI_SEMANTIC_SAMPLEID:
assert(emit->unit == PIPE_SHADER_FRAGMENT);
emit->fs.sample_id_sys_index = index;
index = alloc_system_value_index(emit, index);
emit_input_declaration(emit, VGPU10_OPCODE_DCL_INPUT_PS_SIV,
VGPU10_OPERAND_TYPE_INPUT,
VGPU10_OPERAND_INDEX_1D,
index, 1,
VGPU10_NAME_SAMPLE_INDEX,
VGPU10_OPERAND_4_COMPONENT,
VGPU10_OPERAND_4_COMPONENT_MASK_MODE,
VGPU10_OPERAND_4_COMPONENT_MASK_X,
VGPU10_INTERPOLATION_CONSTANT);
break;
case TGSI_SEMANTIC_SAMPLEPOS:
/* This system value contains the position of the current sample
* when using per-sample shading. We implement this by calling
* the VGPU10_OPCODE_SAMPLE_POS instruction with the current sample
* index as the argument. See emit_sample_position_instructions().
*/
assert(emit->version >= 41);
index = alloc_system_value_index(emit, index);
emit->fs.sample_pos_sys_index = index;
break;
default:
; /* XXX */
debug_printf("unexpected sytem value semantic index %u\n",
semantic_name);
}
}
@ -2390,6 +2502,12 @@ emit_input_declarations(struct svga_shader_emitter_v10 *emit)
interpolationMode = VGPU10_INTERPOLATION_CONSTANT;
name = VGPU10_NAME_PRIMITIVE_ID;
}
else if (semantic_name == TGSI_SEMANTIC_SAMPLEID) {
/* sample index / ID */
type = VGPU10_OPCODE_DCL_INPUT_PS_SGV;
interpolationMode = VGPU10_INTERPOLATION_CONSTANT;
name = VGPU10_NAME_SAMPLE_INDEX;
}
else {
/* general fragment input */
type = VGPU10_OPCODE_DCL_INPUT_PS;
@ -2747,6 +2865,11 @@ emit_temporaries_declaration(struct svga_shader_emitter_v10 *emit)
emit->fs.fragcoord_tmp_index = total_temps;
total_temps += 1;
}
if (emit->fs.sample_pos_sys_index != INVALID_INDEX) {
/* Allocate a temp for the sample position */
emit->fs.sample_pos_tmp_index = total_temps++;
}
}
for (i = 0; i < emit->num_address_regs; i++) {
@ -6010,6 +6133,55 @@ emit_fragcoord_instructions(struct svga_shader_emitter_v10 *emit)
}
/**
* Emit the extra code to get the current sample position value and
* put it into a temp register.
*/
static void
emit_sample_position_instructions(struct svga_shader_emitter_v10 *emit)
{
assert(emit->unit == PIPE_SHADER_FRAGMENT);
if (emit->fs.sample_pos_sys_index != INVALID_INDEX) {
assert(emit->version >= 41);
struct tgsi_full_dst_register tmp_dst =
make_dst_temp_reg(emit->fs.sample_pos_tmp_index);
struct tgsi_full_src_register half =
make_immediate_reg_float4(emit, 0.5, 0.5, 0.0, 0.0);
struct tgsi_full_src_register tmp_src =
make_src_temp_reg(emit->fs.sample_pos_tmp_index);
struct tgsi_full_src_register sample_index_reg =
make_src_scalar_reg(TGSI_FILE_SYSTEM_VALUE,
emit->fs.sample_id_sys_index, TGSI_SWIZZLE_X);
/* The first src register is a shader resource (if we want a
* multisampled resource sample position) or the rasterizer register
* (if we want the current sample position in the color buffer). We
* want the later.
*/
/* SAMPLE_POS dst, RASTERIZER, sampleIndex */
begin_emit_instruction(emit);
emit_opcode(emit, VGPU10_OPCODE_SAMPLE_POS, FALSE);
emit_dst_register(emit, &tmp_dst);
emit_rasterizer_register(emit);
emit_src_register(emit, &sample_index_reg);
end_emit_instruction(emit);
/* Convert from D3D coords to GL coords by adding 0.5 bias */
/* ADD dst, dst, half */
begin_emit_instruction(emit);
emit_opcode(emit, VGPU10_OPCODE_ADD, FALSE);
emit_dst_register(emit, &tmp_dst);
emit_src_register(emit, &tmp_src);
emit_src_register(emit, &half);
end_emit_instruction(emit);
}
}
/**
* Emit extra instructions to adjust VS inputs/attributes. This can
* mean casting a vertex attribute from int to float or setting the
@ -6229,6 +6401,7 @@ emit_pre_helpers(struct svga_shader_emitter_v10 *emit)
if (emit->unit == PIPE_SHADER_FRAGMENT) {
emit_frontface_instructions(emit);
emit_fragcoord_instructions(emit);
emit_sample_position_instructions(emit);
}
else if (emit->unit == PIPE_SHADER_VERTEX) {
emit_vertex_attrib_instructions(emit);
@ -6625,6 +6798,8 @@ svga_tgsi_vgpu10_translate(struct svga_context *svga,
emit->fs.color_tmp_index = INVALID_INDEX;
emit->fs.face_input_index = INVALID_INDEX;
emit->fs.fragcoord_input_index = INVALID_INDEX;
emit->fs.sample_id_sys_index = INVALID_INDEX;
emit->fs.sample_pos_sys_index = INVALID_INDEX;
emit->gs.prim_id_index = INVALID_INDEX;