[Vulkan] Fix draw_resolution_scaled_texture_offsets cancelling itself out
The offset was being multiplied by the scale and divided by the host scaled size, which collapsed back to guest step, so the cvar changed nothing on Vulkan while D3D12 stepped host texels. Since the size is already in host texels, dividing the offset by it gives the proper step. Unnormalized coordinates convert to host texels before the offset add so the offset isn't multiplied along with the coordinate. Folds in the fix for 5841095A. Co-authored-by: Herman S. <429230+has207@users.noreply.github.com>
This commit is contained in:
committed by
Radosław Gliński
parent
3eab2b8b39
commit
31168682b0
@@ -1245,12 +1245,9 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
|||||||
} else {
|
} else {
|
||||||
// kTextureFetch or kGetTextureComputedLod.
|
// kTextureFetch or kGetTextureComputedLod.
|
||||||
|
|
||||||
// Normalize the XY coordinates, and apply the offset.
|
// Normalize the XY coordinates, and apply the offset. When the texture
|
||||||
// When a texture is from a resolution-scaled resolve, offsets are in
|
// is resolution-scaled, size has already been scaled up to host texels
|
||||||
// guest texels but the size is in host texels. We need to scale offsets
|
// above so dividing the offset by it yields a 1-host-texel step.
|
||||||
// to compensate:
|
|
||||||
// - For normalized coords: coord + (offset * scale) / size_scaled
|
|
||||||
// - For unnormalized coords: (coord + offset) * scale / size_scaled
|
|
||||||
for (uint32_t i = 0;
|
for (uint32_t i = 0;
|
||||||
i <= uint32_t(coordinate_dimension != xenos::FetchOpDimension::k1D);
|
i <= uint32_t(coordinate_dimension != xenos::FetchOpDimension::k1D);
|
||||||
++i) {
|
++i) {
|
||||||
@@ -1260,15 +1257,10 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
|||||||
: spv::NoResult;
|
: spv::NoResult;
|
||||||
spv::Id size_component = size[i];
|
spv::Id size_component = size[i];
|
||||||
if (instr.attributes.unnormalized_coordinates) {
|
if (instr.attributes.unnormalized_coordinates) {
|
||||||
if (component_offset != spv::NoResult) {
|
// Convert the guest-texel coord to host texels for resolution-scaled
|
||||||
coordinate_ref = builder_->createNoContractionBinOp(
|
// textures, since size below is in host texels. Done before the
|
||||||
spv::OpFAdd, type_float_, coordinate_ref, component_offset);
|
// offset add so the offset stays at 1 host texel rather than being
|
||||||
}
|
// multiplied with the coord.
|
||||||
// For resolution-scaled textures with unnormalized coords, we need
|
|
||||||
// to scale the coordinate (which now includes offset) before
|
|
||||||
// dividing by the scaled size. This ensures:
|
|
||||||
// (coord + offset) * scale / size_scaled = (coord + offset) /
|
|
||||||
// guest_size
|
|
||||||
if (is_texture_resolved != spv::NoResult &&
|
if (is_texture_resolved != spv::NoResult &&
|
||||||
((i == 0 && draw_resolution_scale_x_ > 1) ||
|
((i == 0 && draw_resolution_scale_x_ > 1) ||
|
||||||
(i == 1 && draw_resolution_scale_y_ > 1))) {
|
(i == 1 && draw_resolution_scale_y_ > 1))) {
|
||||||
@@ -1281,32 +1273,19 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
|||||||
spv::OpSelect, type_float_, is_texture_resolved, scaled_coord,
|
spv::OpSelect, type_float_, is_texture_resolved, scaled_coord,
|
||||||
coordinate_ref);
|
coordinate_ref);
|
||||||
}
|
}
|
||||||
|
if (component_offset != spv::NoResult) {
|
||||||
|
coordinate_ref = builder_->createNoContractionBinOp(
|
||||||
|
spv::OpFAdd, type_float_, coordinate_ref, component_offset);
|
||||||
|
}
|
||||||
assert_true(size_component != spv::NoResult);
|
assert_true(size_component != spv::NoResult);
|
||||||
coordinate_ref = builder_->createNoContractionBinOp(
|
coordinate_ref = builder_->createNoContractionBinOp(
|
||||||
spv::OpFDiv, type_float_, coordinate_ref, size_component);
|
spv::OpFDiv, type_float_, coordinate_ref, size_component);
|
||||||
} else {
|
} else {
|
||||||
if (component_offset != spv::NoResult) {
|
if (component_offset != spv::NoResult) {
|
||||||
assert_true(size_component != spv::NoResult);
|
assert_true(size_component != spv::NoResult);
|
||||||
// For resolution-scaled textures with normalized coords, scale the
|
|
||||||
// offset before normalizing. This ensures:
|
|
||||||
// coord + (offset * scale) / size_scaled = coord + offset /
|
|
||||||
// guest_size
|
|
||||||
spv::Id effective_offset = component_offset;
|
|
||||||
if (is_texture_resolved != spv::NoResult &&
|
|
||||||
((i == 0 && draw_resolution_scale_x_ > 1) ||
|
|
||||||
(i == 1 && draw_resolution_scale_y_ > 1))) {
|
|
||||||
float scale = (i == 0) ? float(draw_resolution_scale_x_)
|
|
||||||
: float(draw_resolution_scale_y_);
|
|
||||||
spv::Id scaled_offset = builder_->createNoContractionBinOp(
|
|
||||||
spv::OpFMul, type_float_, component_offset,
|
|
||||||
builder_->makeFloatConstant(scale));
|
|
||||||
effective_offset = builder_->createTriOp(
|
|
||||||
spv::OpSelect, type_float_, is_texture_resolved,
|
|
||||||
scaled_offset, component_offset);
|
|
||||||
}
|
|
||||||
spv::Id component_offset_normalized =
|
spv::Id component_offset_normalized =
|
||||||
builder_->createNoContractionBinOp(
|
builder_->createNoContractionBinOp(
|
||||||
spv::OpFDiv, type_float_, effective_offset, size_component);
|
spv::OpFDiv, type_float_, component_offset, size_component);
|
||||||
coordinate_ref = builder_->createNoContractionBinOp(
|
coordinate_ref = builder_->createNoContractionBinOp(
|
||||||
spv::OpFAdd, type_float_, coordinate_ref,
|
spv::OpFAdd, type_float_, coordinate_ref,
|
||||||
component_offset_normalized);
|
component_offset_normalized);
|
||||||
|
|||||||
Reference in New Issue
Block a user