diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index a2b97452c..cba883287 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -8234,12 +8234,24 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // It's probably applicable to tfetchCube too, we're going to assume it's // used for them the same way as for stacked textures. // http://web.archive.org/web/20090511231340/http://msdn.microsoft.com:80/en-us/library/bb313959.aspx + // Adding 1/1024 - quarter of one fixed-point unit of subpixel precision + // (not to touch rounding when the GPU is converting to fixed-point) - to + // resolve the ambiguity when the texture coordinate is directly between two + // pixels, which hurts nearest-neighbor sampling (fixes the XBLA logo being + // blocky in Banjo-Kazooie and the outlines around things and overall + // blockiness in Halo 3). float offset_x = instr.attributes.offset_x; + if (instr.opcode != FetchOpcode::kGetTextureWeights) { + offset_x += 1.0f / 1024.0f; + } float offset_y = 0.0f, offset_z = 0.0f; if (instr.dimension == TextureDimension::k2D || instr.dimension == TextureDimension::k3D || instr.dimension == TextureDimension::kCube) { offset_y = instr.attributes.offset_y; + if (instr.opcode != FetchOpcode::kGetTextureWeights) { + offset_y += 1.0f / 1024.0f; + } // Don't care about the Z offset for cubemaps when getting weights because // zero Z will be returned anyway (the face index doesn't participate in // bilinear filtering). @@ -8247,6 +8259,9 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( (instr.dimension == TextureDimension::kCube && instr.opcode != FetchOpcode::kGetTextureWeights)) { offset_z = instr.attributes.offset_z; + if (instr.opcode != FetchOpcode::kGetTextureWeights) { + offset_z += 1.0f / 1024.0f; + } } } @@ -8262,6 +8277,9 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // unlikely to be used on purpose. // http://web.archive.org/web/20090514012026/http://msdn.microsoft.com:80/en-us/library/bb313957.aspx uint32_t size_and_is_3d_temp = UINT32_MAX; + // With 1/1024 this will always be true anyway, but let's keep the shorter + // path without the offset in case some day this hack won't be used anymore + // somehow. bool has_offset = offset_x != 0.0f || offset_y != 0.0f || offset_z != 0.0f; if (instr.opcode == FetchOpcode::kGetTextureWeights || has_offset || instr.attributes.unnormalized_coordinates ||