mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: add native 64-bit LDS OR with shared typed storage views
This commit is contained in:
@@ -16198,6 +16198,8 @@ private:
|
||||
(vk::QueueFlagBits::eCompute | vk::QueueFlagBits::eGraphics)) {
|
||||
vk::PhysicalDeviceVulkan12Features features12{};
|
||||
features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
|
||||
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR workgroup_layout{};
|
||||
features12.pNext = &workgroup_layout;
|
||||
vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR barycentric{};
|
||||
barycentric.sType = vk::StructureType::ePhysicalDeviceFragmentShaderBarycentricFeaturesKHR;
|
||||
barycentric.pNext = &features12;
|
||||
@@ -16207,6 +16209,11 @@ private:
|
||||
physical.getFeatures2(&features);
|
||||
if (barycentric.fragmentShaderBarycentric != true ||
|
||||
features.features.shaderInt64 != true ||
|
||||
features12.samplerMirrorClampToEdge != true ||
|
||||
features12.shaderOutputViewportIndex != true ||
|
||||
features12.shaderBufferInt64Atomics != true ||
|
||||
features12.shaderSharedInt64Atomics != true ||
|
||||
workgroup_layout.workgroupMemoryExplicitLayout != true ||
|
||||
features12.bufferDeviceAddress != true) {
|
||||
continue;
|
||||
}
|
||||
@@ -16220,7 +16227,7 @@ private:
|
||||
}
|
||||
}
|
||||
Require("VulkanHarness", "dispatch", m_physical_device != nullptr,
|
||||
"no Vulkan graphics+compute device with fragment barycentrics");
|
||||
"no Vulkan graphics+compute device with fragment barycentrics and 64-bit LDS atomics");
|
||||
m_physical_device.getMemoryProperties(&m_memory_properties);
|
||||
|
||||
vk::PhysicalDeviceFeatures available_features{};
|
||||
@@ -16305,12 +16312,11 @@ private:
|
||||
device_info.sType = vk::StructureType::eDeviceCreateInfo;
|
||||
device_info.queueCreateInfoCount = 1;
|
||||
device_info.pQueueCreateInfos = &queue_info;
|
||||
vk::PhysicalDeviceVulkan12Features device_features12{};
|
||||
device_features12.sType =
|
||||
vk::StructureType::ePhysicalDeviceVulkan12Features;
|
||||
device_features12.timelineSemaphore = true;
|
||||
device_features12.bufferDeviceAddress = true;
|
||||
device_features12.shaderOutputLayer = true;
|
||||
auto device_features12 = WindowContext::RequiredVulkan12Features();
|
||||
device_features12.shaderSharedInt64Atomics = true;
|
||||
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR workgroup_layout{};
|
||||
workgroup_layout.workgroupMemoryExplicitLayout = true;
|
||||
device_features12.pNext = &workgroup_layout;
|
||||
vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR barycentric{};
|
||||
barycentric.sType = vk::StructureType::ePhysicalDeviceFragmentShaderBarycentricFeaturesKHR;
|
||||
barycentric.pNext = &device_features12;
|
||||
@@ -16365,6 +16371,7 @@ private:
|
||||
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
|
||||
VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME,
|
||||
VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME,
|
||||
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME,
|
||||
VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME};
|
||||
if (m_rasterization_supported) {
|
||||
device_extensions.push_back(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
|
||||
@@ -26858,6 +26865,95 @@ TestCase DsAtomicReturnVariants() {
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase DsOrB64Bounds() {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
test.name = "DsOrB64Bounds";
|
||||
auto &code = test.code;
|
||||
AppendVMovU32(&code, 0, 0x1234);
|
||||
AppendVMovU32(&code, 7, 0);
|
||||
const u32 initial[] = {0x100, 0x200, 0x400, 0x800, 0x13579bdf};
|
||||
for (u32 i = 0; i < std::size(initial); ++i) {
|
||||
AppendVMovLiteral(&code, 3, initial[i]);
|
||||
code.push_back(EncodeDs0(0x0d, i * 4u));
|
||||
code.push_back(EncodeDs1(0, 3, 7));
|
||||
}
|
||||
AppendVMovU32(&code, 3, 1);
|
||||
AppendVMovU32(&code, 4, 2);
|
||||
AppendVMovU32(&code, 7, 3); // The 64-bit address ignores the low three bits.
|
||||
code.insert(code.end(), {0xd9280000u, 0x00000307u});
|
||||
AppendVMovLiteral(&code, 7, 0x10007);
|
||||
code.push_back(EncodeDs0(0x4a, 2)); // Offset before 16-bit wrap/alignment -> 8.
|
||||
code.push_back(EncodeDs1(0, 3, 7));
|
||||
AppendVMovLiteral(&code, 3, 0xffffffffu);
|
||||
AppendVMovLiteral(&code, 4, 0xffffffffu);
|
||||
AppendVMovU32(&code, 7, 16); // Only one DWORD remains: ignore the entire OR.
|
||||
code.insert(code.end(), {0xd9280000u, 0x00000307u});
|
||||
AppendVMovU32(&code, 7, 0);
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(0)));
|
||||
code.insert(code.end(), {0xd9280000u, 0x00000307u});
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(1)));
|
||||
for (u32 i = 0; i < std::size(initial); ++i) {
|
||||
code.push_back(EncodeDs0(0x36, i * 4u));
|
||||
code.push_back(EncodeDs1(8, 0, 7));
|
||||
AppendStoreVgpr(&code, 8, i);
|
||||
}
|
||||
AppendStoreVgpr(&code, 0, 5); // No-return DS must not overwrite the encoded VDst.
|
||||
AppendEnd(&code);
|
||||
test.expected = {0x101, 0x202, 0x401, 0x802, 0x13579bdf, 0x1234};
|
||||
test.compute_info.lds_size_dwords = 5;
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::DS_WRITE_B32, O::DS_OR_B64,
|
||||
O::DS_READ_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.required_spirv = {"OpAtomicOr %ulong", "WorkgroupMemoryExplicitLayoutKHR", "Aliased"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase DsOrB64Contention(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
test.name = wave_size == 32 ? "DsOrB64ContentionWave32" : "DsOrB64ContentionWave64";
|
||||
auto &code = test.code;
|
||||
AppendVMovU32(&code, 7, 0);
|
||||
code.push_back(EncodeSop1(0x04, 10, 126));
|
||||
code.push_back(EncodeVopc(0xc2, InlineU32(0), 0));
|
||||
code.push_back(EncodeSop1(0x04, 126, 106));
|
||||
for (u32 offset : {0, 4}) {
|
||||
code.push_back(EncodeDs0(0x0d, offset));
|
||||
code.push_back(EncodeDs1(0, 7, 7));
|
||||
}
|
||||
code.push_back(EncodeSop1(0x04, 126, 10));
|
||||
code.push_back(EncodeSopp(0x0a, 0));
|
||||
AppendVMovU32(&code, 5, 1);
|
||||
AppendVMovU32(&code, 6, 2);
|
||||
code.push_back(EncodeVop2(0x1a, 3, Vgpr(0), 5));
|
||||
code.push_back(EncodeVop2(0x1a, 4, Vgpr(0), 6));
|
||||
AppendSMovLiteral(&code, 126, 0x55555555u);
|
||||
AppendSMovLiteral(&code, 127, 0xaaaaaaaau);
|
||||
code.insert(code.end(), {0xd9280000u, 0x00000307u});
|
||||
code.push_back(EncodeSop1(0x04, 126, 10));
|
||||
code.push_back(EncodeSopp(0x0a, 0));
|
||||
for (u32 half = 0; half < 2; ++half) {
|
||||
code.push_back(EncodeDs0(0x36, half * 4));
|
||||
code.push_back(EncodeDs1(8, 0, 7));
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 8, 0, half * 128);
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.expected.assign(128, wave_size == 32 ? 0x55555555u : 0xffffffffu);
|
||||
test.expected.resize(256, wave_size == 32 ? 0xaaaaaaaau : 0xfffffffeu);
|
||||
test.compute_info.threads_num[0] = 128;
|
||||
test.compute_info.threads_num[1] = test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.compute_info.lds_size_dwords = 2;
|
||||
test.has_compute_info = true;
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::S_MOV_B64, O::S_BARRIER,
|
||||
O::V_CMP_EQ_U32, O::V_LSHLREV_B32, O::V_ADD_NC_U32,
|
||||
O::DS_WRITE_B32, O::DS_OR_B64, O::DS_READ_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.required_spirv = {"OpAtomicOr %ulong", "WorkgroupMemoryExplicitLayoutKHR", "Aliased"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase DsBoundedAtomicBoundaries(bool decrement, bool gds) {
|
||||
using O = ShaderOpcode;
|
||||
constexpr u32 guard = 0x13579bdfu;
|
||||
@@ -30392,6 +30488,8 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(DsWideGdsPartialBounds);
|
||||
AddCase(DsAtomicNoReturnVariants);
|
||||
AddCase(DsAtomicReturnVariants);
|
||||
AddCase(DsOrB64Bounds);
|
||||
for (u32 wave_size : {32, 64}) cases.push_back(DsOrB64Contention(wave_size));
|
||||
for (bool decrement : {false, true}) {
|
||||
for (bool gds : {false, true}) {
|
||||
cases.push_back(DsBoundedAtomicBoundaries(decrement, gds));
|
||||
@@ -32933,6 +33031,15 @@ void CheckShaderRecompilerFatalContracts() {
|
||||
(void)CompileCase(test);
|
||||
});
|
||||
|
||||
ExpectFatal("GdsOrB64Rejection", [] {
|
||||
TestCase test;
|
||||
test.name = "GdsOrB64Rejection";
|
||||
test.code = {EncodeDs0(0x4a, 0, true), EncodeDs1(0, 3, 7)};
|
||||
AppendEnd(&test.code);
|
||||
test.opcodes = {ShaderOpcode::DS_OR_B64, ShaderOpcode::S_ENDPGM};
|
||||
(void)CompileCase(test);
|
||||
});
|
||||
|
||||
{
|
||||
ShaderRecompiler::IR::Program program;
|
||||
program.resource_tracking_complete = true;
|
||||
|
||||
Reference in New Issue
Block a user