diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageSampleDerivatives.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageSampleDerivatives.cpp new file mode 100644 index 000000000..5c29b7e6c --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageSampleDerivatives.cpp @@ -0,0 +1,345 @@ +#include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp" +#include "prx/libSceAgcDriver/Graphics/include/Draw.hpp" +#include "Recompiler.hpp" +#include "VulkanTestDevice.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using AgcDriver::Graphics::Require; +using ShaderRecompiler::ShaderStage; + +constexpr std::uint32_t Threads = 32; +constexpr std::uint32_t Wave64Threads = 64; +constexpr std::uint32_t Inputs = 12; +constexpr std::uint32_t Results = 16; +constexpr std::uint32_t Width = 64; +constexpr std::uint32_t Height = 4; +constexpr std::uint32_t Depth = 2; +constexpr std::uint32_t Format32Float = 22; + +alignas(256) constexpr std::array Input{ + 0x3ce00000, 0x3e000000, 0x3e800000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3d300000, 0x3ec00000, 0x3e800000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, + 0x3d700000, 0x3f200000, 0x3e800000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x3d980000, 0x3f600000, 0x3e800000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, + 0x3db80000, 0x3e000000, 0x3f400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, 0x3dd80000, 0x3ec00000, 0x3f400000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3df80000, 0x3f200000, 0x3f400000, 0x00000000, 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e0c0000, 0x3f600000, 0x3f400000, 0x00000000, + 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, + 0x3e1c0000, 0x3e000000, 0x3e800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3e2c0000, 0x3ec00000, 0x3e800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x3a800000, 0x00000000, + 0x3e3c0000, 0x3f200000, 0x3e800000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e4c0000, 0x3f600000, 0x3e800000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3e5c0000, 0x3e000000, 0x3f400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3a800000, 0x3a800000, 0x00000000, 0x00000000, 0x3e6c0000, 0x3ec00000, 0x3f400000, 0x00000000, + 0x3a800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, + 0x3e7c0000, 0x3f200000, 0x3f400000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x3e860000, 0x3f600000, 0x3f400000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3e8e0000, 0x3e000000, 0x3e800000, 0x00000000, 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e960000, 0x3ec00000, 0x3e800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3e9e0000, 0x3f200000, 0x3e800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, 0x3ea60000, 0x3f600000, 0x3e800000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, + 0x3eae0000, 0x3e000000, 0x3f400000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3eb60000, 0x3ec00000, 0x3f400000, 0x00000000, + 0x3a800000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3ebe0000, 0x3f200000, 0x3f400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3ec60000, 0x3f600000, 0x3f400000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, + 0x3ece0000, 0x3e000000, 0x3e800000, 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3ed60000, 0x3ec00000, 0x3e800000, 0x00000000, + 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x00000000, + 0x3ede0000, 0x3f200000, 0x3e800000, 0x00000000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x3ee60000, 0x3f600000, 0x3e800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3eee0000, 0x3e000000, 0x3f400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, 0x3ef60000, 0x3ec00000, 0x3f400000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3efe0000, 0x3f200000, 0x3f400000, 0x00000000, 0x00000000, 0x3a800000, 0x3a800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f030000, 0x3f600000, 0x3f400000, 0x00000000, + 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, 0x3a800000, 0x00000000, 0x00000000, +}; +alignas(256) std::array Buffer{}; +alignas(256) std::array Texels{}; + +alignas(256) constexpr std::array Code2D{ + 0x160200b0, 0x34060086, 0xe0381000, 0x80000401, 0xe0381010, 0x80002801, 0xe0381020, 0x80003201, + 0xbe900404, 0xbe920406, 0xbe940408, 0xbe96040a, 0xbe98040c, 0xbe9a040e, 0x7e140280, 0x7e160280, + 0x7e180280, 0x7e1a0280, 0x7e1c0280, 0x7e1e0280, 0x7e200280, 0x7e220280, 0x7e240280, 0x7e260280, + 0x7e280280, 0x7e2a0280, 0x7e2c0280, 0x7e2e0280, 0x7e300280, 0x7e320280, 0xbf8c3f70, 0x5e585328, + 0xd52f002d, 0x0201012a, 0x5e5c6732, 0xd52f002f, 0x02010134, 0x5e600b04, 0xd52f0031, 0x02010106, + 0xd52f0036, 0x02010128, 0xd52f0037, 0x02010132, 0xd52f003b, 0x02010104, 0x7e780281, 0x7e7a02f6, + 0x7e7c02ff, 0x00000101, 0x7e800328, 0x7e820329, 0x7e840332, 0x7e860333, 0x7e880304, 0x7e8a0305, + 0xf0880108, 0x00c40a40, 0x7e800328, 0x7e820329, 0x7e840332, 0x7e860333, 0x7e880304, 0x7e8a0305, + 0xf1a00108, 0x00c40b40, 0x7e800328, 0x7e820329, 0x7e840332, 0x7e860333, 0x7e880304, 0x7e8a0305, + 0xbe9e037e, 0xbefe03ff, 0xaeeeffff, 0xf1a00108, 0x00c40c40, 0xbefe031e, 0x7e80032c, 0x7e82032e, + 0x7e840304, 0x7e860305, 0xf0880109, 0x00c40d40, 0x7e80032c, 0x7e82032e, 0x7e840304, 0x7e860305, + 0xf1a00109, 0x00c40e40, 0x7e800328, 0x7e820329, 0x7e840332, 0x7e860333, 0x7e880330, 0xf0880108, + 0x40c40f40, 0x7e80032c, 0x7e82032e, 0x7e840330, 0xf0880109, 0x40c41040, 0x7e80033c, 0x7e820328, + 0x7e840329, 0x7e860332, 0x7e880333, 0x7e8a0304, 0x7e8c0305, 0xf1b00108, 0x00c41140, 0x7e80033e, + 0x7e82032c, 0x7e84032e, 0x7e860304, 0x7e880305, 0xf0c80109, 0x00c41240, 0x7e80033c, 0x7e82032c, + 0x7e84032e, 0x7e860304, 0x7e880305, 0xf1b00109, 0x00c41340, 0x7e80033c, 0x7e82032c, 0x7e84032e, + 0x7e860330, 0xf0c80109, 0x40c41440, 0x7e80033c, 0x7e82032c, 0x7e84032e, 0x7e860304, 0x7e880305, + 0xbe9e037e, 0xbefe03ff, 0xaeeeffff, 0xf1b00109, 0x00c41540, 0xbefe031e, 0xbf8c3f70, 0xe0701600, + 0x80000a03, 0xe0701604, 0x80000b03, 0xe0701608, 0x80000c03, 0xe070160c, 0x80000d03, 0xe0701610, + 0x80000e03, 0xe0701614, 0x80000f03, 0xe0701618, 0x80001003, 0xe070161c, 0x80001103, 0xe0701620, + 0x80001203, 0xe0701624, 0x80001303, 0xe0701628, 0x80001403, 0xe070162c, 0x80001503, 0xbf810000, +}; + +alignas(256) constexpr std::array Code3D{ + 0x160200b0, 0x34060086, 0xe0381000, 0x80000401, 0xe0381010, 0x80002801, 0xe0381020, 0x80003201, + 0xbe900404, 0xbe920406, 0xbe940408, 0xbe96040a, 0xbe98040c, 0xbe9a040e, 0x7e140280, 0x7e160280, + 0x7e180280, 0x7e1a0280, 0x7e1c0280, 0x7e1e0280, 0x7e200280, 0x7e220280, 0x7e240280, 0x7e260280, + 0x7e280280, 0x7e2a0280, 0x7e2c0280, 0x7e2e0280, 0x7e300280, 0x7e320280, 0xbf8c3f70, 0x5e585328, + 0xd52f002d, 0x0201012a, 0x5e5c6732, 0xd52f002f, 0x02010134, 0x5e600b04, 0xd52f0031, 0x02010106, + 0xd52f0036, 0x02010128, 0xd52f0037, 0x02010132, 0xd52f003b, 0x02010104, 0x7e780281, 0x7e7a02f6, + 0x7e7c02ff, 0x00000101, 0x7e800328, 0x7e820329, 0x7e84032a, 0x7e860332, 0x7e880333, 0x7e8a0334, + 0x7e8c0304, 0x7e8e0305, 0x7e900306, 0xf0880110, 0x00c40a40, 0x7e800328, 0x7e820329, 0x7e84032a, + 0x7e860332, 0x7e880333, 0x7e8a0334, 0x7e8c0304, 0x7e8e0305, 0x7e900306, 0xf1a00110, 0x00c40b40, + 0x7e80032c, 0x7e82032d, 0x7e84032e, 0x7e86032f, 0x7e880304, 0x7e8a0305, 0x7e8c0306, 0xf0880111, + 0x00c40c40, 0x7e80032c, 0x7e82032d, 0x7e84032e, 0x7e86032f, 0x7e880304, 0x7e8a0305, 0x7e8c0306, + 0xf1a00111, 0x00c40d40, 0x7e800328, 0x7e820329, 0x7e84032a, 0x7e860332, 0x7e880333, 0x7e8a0334, + 0x7e8c0330, 0x7e8e0331, 0xf0880110, 0x40c40e40, 0x7e80032c, 0x7e82032d, 0x7e84032e, 0x7e86032f, + 0x7e880330, 0x7e8a0331, 0xf0880111, 0x40c40f40, 0xbf8c3f70, 0xe0701600, 0x80000a03, 0xe0701604, + 0x80000b03, 0xe0701608, 0x80000c03, 0xe070160c, 0x80000d03, 0xe0701610, 0x80000e03, 0xe0701614, + 0x80000f03, 0xbf810000, +}; + +alignas(256) constexpr std::array Code1D{ + 0x160200b0, 0x34060086, 0xe0381000, 0x80000401, 0xe0381010, 0x80002801, 0xe0381020, 0x80003201, + 0xbe900404, 0xbe920406, 0xbe940408, 0xbe96040a, 0xbe98040c, 0xbe9a040e, 0x7e140280, 0x7e160280, + 0x7e180280, 0x7e1a0280, 0x7e1c0280, 0x7e1e0280, 0x7e200280, 0x7e220280, 0x7e240280, 0x7e260280, + 0x7e280280, 0x7e2a0280, 0x7e2c0280, 0x7e2e0280, 0x7e300280, 0x7e320280, 0xbf8c3f70, 0x5e585328, + 0xd52f002d, 0x0201012a, 0x5e5c6732, 0xd52f002f, 0x02010134, 0x5e600b04, 0xd52f0031, 0x02010106, + 0xd52f0036, 0x02010128, 0xd52f0037, 0x02010132, 0xd52f003b, 0x02010104, 0x7e780281, 0x7e7a02f6, + 0x7e7c02ff, 0x00000101, 0x7e800328, 0x7e820332, 0x7e840304, 0xf0880100, 0x00c40a40, 0x7e800336, + 0x7e820337, 0x7e840304, 0xf0880101, 0x00c40b40, 0x7e800336, 0x7e820337, 0x7e840304, 0xf1a00101, + 0x00c40c40, 0x7e800328, 0x7e820332, 0x7e84033b, 0xf0880100, 0x40c40d40, 0x7e800336, 0x7e820337, + 0x7e84033b, 0xf1a00101, 0x40c40e40, 0xbf8c3f70, 0xe0701600, 0x80000a03, 0xe0701604, 0x80000b03, + 0xe0701608, 0x80000c03, 0xe070160c, 0x80000d03, 0xe0701610, 0x80000e03, 0xbf810000, +}; + +constexpr std::array Names2D{"image_sample_d", "image_sample_cd", "image_sample_cd (exec)", "image_sample_d_g16", "image_sample_cd_g16", "image_sample_d a16", "image_sample_d_g16 a16", "image_sample_cd_o", "image_sample_d_o_g16", "image_sample_cd_o_g16", "image_sample_d_o_g16 a16", "image_sample_cd_o_g16 (exec)"}; +constexpr std::array Masked2D{false, false, true, false, false, false, false, false, false, false, false, true}; +constexpr std::array Expected2D{ + 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x40100000, + 0x42cc8000, 0x40100000, 0x40100000, 0x40100000, 0x42cc0000, 0x42cc8000, 0x42cc8000, 0x42cc0000, + 0x42cc8000, 0x42cc0000, 0x42cc0000, 0x42ce8000, 0x434b0000, 0x42ce8000, 0x42ce0000, 0x42ce8000, + 0x434b0000, 0x434b4000, 0x434b4000, 0x434b0000, 0x434b4000, 0x434b0000, 0x434b0000, 0x434c4000, + 0x43980000, 0x434c4000, 0x434c0000, 0x434c4000, 0x43980000, 0x43982000, 0x43982000, 0x43980000, + 0x43982000, 0x43980000, 0x43980000, 0x4398a000, 0x43988000, 0x4398a000, 0x43988000, 0x4398a000, + 0x40a00000, 0x40a00000, 0x40a00000, 0x40a00000, 0x40a00000, 0x40a00000, 0x40a00000, 0x40c00000, + 0x42d40000, 0x40c00000, 0x40c00000, 0x40c00000, 0x42d48000, 0x42d40000, 0x42d40000, 0x42d48000, + 0x42d40000, 0x42d48000, 0x42d48000, 0x42d60000, 0x434f4000, 0x42d60000, 0x42d68000, 0x42d60000, + 0x434f0000, 0x434f0000, 0x434f0000, 0x434f0000, 0x434f0000, 0x434f0000, 0x434f0000, 0x43500000, + 0x439a0000, 0x43500000, 0x43500000, 0x43500000, 0x439a0000, 0x439a0000, 0x439a0000, 0x439a0000, + 0x439a0000, 0x439a0000, 0x439a0000, 0x439a8000, 0x439a8000, 0x439a8000, 0x439a8000, 0x439a8000, + 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41200000, + 0x42dc0000, 0x41200000, 0x41200000, 0x41200000, 0x42dc0000, 0x42dc0000, 0x42dc0000, 0x42dc0000, + 0x42dc0000, 0x42dc0000, 0x42dc0000, 0x42de0000, 0x43530000, 0x42de0000, 0x42de0000, 0x42de0000, + 0x43534000, 0x43530000, 0x43530000, 0x43534000, 0x43530000, 0x43534000, 0x43534000, 0x43540000, + 0x439c2000, 0x43540000, 0x43544000, 0x43540000, 0x439c0000, 0x439c0000, 0x439c0000, 0x439c0000, + 0x439c0000, 0x439c0000, 0x439c0000, 0x439c8000, 0x439c8000, 0x439c8000, 0x439c8000, 0x439c8000, + 0x41500000, 0x41500000, 0x41500000, 0x41500000, 0x41500000, 0x41500000, 0x41500000, 0x41600000, + 0x42e40000, 0x41600000, 0x41600000, 0x41600000, 0x42e40000, 0x42e40000, 0x42e40000, 0x42e40000, + 0x42e40000, 0x42e40000, 0x42e40000, 0x42e60000, 0x43570000, 0x42e60000, 0x42e60000, 0x42e60000, + 0x43570000, 0x43570000, 0x43570000, 0x43570000, 0x43570000, 0x43570000, 0x43570000, 0x43580000, + 0x439e0000, 0x43580000, 0x43580000, 0x43580000, 0x439e2000, 0x439e0000, 0x439e0000, 0x439e2000, + 0x439e0000, 0x439e2000, 0x439e2000, 0x439e8000, 0x439ea000, 0x439e8000, 0x439ea000, 0x439e8000, + 0x41880000, 0x41880000, 0x00000000, 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x41900000, + 0x42ec0000, 0x41900000, 0x41900000, 0x00000000, 0x42ec8000, 0x42ec0000, 0x42ec8000, 0x42ec8000, + 0x42ec0000, 0x42ec8000, 0x42ec8000, 0x42ee0000, 0x435b4000, 0x42ee0000, 0x42ee8000, 0x42ee8000, + 0x435b0000, 0x435b0000, 0x435b4000, 0x435b0000, 0x435b0000, 0x435b0000, 0x435b0000, 0x435c0000, + 0x43a00000, 0x435c0000, 0x435c0000, 0x435c4000, 0x43a00000, 0x43a00000, 0x43a02000, 0x43a00000, + 0x43a00000, 0x43a00000, 0x43a00000, 0x43a08000, 0x43a08000, 0x43a08000, 0x43a08000, 0x43a0a000, + 0x41a80000, 0x41a80000, 0x00000000, 0x41a80000, 0x41a80000, 0x41a80000, 0x41a80000, 0x41b00000, + 0x42f40000, 0x41b00000, 0x41b00000, 0x00000000, 0x42f40000, 0x42f40000, 0x42f40000, 0x42f40000, + 0x42f40000, 0x42f40000, 0x42f40000, 0x42f60000, 0x435f0000, 0x42f60000, 0x42f60000, 0x42f60000, + 0x435f4000, 0x435f0000, 0x435f0000, 0x435f4000, 0x435f0000, 0x435f4000, 0x435f4000, 0x43600000, + 0x43a22000, 0x43600000, 0x43604000, 0x43600000, 0x43a20000, 0x43a20000, 0x43a20000, 0x43a20000, + 0x43a20000, 0x43a20000, 0x43a20000, 0x43a28000, 0x43a28000, 0x43a28000, 0x43a28000, 0x43a28000, + 0x41c80000, 0x41c80000, 0x00000000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41d00000, + 0x42fc0000, 0x41d00000, 0x41d00000, 0x00000000, 0x42fc0000, 0x42fc0000, 0x42fc0000, 0x42fc0000, + 0x42fc0000, 0x42fc0000, 0x42fc0000, 0x42fe0000, 0x43630000, 0x42fe0000, 0x42fe0000, 0x42fe0000, + 0x43630000, 0x43630000, 0x43630000, 0x43630000, 0x43630000, 0x43630000, 0x43630000, 0x43640000, + 0x43a40000, 0x43640000, 0x43640000, 0x43640000, 0x43a42000, 0x43a40000, 0x43a40000, 0x43a42000, + 0x43a40000, 0x43a42000, 0x43a42000, 0x43a48000, 0x43a4a000, 0x43a48000, 0x43a4a000, 0x43a48000, + 0x41e80000, 0x41e80000, 0x00000000, 0x41e80000, 0x41e80000, 0x41e80000, 0x41e80000, 0x41f00000, + 0x43020000, 0x41f00000, 0x41f00000, 0x00000000, 0x43024000, 0x43020000, 0x43024000, 0x43024000, + 0x43020000, 0x43024000, 0x43024000, 0x43030000, 0x43674000, 0x43030000, 0x43034000, 0x43034000, + 0x43670000, 0x43670000, 0x00000000, 0x43670000, 0x43670000, 0x43670000, 0x43670000, 0x43680000, + 0x43a60000, 0x43680000, 0x43680000, 0x00000000, 0x43a60000, 0x43a60000, 0x43a62000, 0x43a60000, + 0x43a60000, 0x43a60000, 0x43a60000, 0x43a68000, 0x43a68000, 0x43a68000, 0x43a68000, 0x43a6a000, +}; +constexpr std::array Names3D{"image_sample_d 3D", "image_sample_cd 3D", "image_sample_d_g16 3D", "image_sample_cd_g16 3D", "image_sample_d a16 3D", "image_sample_d_g16 a16 3D"}; +constexpr std::array Masked3D{false, false, false, false, false, false}; +constexpr std::array Expected3D{ + 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x42cc0000, 0x42cc8000, + 0x42cc0000, 0x42cc8000, 0x42cc0000, 0x42cc0000, 0x434b0000, 0x434b4000, 0x434b0000, 0x434b4000, + 0x434b0000, 0x434b0000, 0x43980000, 0x43982000, 0x43980000, 0x43982000, 0x43980000, 0x43980000, + 0x447b4000, 0x447b4000, 0x447b4000, 0x447b4000, 0x447b4000, 0x447b4000, 0x448a4800, 0x448a4000, + 0x448a4800, 0x448a4000, 0x448a4800, 0x448a4800, 0x4496e000, 0x4496e000, 0x4496e000, 0x4496e000, + 0x4496e000, 0x4496e000, 0x44a38000, 0x44a38000, 0x44a38000, 0x44a38000, 0x44a38000, 0x44a38000, + 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x42dc0000, 0x42dc0000, + 0x42dc0000, 0x42dc0000, 0x42dc0000, 0x42dc0000, 0x43534000, 0x43530000, 0x43534000, 0x43530000, + 0x43534000, 0x43534000, 0x439c0000, 0x439c0000, 0x439c0000, 0x439c0000, 0x439c0000, 0x439c0000, + 0x447d4000, 0x447d4000, 0x447d4000, 0x447d4000, 0x447d4000, 0x447d4000, 0x448b4000, 0x448b4000, + 0x448b4000, 0x448b4000, 0x448b4000, 0x448b4000, 0x4497e000, 0x4497e000, 0x4497e000, 0x4497e000, + 0x4497e000, 0x4497e000, 0x44a48800, 0x44a48000, 0x44a48800, 0x44a48000, 0x44a48800, 0x44a48800, + 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x42ec8000, 0x42ec0000, + 0x42ec8000, 0x42ec0000, 0x42ec8000, 0x42ec8000, 0x435b0000, 0x435b0000, 0x435b0000, 0x435b0000, + 0x435b0000, 0x435b0000, 0x43a00000, 0x43a00000, 0x43a00000, 0x43a00000, 0x43a00000, 0x43a00000, + 0x447f4000, 0x447f4000, 0x447f4000, 0x447f4000, 0x447f4000, 0x447f4000, 0x448c4000, 0x448c4000, + 0x448c4000, 0x448c4000, 0x448c4000, 0x448c4000, 0x4498e800, 0x4498e000, 0x4498e800, 0x4498e000, + 0x4498e800, 0x4498e800, 0x44a58000, 0x44a58000, 0x44a58000, 0x44a58000, 0x44a58000, 0x44a58000, + 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x42fc0000, 0x42fc0000, + 0x42fc0000, 0x42fc0000, 0x42fc0000, 0x42fc0000, 0x43630000, 0x43630000, 0x43630000, 0x43630000, + 0x43630000, 0x43630000, 0x43a42000, 0x43a40000, 0x43a42000, 0x43a40000, 0x43a42000, 0x43a42000, + 0x4480a000, 0x4480a000, 0x4480a000, 0x4480a000, 0x4480a000, 0x4480a000, 0x448d4800, 0x448d4000, + 0x448d4800, 0x448d4000, 0x448d4800, 0x448d4800, 0x4499e000, 0x4499e000, 0x4499e000, 0x4499e000, + 0x4499e000, 0x4499e000, 0x44a68000, 0x44a68000, 0x44a68000, 0x44a68000, 0x44a68000, 0x44a68000, +}; +constexpr std::array Names1D{"image_sample_d 1D", "image_sample_d_g16 1D", "image_sample_cd_g16 1D", "image_sample_d a16 1D", "image_sample_cd_g16 a16 1D"}; +constexpr std::array Masked1D{false, false, false, false, false}; +constexpr std::array Expected1D{ + 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x3fa00000, 0x40000000, 0x40000000, 0x40100000, + 0x40000000, 0x40100000, 0x40400000, 0x40400000, 0x40500000, 0x40400000, 0x40500000, 0x40800000, + 0x40800000, 0x40880000, 0x40800000, 0x40880000, 0x40a00000, 0x40a00000, 0x40a00000, 0x40a00000, + 0x40a00000, 0x40c80000, 0x40c80000, 0x40c00000, 0x40c80000, 0x40c00000, 0x40e00000, 0x40e00000, + 0x40e00000, 0x40e00000, 0x40e00000, 0x41000000, 0x41000000, 0x41000000, 0x41000000, 0x41000000, + 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41100000, 0x41200000, 0x41200000, 0x41200000, + 0x41200000, 0x41200000, 0x41340000, 0x41340000, 0x41300000, 0x41340000, 0x41300000, 0x41400000, + 0x41400000, 0x41400000, 0x41400000, 0x41400000, 0x41500000, 0x41500000, 0x41500000, 0x41500000, + 0x41500000, 0x41600000, 0x41600000, 0x41600000, 0x41600000, 0x41600000, 0x41700000, 0x41700000, + 0x41700000, 0x41700000, 0x41700000, 0x41820000, 0x41820000, 0x41800000, 0x41820000, 0x41800000, + 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x41880000, 0x41920000, 0x41920000, 0x41900000, + 0x41920000, 0x41900000, 0x41980000, 0x41980000, 0x41980000, 0x41980000, 0x41980000, 0x41a00000, + 0x41a00000, 0x41a00000, 0x41a00000, 0x41a00000, 0x41a80000, 0x41a80000, 0x41a80000, 0x41a80000, + 0x41a80000, 0x41b00000, 0x41b00000, 0x41b00000, 0x41b00000, 0x41b00000, 0x41ba0000, 0x41ba0000, + 0x41b80000, 0x41ba0000, 0x41b80000, 0x41c00000, 0x41c00000, 0x41c00000, 0x41c00000, 0x41c00000, + 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41c80000, 0x41d00000, 0x41d00000, 0x41d00000, + 0x41d00000, 0x41d00000, 0x41d80000, 0x41d80000, 0x41d80000, 0x41d80000, 0x41d80000, 0x41e20000, + 0x41e20000, 0x41e00000, 0x41e20000, 0x41e00000, 0x41e80000, 0x41e80000, 0x41e80000, 0x41e80000, + 0x41e80000, 0x41f20000, 0x41f20000, 0x41f00000, 0x41f20000, 0x41f00000, 0x41f80000, 0x41f80000, + 0x41f80000, 0x41f80000, 0x41f80000, 0x42000000, 0x42000000, 0x42000000, 0x42000000, 0x42000000, +}; + +std::array TextureDescriptor(std::uint32_t type, std::uint32_t height, std::uint32_t depth) { + const auto address = static_cast(reinterpret_cast(Texels.data())); + return { + static_cast(address >> 8u), + static_cast((address >> 40u) & 0xffu) | (Format32Float << 20u) | (((Width - 1u) & 3u) << 30u), + ((Width - 1u) >> 2u) | ((height - 1u) << 14u) | (1u << 31u), + 0xfacu | (type << 28u), + depth - 1u, 0u, 0u, 0u, + }; +} + +std::string Hex(std::uint32_t value) { + char text[16]; + std::snprintf(text, sizeof(text), "0x%08x", value); + return text; +} + +std::uint32_t SourceRow(std::uint32_t tid) { + return tid < Threads ? tid : (tid - Threads + Threads / 2u) % Threads; +} + +template +std::array MovedStores(const std::array& code, std::uint32_t threads) { + auto moved = code; + for (auto& word : moved) { + if ((word & 0xfffff000u) == 0xe0701000u && (word & 0xfffu) >= Threads * Inputs * 4u) word += (threads - Threads) * Inputs * 4u; + } + return moved; +} + +template +void Run(AgcDriver::VulkanDevice& device, const std::array& source, std::uint32_t threads, std::uint32_t type, std::uint32_t height, std::uint32_t depth, + const std::array& names, const std::array& masked, const std::array& expected) { + alignas(256) static std::array code; + code = MovedStores(source, threads); + for (std::uint32_t tid = 0; tid < threads; ++tid) { + std::copy_n(Input.begin() + SourceRow(tid) * Inputs, Inputs, Buffer.begin() + tid * Inputs); + } + std::fill(Buffer.begin() + threads * Inputs, Buffer.end(), 0xdeadbeefu); + for (std::uint32_t z = 0; z < depth; ++z) { + for (std::uint32_t y = 0; y < height; ++y) { + for (std::uint32_t x = 0; x < Width; ++x) { + Texels[(z * height + y) * Width + x] = static_cast(x + 100u * y + 1000u * z); + } + } + } + const auto address = reinterpret_cast(Buffer.data()); + const std::array buffer{static_cast(address), static_cast((address >> 32u) & 0xffffu), static_cast(Buffer.size() * 4u), 0x01016facu}; + const auto texture = TextureDescriptor(type, height, depth); + const std::array sampler{0x92u, (4u * 256u) << 12u, (1u << 22u) | (1u << 26u), 0u}; + std::vector userData(16, 0u); + std::copy(buffer.begin(), buffer.end(), userData.begin()); + std::copy(texture.begin(), texture.end(), userData.begin() + 4); + std::copy(sampler.begin(), sampler.end(), userData.begin() + 12); + const std::span span(code); + const std::array memory{{{reinterpret_cast(span.data()), std::as_bytes(span)}}}; + const ShaderRecompiler::ShaderComputeStageInfo compute{{threads, 1, 1}, 0u, {false, false, false}, false, 1}; + ShaderRecompiler::RecompileRequest request{ + {ShaderStage::Compute, reinterpret_cast(span.data()), span, 0, {}}, + {threads, 0, userData, compute, std::nullopt, std::nullopt, memory}, + device.Target(), + {0, 0, 0, 128} + }; + request.useCache = false; + const auto result = ShaderRecompiler::Recompile(request); + device.Dispatch(result, 1, 1, 1, {}, reinterpret_cast(span.data())); + device.WaitIdle(); + for (std::uint32_t tid = 0; tid < threads; ++tid) { + for (std::uint32_t k = 0; k < Cases; ++k) { + if (masked[k] && (device.Target().subgroupSize < Threads || tid >= Threads)) continue; + const auto actual = Buffer[threads * Inputs + tid * Results + k]; + const auto wanted = expected[SourceRow(tid) * Cases + k]; + const bool close = std::fabs(std::bit_cast(actual) - std::bit_cast(wanted)) <= 1.0f / 64.0f; + Require(close, std::string(names[k]) + ": wave" + std::to_string(threads) + " lane " + std::to_string(tid) + " is " + Hex(actual) + ", expected " + Hex(wanted)); + } + } +} + +} + +int main() { + try { + const auto device = OpenVulkanTestDevice(); + if (!device) return VulkanTestSkipped; + if (device->Target().subgroupSize < Threads) { + std::printf("EXEC-masked cases skipped, subgroup size %u cannot hold a wave32\n", device->Target().subgroupSize); + } + std::vector waves{Threads}; + if (device->Target().subgroupSize >= Threads) waves.push_back(Wave64Threads); + for (const auto threads : waves) { + Run(*device, Code2D, threads, 9u, Height, 1u, Names2D, Masked2D, Expected2D); + Run(*device, Code3D, threads, 10u, Height, Depth, Names3D, Masked3D, Expected3D); + Run(*device, Code1D, threads, 8u, 1u, 1u, Names1D, Masked1D, Expected1D); + } + std::puts("image sample derivatives tests passed"); + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } +} diff --git a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaInstruction.hpp b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaInstruction.hpp index a3b7ea54c..1c7598815 100644 --- a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaInstruction.hpp +++ b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaInstruction.hpp @@ -73,8 +73,12 @@ enum RdnaImageSampleFlag : std::uint32_t { RdnaImageSampleFlagCd = 1u << 8u, RdnaImageSampleFlagGatherHorizontal = 1u << 9u, RdnaImageSampleFlagAdjust = 1u << 10u, + RdnaImageSampleFlagG16 = 1u << 11u, }; +inline constexpr std::uint32_t RdnaImageSampleGradientCountShift = 12u; +inline constexpr std::uint32_t RdnaImageSampleGradientCountMask = 3u << RdnaImageSampleGradientCountShift; + inline constexpr std::uint32_t MaxRdnaInstructionRawWords = 5; inline constexpr std::uint32_t MaxRdnaImageNsaAddressComponents = 12; diff --git a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp index 83a4a5604..db51e913f 100644 --- a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp +++ b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp @@ -140,6 +140,30 @@ enum class RdnaOpcode : std::uint16_t { ImageSampleDO, ImageSampleLzO, ImageSampleO, + ImageSampleCd, + ImageSampleCdCl, + ImageSampleCCd, + ImageSampleCCdCl, + ImageSampleCdO, + ImageSampleCdClO, + ImageSampleCCdO, + ImageSampleCCdClO, + ImageSampleDG16, + ImageSampleDClG16, + ImageSampleCDG16, + ImageSampleCDClG16, + ImageSampleDOG16, + ImageSampleDClOG16, + ImageSampleCDOG16, + ImageSampleCDClOG16, + ImageSampleCdG16, + ImageSampleCdClG16, + ImageSampleCCdG16, + ImageSampleCCdClG16, + ImageSampleCdOG16, + ImageSampleCdClOG16, + ImageSampleCCdOG16, + ImageSampleCCdClOG16, ImageLoad, ImageStore, ImageGetResinfo, diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp index 0a44d6361..a568080a1 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp @@ -40,7 +40,30 @@ constexpr ImageOpcodeInfo imageOpcodes[] = { {0x35u, RdnaOpcode::ImageSampleBO, "image_sample_b_o", RdnaImageSampleFlagBias | RdnaImageSampleFlagOffset, true, false, false}, {0x37u, RdnaOpcode::ImageSampleLzO, "image_sample_lz_o", RdnaImageSampleFlagLevelZero | RdnaImageSampleFlagOffset, true, false, false}, {0x38u, RdnaOpcode::ImageSampleCO, "image_sample_c_o", RdnaImageSampleFlagCompare | RdnaImageSampleFlagOffset, true, false, false}, - {0x68u, RdnaOpcode::ImageSample, "image_sample_cd", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagCd, true, false, false}, + {0x68u, RdnaOpcode::ImageSampleCd, "image_sample_cd", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagCd, true, false, false}, + {0x69u, RdnaOpcode::ImageSampleCdCl, "image_sample_cd_cl", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagCd, true, false, false}, + {0x6au, RdnaOpcode::ImageSampleCCd, "image_sample_c_cd", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagCd, true, false, false}, + {0x6bu, RdnaOpcode::ImageSampleCCdCl, "image_sample_c_cd_cl", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagCd, true, false, false}, + {0x6cu, RdnaOpcode::ImageSampleCdO, "image_sample_cd_o", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd, true, false, false}, + {0x6du, RdnaOpcode::ImageSampleCdClO, "image_sample_cd_cl_o", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd, true, false, false}, + {0x6eu, RdnaOpcode::ImageSampleCCdO, "image_sample_c_cd_o", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd, true, false, false}, + {0x6fu, RdnaOpcode::ImageSampleCCdClO, "image_sample_c_cd_cl_o", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd, true, false, false}, + {0xa2u, RdnaOpcode::ImageSampleDG16, "image_sample_d_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagG16, true, false, false}, + {0xa3u, RdnaOpcode::ImageSampleDClG16, "image_sample_d_cl_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagG16, true, false, false}, + {0xaau, RdnaOpcode::ImageSampleCDG16, "image_sample_c_d_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagG16, true, false, false}, + {0xabu, RdnaOpcode::ImageSampleCDClG16, "image_sample_c_d_cl_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagG16, true, false, false}, + {0xb2u, RdnaOpcode::ImageSampleDOG16, "image_sample_d_o_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagG16, true, false, false}, + {0xb3u, RdnaOpcode::ImageSampleDClOG16, "image_sample_d_cl_o_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagG16, true, false, false}, + {0xbau, RdnaOpcode::ImageSampleCDOG16, "image_sample_c_d_o_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagG16, true, false, false}, + {0xbbu, RdnaOpcode::ImageSampleCDClOG16, "image_sample_c_d_cl_o_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagG16, true, false, false}, + {0xe8u, RdnaOpcode::ImageSampleCdG16, "image_sample_cd_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xe9u, RdnaOpcode::ImageSampleCdClG16, "image_sample_cd_cl_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xeau, RdnaOpcode::ImageSampleCCdG16, "image_sample_c_cd_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xebu, RdnaOpcode::ImageSampleCCdClG16, "image_sample_c_cd_cl_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xecu, RdnaOpcode::ImageSampleCdOG16, "image_sample_cd_o_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xedu, RdnaOpcode::ImageSampleCdClOG16, "image_sample_cd_cl_o_g16", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xeeu, RdnaOpcode::ImageSampleCCdOG16, "image_sample_c_cd_o_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, + {0xefu, RdnaOpcode::ImageSampleCCdClOG16, "image_sample_c_cd_cl_o_g16", RdnaImageSampleFlagCompare | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset | RdnaImageSampleFlagCd | RdnaImageSampleFlagG16, true, false, false}, {0x33u, RdnaOpcode::ImageSample, "image_sample_d_cl_o", RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagOffset, true, false, false}, {0xa0u, RdnaOpcode::ImageSample, "image_sample_a", RdnaImageSampleFlagAdjust, true, false, false}, {0xa1u, RdnaOpcode::ImageSample, "image_sample_cl_a", RdnaImageSampleFlagLodClamp | RdnaImageSampleFlagAdjust, true, false, false}, @@ -124,12 +147,12 @@ const ImageOpcodeInfo& lookupOpcode(std::uint32_t opcode) { } void validateFlags(std::uint32_t flags) { - constexpr std::uint32_t known = (1u << 11u) - 1u; + constexpr std::uint32_t known = ((1u << 12u) - 1u) | RdnaImageSampleGradientCountMask; if ((flags & ~known) != 0u) { throw std::runtime_error("unknown image address flags"); } - if ((flags & RdnaImageSampleFlagCd) != 0u) { - throw std::runtime_error("unsupported image coarse derivative (_cd) address layout"); + if (((flags & RdnaImageSampleGradientCountMask) != 0u) != ((flags & RdnaImageSampleFlagDerivative) != 0u)) { + throw std::runtime_error("image derivative flags without a gradient count"); } const auto lodModes = flags & (RdnaImageSampleFlagLod | RdnaImageSampleFlagBias | RdnaImageSampleFlagDerivative | RdnaImageSampleFlagLevelZero); if (std::popcount(lodModes) > 1) { @@ -137,27 +160,41 @@ void validateFlags(std::uint32_t flags) { } } -std::uint32_t componentWidth(std::uint32_t flags, std::uint32_t component) { - if ((flags & RdnaImageSampleFlagA16) == 0u) { - return 32; - } +struct ComponentShape { + std::uint32_t width; + bool startsDword; +}; + +ComponentShape componentShape(std::uint32_t flags, std::uint32_t component) { + const bool a16 = (flags & RdnaImageSampleFlagA16) != 0u; std::uint32_t cursor = 0; if ((flags & RdnaImageSampleFlagOffset) != 0u) { if (component == cursor) { - return 32; + return {32, true}; } ++cursor; } if ((flags & RdnaImageSampleFlagBias) != 0u) { if (component == cursor) { - return 16; + return {a16 ? 16u : 32u, !a16}; } ++cursor; } - if ((flags & RdnaImageSampleFlagCompare) != 0u && component == cursor) { - return 32; + if ((flags & RdnaImageSampleFlagCompare) != 0u) { + if (component == cursor) { + return {32, true}; + } + ++cursor; } - return 16; + const auto gradients = (flags & RdnaImageSampleGradientCountMask) >> RdnaImageSampleGradientCountShift; + if (component < cursor + gradients * 2u) { + if ((flags & RdnaImageSampleFlagG16) == 0u) { + return {32, true}; + } + return {16, (component - cursor) % gradients == 0u}; + } + cursor += gradients * 2u; + return {a16 ? 16u : 32u, !a16 || (gradients != 0u && component == cursor)}; } bool isBiasComponent(std::uint32_t flags, std::uint32_t component) { @@ -236,14 +273,14 @@ RdnaImageAddressComponent GetRdnaImageAddressComponentLayout(std::uint32_t flags } std::uint32_t offset = 0; for (std::uint32_t index = 0; index <= component; ++index) { - const auto width = componentWidth(flags, index); - if (width == 32u) { + const auto shape = componentShape(flags, index); + if (shape.startsDword) { offset = (offset + 31u) & ~31u; } if (index == component) { - return {offset, width}; + return {offset, shape.width}; } - offset += isBiasComponent(flags, index) ? 32u : width; + offset += isBiasComponent(flags, index) ? 32u : shape.width; } throw std::runtime_error("invalid image address component"); } @@ -292,13 +329,16 @@ RdnaInstruction DecodeRdnaMimg(std::uint32_t programCounter, std::span> 3u) & 7u); const bool multisampled = dimension == RdnaImageDimension::Dim2DMsaa || dimension == RdnaImageDimension::Dim2DMsaaArray; if (multisampled && (info.sample || info.gather || opcode == 0x60u || (opcode >= 1u && opcode <= 5u) || opcode == 9u || opcode == 0x0bu)) { throw std::runtime_error("unsupported multisampled MIMG operation"); } + auto flags = info.flags | (a16 ? RdnaImageSampleFlagA16 : 0u); + if ((info.flags & RdnaImageSampleFlagDerivative) != 0u) { + flags |= gradientCount(dimension) << RdnaImageSampleGradientCountShift; + } + validateFlags(flags); const auto dmask = (word0 >> 8u) & 15u; const bool compareSwap = info.opcode == RdnaOpcode::ImageAtomicCmpswap || info.opcode == RdnaOpcode::ImageAtomicFcmpswap; if (dmask == 0u || (compareSwap ? dmask != 3u : (info.gather || info.atomic) && !std::has_single_bit(dmask))) { diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp index e0649a014..7473a018d 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp @@ -782,6 +782,30 @@ bool IsImageOpcode(RdnaOpcode opcode) { case RdnaOpcode::ImageSampleDO: case RdnaOpcode::ImageSampleLzO: case RdnaOpcode::ImageSampleO: + case RdnaOpcode::ImageSampleCd: + case RdnaOpcode::ImageSampleCdCl: + case RdnaOpcode::ImageSampleCCd: + case RdnaOpcode::ImageSampleCCdCl: + case RdnaOpcode::ImageSampleCdO: + case RdnaOpcode::ImageSampleCdClO: + case RdnaOpcode::ImageSampleCCdO: + case RdnaOpcode::ImageSampleCCdClO: + case RdnaOpcode::ImageSampleDG16: + case RdnaOpcode::ImageSampleDClG16: + case RdnaOpcode::ImageSampleCDG16: + case RdnaOpcode::ImageSampleCDClG16: + case RdnaOpcode::ImageSampleDOG16: + case RdnaOpcode::ImageSampleDClOG16: + case RdnaOpcode::ImageSampleCDOG16: + case RdnaOpcode::ImageSampleCDClOG16: + case RdnaOpcode::ImageSampleCdG16: + case RdnaOpcode::ImageSampleCdClG16: + case RdnaOpcode::ImageSampleCCdG16: + case RdnaOpcode::ImageSampleCCdClG16: + case RdnaOpcode::ImageSampleCdOG16: + case RdnaOpcode::ImageSampleCdClOG16: + case RdnaOpcode::ImageSampleCCdOG16: + case RdnaOpcode::ImageSampleCCdClOG16: case RdnaOpcode::ImageSampleLz: case RdnaOpcode::ImageLoad: case RdnaOpcode::ImageStore: diff --git a/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryInstructionDispatch.cpp b/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryInstructionDispatch.cpp index 979c2080a..ae2a77fdf 100644 --- a/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryInstructionDispatch.cpp +++ b/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryInstructionDispatch.cpp @@ -435,6 +435,30 @@ bool TranslationContext::emitMemory(const RdnaInstruction& inst) { case RdnaOpcode::ImageSampleDO: case RdnaOpcode::ImageSampleLzO: case RdnaOpcode::ImageSampleO: + case RdnaOpcode::ImageSampleCd: + case RdnaOpcode::ImageSampleCdCl: + case RdnaOpcode::ImageSampleCCd: + case RdnaOpcode::ImageSampleCCdCl: + case RdnaOpcode::ImageSampleCdO: + case RdnaOpcode::ImageSampleCdClO: + case RdnaOpcode::ImageSampleCCdO: + case RdnaOpcode::ImageSampleCCdClO: + case RdnaOpcode::ImageSampleDG16: + case RdnaOpcode::ImageSampleDClG16: + case RdnaOpcode::ImageSampleCDG16: + case RdnaOpcode::ImageSampleCDClG16: + case RdnaOpcode::ImageSampleDOG16: + case RdnaOpcode::ImageSampleDClOG16: + case RdnaOpcode::ImageSampleCDOG16: + case RdnaOpcode::ImageSampleCDClOG16: + case RdnaOpcode::ImageSampleCdG16: + case RdnaOpcode::ImageSampleCdClG16: + case RdnaOpcode::ImageSampleCCdG16: + case RdnaOpcode::ImageSampleCCdClG16: + case RdnaOpcode::ImageSampleCdOG16: + case RdnaOpcode::ImageSampleCdClOG16: + case RdnaOpcode::ImageSampleCCdOG16: + case RdnaOpcode::ImageSampleCCdClOG16: return imageSample(inst); case RdnaOpcode::ImageGather4Lz: case RdnaOpcode::ImageGather4C: diff --git a/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryResourceHelpers.cpp b/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryResourceHelpers.cpp index 88e1afe14..369b78f6c 100644 --- a/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryResourceHelpers.cpp +++ b/core/shader/recompiler/Translation/src/MemoryInstructions/MemoryResourceHelpers.cpp @@ -3,6 +3,7 @@ #include "RdnaDecoder/RdnaImageOpDecoder.hpp" #include #include +#include #include namespace ShaderRecompiler { @@ -109,6 +110,24 @@ IrValue* TranslationContext::makeImageAddress(const RdnaInstruction& inst, const components[index] = &readRawU32(offsetOperand(plainBase, index)).Value(); } } + if ((inst.imageSampleFlags & RdnaImageSampleFlagCd) != 0u) { + const auto mask = ballotMask(IrU1(ir.GetExec())); + IrValue& lane = ir.Emit(IrOpcode::LaneId, IrType::U32, {}); + IrValue& quad = ir.BitwiseAnd(lane, ir.Constant(~3u)); + IrValue& word = program.WaveSize() == 64u ? ir.Select(ir.ULessThan(lane, ir.Constant(32u)), mask[0].Value(), mask[1].Value()) : mask[0].Value(); + IrValue& active = ir.BitwiseAnd(ir.ShiftRightLogical(word, ir.BitwiseAnd(quad, ir.Constant(31u))), ir.Constant(15u)); + IrValue& first = ir.Emit(IrOpcode::FindILsb32, IrType::U32, {&active}); + IrValue& source = ir.Select(ir.INotEqual(active, ir.Constant(0u)), ir.IAdd(quad, first), lane); + IrValue& address = ir.ShiftLeftLogical(source, ir.Constant(2u)); + IrValue& exec = ir.GetExec(); + const std::uint32_t gradientStart = std::popcount(inst.imageSampleFlags & (RdnaImageSampleFlagOffset | RdnaImageSampleFlagBias | RdnaImageSampleFlagCompare)); + const std::uint32_t gradients = 2u * ((inst.imageSampleFlags & RdnaImageSampleGradientCountMask) >> RdnaImageSampleGradientCountShift); + const std::uint32_t firstDword = GetRdnaImageAddressComponentLayout(inst.imageSampleFlags, gradientStart).bitOffset / 32u; + const std::uint32_t lastDword = GetRdnaImageAddressComponentLayout(inst.imageSampleFlags, gradientStart + gradients - 1u).bitOffset / 32u; + for (std::uint32_t index = firstDword; index <= lastDword; ++index) { + components[index] = &ir.Emit(IrOpcode::BpermuteU32, IrOpcodeType(IrOpcode::BpermuteU32), {components[index], &address, &exec}); + } + } return &ir.Emit(IrOpcode::MakeImageAddress, IrOpcodeType(IrOpcode::MakeImageAddress), {components[0], components[1], components[2], components[3], components[4], components[5], components[6], components[7], components[8], components[9], components[10], components[11], components[12]});