Merge pull request #475 from adriadam10/feat/mimg-coarse-g16

feat(shader): implement image_sample_cd/_g16 variants and fix a16 gradient layout
This commit is contained in:
Dean 2026-10-05 18:10:20 +13:00 committed by GitHub
commit bdd10f1929
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 499 additions and 19 deletions

View File

@ -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 <algorithm>
#include <array>
#include <bit>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <span>
#include <string>
#include <vector>
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<std::uint32_t, Threads * Inputs> 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<std::uint32_t, Wave64Threads * Inputs + Wave64Threads * Results> Buffer{};
alignas(256) std::array<float, Width * Height * Depth> Texels{};
alignas(256) constexpr std::array<std::uint32_t, 168> 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<std::uint32_t, 122> 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<std::uint32_t, 87> 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<const char*, 12> 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<bool, 12> Masked2D{false, false, true, false, false, false, false, false, false, false, false, true};
constexpr std::array<std::uint32_t, Threads * 12> 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<const char*, 6> 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<bool, 6> Masked3D{false, false, false, false, false, false};
constexpr std::array<std::uint32_t, Threads * 6> 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<const char*, 5> 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<bool, 5> Masked1D{false, false, false, false, false};
constexpr std::array<std::uint32_t, Threads * 5> 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<std::uint32_t, 8> TextureDescriptor(std::uint32_t type, std::uint32_t height, std::uint32_t depth) {
const auto address = static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(Texels.data()));
return {
static_cast<std::uint32_t>(address >> 8u),
static_cast<std::uint32_t>((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::size_t CodeWords>
std::array<std::uint32_t, CodeWords> MovedStores(const std::array<std::uint32_t, CodeWords>& 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 <std::size_t CodeWords, std::size_t Cases>
void Run(AgcDriver::VulkanDevice& device, const std::array<std::uint32_t, CodeWords>& source, std::uint32_t threads, std::uint32_t type, std::uint32_t height, std::uint32_t depth,
const std::array<const char*, Cases>& names, const std::array<bool, Cases>& masked, const std::array<std::uint32_t, Threads * Cases>& expected) {
alignas(256) static std::array<std::uint32_t, CodeWords> 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<float>(x + 100u * y + 1000u * z);
}
}
}
const auto address = reinterpret_cast<std::uintptr_t>(Buffer.data());
const std::array<std::uint32_t, 4> buffer{static_cast<std::uint32_t>(address), static_cast<std::uint32_t>((address >> 32u) & 0xffffu), static_cast<std::uint32_t>(Buffer.size() * 4u), 0x01016facu};
const auto texture = TextureDescriptor(type, height, depth);
const std::array<std::uint32_t, 4> sampler{0x92u, (4u * 256u) << 12u, (1u << 22u) | (1u << 26u), 0u};
std::vector<std::uint32_t> 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<const std::uint32_t> span(code);
const std::array<ShaderRecompiler::MemoryRegion, 1> memory{{{reinterpret_cast<std::uintptr_t>(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<std::uintptr_t>(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<std::uintptr_t>(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<float>(actual) - std::bit_cast<float>(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<std::uint32_t> 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;
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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<const std
}
const bool a16 = (word1 & 0x40000000u) != 0u;
const bool d16 = (word1 & 0x80000000u) != 0u;
const auto flags = info.flags | (a16 ? RdnaImageSampleFlagA16 : 0u);
validateFlags(flags);
const auto dimension = decodeDimension((word0 >> 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))) {

View File

@ -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:

View File

@ -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:

View File

@ -3,6 +3,7 @@
#include "RdnaDecoder/RdnaImageOpDecoder.hpp"
#include <algorithm>
#include <array>
#include <bit>
#include <stdexcept>
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]});