[GPU] Handle two component tfetch1D coordinates
545407D4's UI shader uses tfetch1D with a nonreplicated source swizzle and a 2D constant. The way we have it set up is causing the translators to sample with Y set to 0. Handle this as 2D in the translators. Normal scalar tfetch1D untouched.
This commit is contained in:
committed by
Radosław Gliński
parent
fe40c0d68f
commit
fbdb1f2817
@@ -713,6 +713,11 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
}
|
||||
|
||||
uint32_t tfetch_index = instr.operands[1].storage_index;
|
||||
xenos::FetchOpDimension coordinate_dimension =
|
||||
instr.dimension == xenos::FetchOpDimension::k1D &&
|
||||
instr.operands[0].component_count > 1
|
||||
? xenos::FetchOpDimension::k2D
|
||||
: instr.dimension;
|
||||
|
||||
// Whether to use gradients (implicit or explicit) for LOD calculation.
|
||||
bool use_computed_lod =
|
||||
@@ -755,7 +760,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// be floored as expected, but the left/upper pixel is still sampled
|
||||
// instead.
|
||||
constexpr float rounding_offset = 1.5f / 1024.0f;
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
offsets[0] = instr.attributes.offset_x + rounding_offset;
|
||||
if (instr.opcode == FetchOpcode::kGetTextureWeights) {
|
||||
@@ -824,7 +829,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// calculation with normalized coordinates (or, if a texture filled with LOD
|
||||
// indices is used, coordinates will need to be normalized as normally).
|
||||
if (!instr.attributes.unnormalized_coordinates) {
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
size_needed_components |= used_result_nonzero_components & 0b0001;
|
||||
break;
|
||||
@@ -841,7 +846,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// Size needed for normalization (or, for stacked texture layers,
|
||||
// denormalization) and for offsets.
|
||||
size_needed_components |= offsets_not_zero;
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
if (instr.attributes.unnormalized_coordinates) {
|
||||
size_needed_components |= 0b0001;
|
||||
@@ -882,7 +887,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
uint32_t size_and_is_3d_temp =
|
||||
size_needed_components ? PushSystemTemp() : UINT32_MAX;
|
||||
if (size_needed_components) {
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
a_.OpUBFE(dxbc::Dest::R(size_and_is_3d_temp, 0b0001), dxbc::Src::LU(24),
|
||||
dxbc::Src::LU(0),
|
||||
@@ -1058,10 +1063,11 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
bool coord_operand_temp_pushed = false;
|
||||
dxbc::Src coord_operand = LoadOperand(
|
||||
instr.operands[0],
|
||||
(1 << xenos::GetFetchOpDimensionComponentCount(instr.dimension)) - 1,
|
||||
(1 << xenos::GetFetchOpDimensionComponentCount(coordinate_dimension)) -
|
||||
1,
|
||||
coord_operand_temp_pushed);
|
||||
uint32_t normalized_components = 0b0000;
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
normalized_components = 0b0001;
|
||||
break;
|
||||
@@ -1217,7 +1223,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
// Pad to 2D array coordinates.
|
||||
a_.OpMov(dxbc::Dest::R(coord_and_sampler_temp, 0b0110),
|
||||
@@ -1521,7 +1527,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
}
|
||||
if (use_computed_lod) {
|
||||
grad_v_temp = PushSystemTemp();
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
grad_component_count = 1;
|
||||
break;
|
||||
@@ -1615,7 +1621,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
|
||||
dxbc::Src::R(grad_v_temp), lod_src);
|
||||
#endif
|
||||
}
|
||||
if (instr.dimension == xenos::FetchOpDimension::k1D) {
|
||||
if (coordinate_dimension == xenos::FetchOpDimension::k1D) {
|
||||
// Pad the gradients to 2D because 1D textures are fetched as 2D
|
||||
// arrays.
|
||||
a_.OpMov(dxbc::Dest::R(grad_h_lod_temp, 0b0010),
|
||||
|
||||
@@ -1121,6 +1121,18 @@ void ParseTextureFetchInstruction(const TextureFetchInstruction& op,
|
||||
opcode_info.override_component_count
|
||||
? opcode_info.override_component_count
|
||||
: xenos::GetFetchOpDimensionComponentCount(op.dimension());
|
||||
if (op.opcode() == FetchOpcode::kTextureFetch &&
|
||||
op.dimension() == xenos::FetchOpDimension::k1D) {
|
||||
uint32_t src_swizzle = op.src_swizzle();
|
||||
uint32_t src_select_x = src_swizzle & 0x3;
|
||||
if (((src_swizzle >> 2) & 0x3) != src_select_x ||
|
||||
((src_swizzle >> 4) & 0x3) != src_select_x) {
|
||||
// 1D may provide XY for a 2D fetch constant. 545407D4's UI shader does
|
||||
// this, and it seems like we have to support it, even if it doesn't
|
||||
// make sense on paper.
|
||||
src_op.component_count = 2;
|
||||
}
|
||||
}
|
||||
uint32_t swizzle = op.src_swizzle();
|
||||
for (uint32_t j = 0; j < src_op.component_count; ++j, swizzle >>= 2) {
|
||||
src_op.components[j] = GetSwizzleFromComponentIndex(swizzle & 0x3);
|
||||
|
||||
@@ -659,6 +659,11 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
|
||||
uint32_t fetch_constant_index = instr.operands[1].storage_index;
|
||||
uint32_t fetch_constant_word_0_index = 6 * fetch_constant_index;
|
||||
xenos::FetchOpDimension coordinate_dimension =
|
||||
instr.dimension == xenos::FetchOpDimension::k1D &&
|
||||
instr.operands[0].component_count > 1
|
||||
? xenos::FetchOpDimension::k2D
|
||||
: instr.dimension;
|
||||
|
||||
spv::Id sampler = spv::NoResult;
|
||||
spv::Id image_2d_array_or_cube_unsigned = spv::NoResult;
|
||||
@@ -770,7 +775,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// `mul` gives a value that would be floored as expected, but the
|
||||
// left/upper pixel is still sampled instead.
|
||||
constexpr float kRoundingOffset = 1.5f / 1024.0f;
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
offset_values[0] = instr.attributes.offset_x + kRoundingOffset;
|
||||
if (instr.opcode == ucode::FetchOpcode::kGetTextureWeights) {
|
||||
@@ -847,7 +852,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// texture filled with LOD indices is used, coordinates will need to be
|
||||
// normalized as normally).
|
||||
if (!instr.attributes.unnormalized_coordinates) {
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
size_needed_components |= used_result_nonzero_components & 0b0001;
|
||||
break;
|
||||
@@ -864,7 +869,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// Size needed for normalization (or, for stacked texture layers,
|
||||
// denormalization) and for offsets.
|
||||
size_needed_components |= offsets_not_zero;
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D:
|
||||
if (instr.attributes.unnormalized_coordinates) {
|
||||
size_needed_components |= 0b0001;
|
||||
@@ -939,7 +944,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
spv::StorageClassUniform,
|
||||
uniform_fetch_constants_, id_vector_temp_),
|
||||
spv::NoPrecision);
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D: {
|
||||
if (size_needed_components & 0b1) {
|
||||
size[0] = builder_->createTriOp(
|
||||
@@ -1143,8 +1148,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
uint32_t coordinates_needed_components =
|
||||
instr.opcode == ucode::FetchOpcode::kGetTextureWeights
|
||||
? used_result_nonzero_components
|
||||
: ((UINT32_C(1)
|
||||
<< xenos::GetFetchOpDimensionComponentCount(instr.dimension)) -
|
||||
: ((UINT32_C(1) << xenos::GetFetchOpDimensionComponentCount(
|
||||
coordinate_dimension)) -
|
||||
1);
|
||||
assert_not_zero(coordinates_needed_components);
|
||||
spv::Id coordinates_operand =
|
||||
@@ -1215,7 +1220,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// - For normalized coords: coord + (offset * scale) / size_scaled
|
||||
// - For unnormalized coords: (coord + offset) * scale / size_scaled
|
||||
for (uint32_t i = 0;
|
||||
i <= uint32_t(instr.dimension != xenos::FetchOpDimension::k1D);
|
||||
i <= uint32_t(coordinate_dimension != xenos::FetchOpDimension::k1D);
|
||||
++i) {
|
||||
spv::Id& coordinate_ref = coordinates[i];
|
||||
spv::Id component_offset =
|
||||
@@ -1691,7 +1696,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
// the future when it's handled in getCompTexLOD somehow.
|
||||
spv::Id lod_gradient_scale = builder_->createUnaryBuiltinCall(
|
||||
type_float_, ext_inst_glsl_std_450_, GLSLstd450Exp2, lod);
|
||||
switch (instr.dimension) {
|
||||
switch (coordinate_dimension) {
|
||||
case xenos::FetchOpDimension::k1D: {
|
||||
spv::Id gradient_h_1d, gradient_v_1d;
|
||||
if (instr.attributes.use_register_gradients) {
|
||||
|
||||
Reference in New Issue
Block a user