mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
Approximate explicit-LOD texture gathers at mip zero
Credits: YuhiAida (@YuhiAida): https://github.com/KytyPS5/KytyPS5/pull/588 https://github.com/KytyPS5/KytyPS5/pull/589 https://github.com/KytyPS5/KytyPS5/pull/655 frans (@francoisatt): https://github.com/KytyPS5/KytyPS5/pull/590 BlackCAT (@psnwd): https://github.com/KytyPS5/KytyPS5/pull/613 shadowbeat070 (@shadowbeat070): https://github.com/KytyPS5/KytyPS5/pull/654 Pouare514 (@Pouare514): https://github.com/KytyPS5/KytyPS5/pull/29 https://github.com/KytyPS5/KytyPS5/pull/32
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
#include "graphics/shader/recompiler/frontend/decode/ImageOps.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <cstdio>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
|
||||
namespace {
|
||||
@@ -646,6 +648,13 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto coord =
|
||||
CoordF32(ctx, mem, *address, layout.coord, dimension_info.coordinate_components);
|
||||
if (op == IR::ValueOpcode::ImageGatherRaw) {
|
||||
if (HasFlag(mem, Decoder::ImageSampleFlagLod)) {
|
||||
static std::atomic_flag warned = ATOMIC_FLAG_INIT;
|
||||
if (!warned.test_and_set(std::memory_order_relaxed)) {
|
||||
std::fputs("Warning: approximating IMAGE_GATHER4_L at mip level 0; explicit LOD is ignored.\n",
|
||||
stderr);
|
||||
}
|
||||
}
|
||||
if (dimension == ImageDimension::Dim1D) {
|
||||
if (dref || !HasFlag(mem, Decoder::ImageSampleFlagLevelZero) ||
|
||||
HasFlag(mem, Decoder::ImageSampleFlagOffset) ||
|
||||
|
||||
@@ -175,6 +175,7 @@ constexpr MimgSampleInfo MIMG_SAMPLE_OPCODE_LIST[] = {
|
||||
};
|
||||
|
||||
constexpr MimgGatherInfo MIMG_GATHER_OPCODE_LIST[] = {
|
||||
{0x44u, Opcode::IMAGE_GATHER4_L, ImageSampleFlagLod},
|
||||
{0x47u, Opcode::IMAGE_GATHER4_LZ, ImageSampleFlagLevelZero},
|
||||
{0x48u, Opcode::IMAGE_GATHER4_C, ImageSampleFlagCompare},
|
||||
{0x4fu, Opcode::IMAGE_GATHER4_C_LZ,
|
||||
|
||||
@@ -144,6 +144,7 @@ std::string FormatMimg(const Instruction& inst) {
|
||||
}
|
||||
switch (inst.opcode) {
|
||||
case Opcode::IMAGE_SAMPLE:
|
||||
case Opcode::IMAGE_GATHER4_L:
|
||||
case Opcode::IMAGE_GATHER4_LZ:
|
||||
case Opcode::IMAGE_GATHER4_C:
|
||||
case Opcode::IMAGE_GATHER4_C_LZ:
|
||||
@@ -580,6 +581,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::IMAGE_LOAD_MIP:
|
||||
case Opcode::IMAGE_GET_RESINFO:
|
||||
case Opcode::IMAGE_GET_LOD:
|
||||
case Opcode::IMAGE_GATHER4_L:
|
||||
case Opcode::IMAGE_GATHER4_LZ:
|
||||
case Opcode::IMAGE_GATHER4_C:
|
||||
case Opcode::IMAGE_GATHER4_C_LZ:
|
||||
|
||||
@@ -559,6 +559,7 @@ enum class Opcode {
|
||||
IMAGE_ATOMIC_OR,
|
||||
IMAGE_ATOMIC_XOR,
|
||||
IMAGE_SAMPLE,
|
||||
IMAGE_GATHER4_L,
|
||||
IMAGE_GATHER4_LZ,
|
||||
IMAGE_GATHER4_C,
|
||||
IMAGE_GATHER4_C_LZ,
|
||||
|
||||
@@ -1034,6 +1034,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
case Decoder::Opcode::IMAGE_STORE:
|
||||
case Decoder::Opcode::IMAGE_STORE_MIP: return IMAGE_STORE(inst);
|
||||
case Decoder::Opcode::IMAGE_SAMPLE: return IMAGE_SAMPLE(inst);
|
||||
case Decoder::Opcode::IMAGE_GATHER4_L:
|
||||
case Decoder::Opcode::IMAGE_GATHER4_LZ:
|
||||
case Decoder::Opcode::IMAGE_GATHER4_C:
|
||||
case Decoder::Opcode::IMAGE_GATHER4_C_LZ:
|
||||
|
||||
@@ -12271,7 +12271,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
vk::Sampler CreateNearestSampler(const char *shader_name) {
|
||||
vk::Sampler CreateNearestSampler(const char *shader_name, u32 mip_levels = 1) {
|
||||
vk::SamplerCreateInfo sampler_info{};
|
||||
sampler_info.sType = vk::StructureType::eSamplerCreateInfo;
|
||||
sampler_info.magFilter = vk::Filter::eNearest;
|
||||
@@ -12281,7 +12281,7 @@ public:
|
||||
sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
|
||||
sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
|
||||
sampler_info.minLod = 0.0f;
|
||||
sampler_info.maxLod = 0.0f;
|
||||
sampler_info.maxLod = static_cast<float>(mip_levels - 1u);
|
||||
vk::Sampler sampler = nullptr;
|
||||
RequireVk(shader_name, "dispatch",
|
||||
m_device.createSampler(&sampler_info, nullptr, &sampler),
|
||||
@@ -15484,7 +15484,7 @@ void RunCase(VulkanHarness *vulkan, const TestCase &test) {
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
if (needs_sampler) {
|
||||
sampler = vulkan->CreateNearestSampler(test.name);
|
||||
sampler = vulkan->CreateNearestSampler(test.name, sampled_image.mip_levels);
|
||||
}
|
||||
|
||||
vulkan->Dispatch(test, compiled, buffer, needs_gds ? &gds_buffer : nullptr,
|
||||
@@ -25001,6 +25001,34 @@ TestCase ImageSampleAndGather() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase ImageGatherLodApproximatesLevelZero() {
|
||||
using O = ShaderOpcode;
|
||||
std::vector<u32> code;
|
||||
AppendVMovLiteral(&code, 20, 0x3f000000u);
|
||||
AppendVMovLiteral(&code, 21, 0x3f000000u);
|
||||
AppendVMovLiteral(&code, 22, 0x3f800000u);
|
||||
code.push_back(EncodeMimg0(0x44, 0x1));
|
||||
code.push_back(EncodeMimg1(0, 20));
|
||||
code.push_back(EncodeMimg0(0x24, 0x1));
|
||||
code.push_back(EncodeMimg1(4, 20));
|
||||
for (u32 i = 0; i < 5u; i++) {
|
||||
AppendStoreVgpr(&code, i, i);
|
||||
}
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "ImageGatherLodApproximatesLevelZero";
|
||||
test.code = std::move(code);
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4_L, O::IMAGE_SAMPLE,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
// Explicit sampling proves mip 1 is accessible; the gather must still read mip 0.
|
||||
test.expected = {0x3f800000u, 0x3f800000u, 0x3f800000u, 0x3f800000u, 0x41000000u};
|
||||
test.sampled_image_rgba_mips = {std::vector<u32>(4 * 4 * 4, 0x3f800000u),
|
||||
std::vector<u32>(2 * 2 * 4, 0x41000000u)};
|
||||
test.required_spirv = {"OpImageGather", "OpImageSampleExplicitLod"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase ImageD16GatherPacksHalfPairs() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -26575,6 +26603,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ImageGetResinfoDmaskWidthHeight);
|
||||
AddCase(ImageGetResinfoDmaskMipLevels);
|
||||
AddCase(ImageSampleAndGather);
|
||||
AddCase(ImageGatherLodApproximatesLevelZero);
|
||||
AddCase(ImageD16GatherPacksHalfPairs);
|
||||
AddCase(ImageSampleA16SamplerCoordsOnGpu);
|
||||
AddCase(ImageSampleOpcodeAliasUsesNormalCoords);
|
||||
@@ -31166,6 +31195,7 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, BranchVccnzUsesWaveMask());
|
||||
RunCase(&vulkan, BranchVccnzUsesCarryProducedWaveMask());
|
||||
RunCase(&vulkan, ImageSampleAndGather());
|
||||
RunCase(&vulkan, ImageGatherLodApproximatesLevelZero());
|
||||
RunCase(&vulkan, SharedReturnKeepsSelectedValues());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user