[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:
goldislead
2026-08-02 10:57:50 -07:00
committed by Radosław Gliński
parent fe40c0d68f
commit fbdb1f2817
3 changed files with 40 additions and 17 deletions

View File

@@ -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),

View File

@@ -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);

View File

@@ -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) {