diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 43d125bf0b4..c5f98e5b9d4 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -583,6 +583,18 @@ void PatchTextureBufferArgs(IR::Block& block, IR::Inst& inst, Info& info) { } } +IR::Value FixCubeCoords(IR::IREmitter& ir, const AmdGpu::Image& image, const IR::Value& x, + const IR::Value& y, const IR::Value& face) { + if (!image.IsCube()) { + return ir.CompositeConstruct(x, y, face); + } + // AMD cube math results in coordinates in the range [1.0, 2.0]. We need + // to convert this to the range [0.0, 1.0] to get correct results. + const auto fixed_x = ir.FPSub(IR::F32{x}, ir.Imm32(1.f)); + const auto fixed_y = ir.FPSub(IR::F32{y}, ir.Imm32(1.f)); + return ir.CompositeConstruct(fixed_x, fixed_y, face); +} + void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info, const ImageResource& image_res, const AmdGpu::Image& image) { const auto handle = inst.Arg(0); @@ -643,8 +655,8 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info, case AmdGpu::ImageType::Color1DArray: return read(0); case AmdGpu::ImageType::Color2D: - case AmdGpu::ImageType::Color2DArray: case AmdGpu::ImageType::Color2DMsaa: + case AmdGpu::ImageType::Color2DArray: return ir.CompositeConstruct(read(0), read(8)); case AmdGpu::ImageType::Color3D: return ir.CompositeConstruct(read(0), read(8), read(16)); @@ -665,8 +677,8 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info, addr_reg = addr_reg + 2; return {get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1)}; case AmdGpu::ImageType::Color2D: - case AmdGpu::ImageType::Color2DArray: case AmdGpu::ImageType::Color2DMsaa: + case AmdGpu::ImageType::Color2DArray: // (du/dx, dv/dx), (du/dy, dv/dy) addr_reg = addr_reg + 4; return {ir.CompositeConstruct(get_addr_reg(addr_reg - 4), get_addr_reg(addr_reg - 3)), @@ -711,12 +723,13 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info, case AmdGpu::ImageType::Color2D: // x, y addr_reg = addr_reg + 2; return ir.CompositeConstruct(get_coord(addr_reg - 2, 0), get_coord(addr_reg - 1, 1)); - case AmdGpu::ImageType::Color2DArray: // x, y, slice - [[fallthrough]]; case AmdGpu::ImageType::Color2DMsaa: // x, y, frag + [[fallthrough]]; + case AmdGpu::ImageType::Color2DArray: // x, y, slice addr_reg = addr_reg + 3; - return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), - get_addr_reg(addr_reg - 1)); + // Note we can use FixCubeCoords with fallthrough cases since it checks for image type. + return FixCubeCoords(ir, image, get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), + get_addr_reg(addr_reg - 1)); case AmdGpu::ImageType::Color3D: // x, y, z addr_reg = addr_reg + 3; return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 523e63497a3..eb008596599 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -47,6 +47,7 @@ struct ImageSpecialization { AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; bool is_integer = false; bool is_storage = false; + bool is_cube = false; AmdGpu::CompMapping dst_select{}; AmdGpu::NumberConversion num_conversion{}; @@ -127,6 +128,7 @@ struct StageSpecialization { spec.type = sharp.GetViewType(desc.is_array); spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); spec.is_storage = desc.is_written; + spec.is_cube = sharp.IsCube(); if (spec.is_storage) { spec.dst_select = sharp.DstSelect(); }