mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 11:26:56 +02:00
graphics: unify atomic feature and width handling
This commit is contained in:
@@ -63,6 +63,17 @@ struct VulkanExtensions {
|
|||||||
std::vector<vk::LayerProperties> available_layers;
|
std::vector<vk::LayerProperties> available_layers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vk::PhysicalDeviceVulkan12Features WindowContext::RequiredVulkan12Features() noexcept {
|
||||||
|
vk::PhysicalDeviceVulkan12Features features {};
|
||||||
|
features.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
|
||||||
|
features.samplerMirrorClampToEdge = VK_TRUE;
|
||||||
|
features.timelineSemaphore = VK_TRUE;
|
||||||
|
features.shaderOutputLayer = VK_TRUE;
|
||||||
|
features.bufferDeviceAddress = VK_TRUE;
|
||||||
|
features.shaderBufferInt64Atomics = VK_TRUE;
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
vk::PhysicalDeviceVulkan13Features WindowContext::RequiredVulkan13Features() noexcept {
|
vk::PhysicalDeviceVulkan13Features WindowContext::RequiredVulkan13Features() noexcept {
|
||||||
vk::PhysicalDeviceVulkan13Features features {};
|
vk::PhysicalDeviceVulkan13Features features {};
|
||||||
features.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
|
features.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
|
||||||
@@ -217,6 +228,7 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
|||||||
device_features2.pNext = &features13;
|
device_features2.pNext = &features13;
|
||||||
|
|
||||||
device.getFeatures2(&device_features2);
|
device.getFeatures2(&device_features2);
|
||||||
|
const auto required_features12 = WindowContext::RequiredVulkan12Features();
|
||||||
const auto required_features13 = WindowContext::RequiredVulkan13Features();
|
const auto required_features13 = WindowContext::RequiredVulkan13Features();
|
||||||
|
|
||||||
const auto queue_family = VulkanFindQueueFamily(device, surface);
|
const auto queue_family = VulkanFindQueueFamily(device, surface);
|
||||||
@@ -249,14 +261,31 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (features12.samplerMirrorClampToEdge != VK_TRUE) {
|
if (required_features12.samplerMirrorClampToEdge == VK_TRUE &&
|
||||||
|
features12.samplerMirrorClampToEdge != VK_TRUE) {
|
||||||
LOGF("samplerMirrorClampToEdge is not supported\n");
|
LOGF("samplerMirrorClampToEdge is not supported\n");
|
||||||
skip_device = true;
|
skip_device = true;
|
||||||
}
|
}
|
||||||
if (features12.timelineSemaphore != VK_TRUE) {
|
if (required_features12.timelineSemaphore == VK_TRUE &&
|
||||||
|
features12.timelineSemaphore != VK_TRUE) {
|
||||||
LOGF("timelineSemaphore is not supported\n");
|
LOGF("timelineSemaphore is not supported\n");
|
||||||
skip_device = true;
|
skip_device = true;
|
||||||
}
|
}
|
||||||
|
if (required_features12.shaderOutputLayer == VK_TRUE &&
|
||||||
|
features12.shaderOutputLayer != VK_TRUE) {
|
||||||
|
LOGF("shaderOutputLayer is not supported\n");
|
||||||
|
skip_device = true;
|
||||||
|
}
|
||||||
|
if (required_features12.bufferDeviceAddress == VK_TRUE &&
|
||||||
|
features12.bufferDeviceAddress != VK_TRUE) {
|
||||||
|
LOGF("bufferDeviceAddress is not supported\n");
|
||||||
|
skip_device = true;
|
||||||
|
}
|
||||||
|
if (required_features12.shaderBufferInt64Atomics == VK_TRUE &&
|
||||||
|
features12.shaderBufferInt64Atomics != VK_TRUE) {
|
||||||
|
LOGF("shaderBufferInt64Atomics is not supported\n");
|
||||||
|
skip_device = true;
|
||||||
|
}
|
||||||
if (features13.robustImageAccess != VK_TRUE) {
|
if (features13.robustImageAccess != VK_TRUE) {
|
||||||
LOGF("robustImageAccess is not supported\n");
|
LOGF("robustImageAccess is not supported\n");
|
||||||
skip_device = true;
|
skip_device = true;
|
||||||
@@ -291,11 +320,6 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
|||||||
LOGF("largePoints is not supported\n");
|
LOGF("largePoints is not supported\n");
|
||||||
skip_device = true;
|
skip_device = true;
|
||||||
}
|
}
|
||||||
if (features12.shaderOutputLayer != VK_TRUE) {
|
|
||||||
LOGF("shaderOutputLayer is not supported\n");
|
|
||||||
skip_device = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) {
|
if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) {
|
||||||
LOGF("fragmentStoresAndAtomics is not supported\n");
|
LOGF("fragmentStoresAndAtomics is not supported\n");
|
||||||
skip_device = true;
|
skip_device = true;
|
||||||
@@ -547,10 +571,8 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
|||||||
#endif
|
#endif
|
||||||
depth_clip_control.depthClipControl = VK_TRUE;
|
depth_clip_control.depthClipControl = VK_TRUE;
|
||||||
|
|
||||||
vk::PhysicalDeviceVulkan12Features features12 {};
|
auto features12 = WindowContext::RequiredVulkan12Features();
|
||||||
features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
|
features12.pNext = &depth_clip_control;
|
||||||
features12.pNext = &depth_clip_control;
|
|
||||||
features12.samplerMirrorClampToEdge = VK_TRUE;
|
|
||||||
|
|
||||||
vk::PhysicalDeviceVulkan13Features supported_features13 {};
|
vk::PhysicalDeviceVulkan13Features supported_features13 {};
|
||||||
supported_features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
|
supported_features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
|
||||||
@@ -586,8 +608,12 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
|||||||
supported_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
|
supported_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
|
||||||
supported_features2.pNext = &supported_features13;
|
supported_features2.pNext = &supported_features13;
|
||||||
physical_device.getFeatures2(&supported_features2);
|
physical_device.getFeatures2(&supported_features2);
|
||||||
|
const auto required_features12 = WindowContext::RequiredVulkan12Features();
|
||||||
const auto required_features13 = WindowContext::RequiredVulkan13Features();
|
const auto required_features13 = WindowContext::RequiredVulkan13Features();
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features12.timelineSemaphore != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(required_features12.samplerMirrorClampToEdge == VK_TRUE &&
|
||||||
|
supported_features12.samplerMirrorClampToEdge != VK_TRUE);
|
||||||
|
EXIT_NOT_IMPLEMENTED(required_features12.timelineSemaphore == VK_TRUE &&
|
||||||
|
supported_features12.timelineSemaphore != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(required_features13.dynamicRendering == VK_TRUE &&
|
EXIT_NOT_IMPLEMENTED(required_features13.dynamicRendering == VK_TRUE &&
|
||||||
supported_features13.dynamicRendering != VK_TRUE);
|
supported_features13.dynamicRendering != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(required_features13.synchronization2 == VK_TRUE &&
|
EXIT_NOT_IMPLEMENTED(required_features13.synchronization2 == VK_TRUE &&
|
||||||
@@ -599,17 +625,15 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
|||||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.largePoints != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(supported_features2.features.largePoints != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.shaderInt64 != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(supported_features2.features.shaderInt64 != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.vertexPipelineStoresAndAtomics != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(supported_features2.features.vertexPipelineStoresAndAtomics != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features12.shaderOutputLayer != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(required_features12.shaderOutputLayer == VK_TRUE &&
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features12.bufferDeviceAddress != VK_TRUE);
|
supported_features12.shaderOutputLayer != VK_TRUE);
|
||||||
EXIT_NOT_IMPLEMENTED(supported_features12.shaderBufferInt64Atomics != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(required_features12.bufferDeviceAddress == VK_TRUE &&
|
||||||
|
supported_features12.bufferDeviceAddress != VK_TRUE);
|
||||||
|
EXIT_NOT_IMPLEMENTED(required_features12.shaderBufferInt64Atomics == VK_TRUE &&
|
||||||
|
supported_features12.shaderBufferInt64Atomics != VK_TRUE);
|
||||||
#if !defined(__APPLE__)
|
#if !defined(__APPLE__)
|
||||||
EXIT_NOT_IMPLEMENTED(supported_fragment_barycentric.fragmentShaderBarycentric != VK_TRUE);
|
EXIT_NOT_IMPLEMENTED(supported_fragment_barycentric.fragmentShaderBarycentric != VK_TRUE);
|
||||||
#endif
|
#endif
|
||||||
features12.timelineSemaphore = VK_TRUE;
|
|
||||||
features12.shaderOutputLayer = VK_TRUE;
|
|
||||||
features12.bufferDeviceAddress = VK_TRUE;
|
|
||||||
features12.shaderBufferInt64Atomics = VK_TRUE;
|
|
||||||
|
|
||||||
vk::PhysicalDeviceFeatures device_features {};
|
vk::PhysicalDeviceFeatures device_features {};
|
||||||
device_features.fragmentStoresAndAtomics = VK_TRUE;
|
device_features.fragmentStoresAndAtomics = VK_TRUE;
|
||||||
device_features.samplerAnisotropy = VK_TRUE;
|
device_features.samplerAnisotropy = VK_TRUE;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct WindowContext {
|
|||||||
~WindowContext();
|
~WindowContext();
|
||||||
KYTY_CLASS_NO_COPY(WindowContext);
|
KYTY_CLASS_NO_COPY(WindowContext);
|
||||||
|
|
||||||
|
[[nodiscard]] static vk::PhysicalDeviceVulkan12Features RequiredVulkan12Features() noexcept;
|
||||||
[[nodiscard]] static vk::PhysicalDeviceVulkan13Features RequiredVulkan13Features() noexcept;
|
[[nodiscard]] static vk::PhysicalDeviceVulkan13Features RequiredVulkan13Features() noexcept;
|
||||||
[[nodiscard]] static uint32_t InitialWindowFlags(bool fullscreen) noexcept;
|
[[nodiscard]] static uint32_t InitialWindowFlags(bool fullscreen) noexcept;
|
||||||
void CreateVulkan();
|
void CreateVulkan();
|
||||||
|
|||||||
@@ -523,20 +523,14 @@ bool Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
|
|||||||
const auto resource = GetBufferResource(memory);
|
const auto resource = GetBufferResource(memory);
|
||||||
const auto address = ReadBufferAddress(inst, 1);
|
const auto address = ReadBufferAddress(inst, 1);
|
||||||
const auto data_src = MemorySourceAt(inst, 0);
|
const auto data_src = MemorySourceAt(inst, 0);
|
||||||
IR::Value data = ReadU32(data_src);
|
const IR::Value data =
|
||||||
if (memory.data_dwords == 2u) {
|
memory.data_dwords == 2u ? IR::Value(ReadU64(data_src)) : IR::Value(ReadU32(data_src));
|
||||||
data = ir.ConstructU64(ReadU32(data_src), ReadU32(OffsetOperand(data_src, 1u)));
|
|
||||||
}
|
|
||||||
const auto result = ir.Emit(opcode,
|
const auto result = ir.Emit(opcode,
|
||||||
{resource, address.index, address.offset, address.soffset, data,
|
{resource, address.index, address.offset, address.soffset, data,
|
||||||
ir.GetExec()},
|
ir.GetExec()},
|
||||||
AddMemoryInfo(memory, inst.pc));
|
AddMemoryInfo(memory, inst.pc));
|
||||||
if (inst.glc) {
|
if (inst.glc) {
|
||||||
WriteOperand(inst.dst,
|
WriteOperand(inst.dst, result);
|
||||||
memory.data_dwords == 1u ? result : ir.CompositeExtract(result, 0u));
|
|
||||||
if (memory.data_dwords == 2u) {
|
|
||||||
WriteOperand(OffsetOperand(inst.dst, 1u), ir.CompositeExtract(result, 1u));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8618,10 +8618,41 @@ void TestCapturedBufferAtomicOrX2() {
|
|||||||
"64-bit buffer atomic storage view does not use eight-byte elements");
|
"64-bit buffer atomic storage view does not use eight-byte elements");
|
||||||
Check(CountSourceOccurrences(source, "Aliased") == 2u,
|
Check(CountSourceOccurrences(source, "Aliased") == 2u,
|
||||||
"both storage-buffer views must declare that they alias");
|
"both storage-buffer views must declare that they alias");
|
||||||
|
const auto array_length =
|
||||||
|
Common::FindIndex(source, std::string("OpArrayLength"), 0);
|
||||||
|
const auto bounds_branch = Common::FindIndex(
|
||||||
|
source, std::string("OpBranchConditional"), array_length);
|
||||||
|
const auto atomic = Common::FindIndex(source, std::string("OpAtomicOr"), 0);
|
||||||
|
const auto memory_barrier =
|
||||||
|
Common::FindIndex(source, std::string("OpMemoryBarrier"), atomic);
|
||||||
|
Check(array_length != Common::FIND_INVALID_INDEX &&
|
||||||
|
bounds_branch != Common::FIND_INVALID_INDEX &&
|
||||||
|
atomic != Common::FIND_INVALID_INDEX && bounds_branch < atomic,
|
||||||
|
"64-bit buffer atomic was not guarded by storage-buffer bounds");
|
||||||
Check(SpirvInstructionOpcodeCount(result.spirv, 241u) == 1u,
|
Check(SpirvInstructionOpcodeCount(result.spirv, 241u) == 1u,
|
||||||
"buffer_atomic_or_x2 must lower to exactly one OpAtomicOr");
|
"buffer_atomic_or_x2 must lower to exactly one OpAtomicOr");
|
||||||
Check(Common::ContainsStr(source, "OpMemoryBarrier"),
|
Check(memory_barrier != Common::FIND_INVALID_INDEX && atomic < memory_barrier,
|
||||||
"64-bit buffer atomic SPIR-V lacks its device-memory barrier");
|
"64-bit buffer atomic lacks a following device-memory barrier");
|
||||||
|
|
||||||
|
const std::array glc_shader = {
|
||||||
|
shader[0] | (1u << 14u), shader[1],
|
||||||
|
EncodeMubuf0(0x1d, 32, false),
|
||||||
|
EncodeMubuf1(0, 0, 0), // preserve returned v0:v1 through a dwordx2 store
|
||||||
|
shader[2],
|
||||||
|
};
|
||||||
|
auto glc_result = RecompileForTest(glc_shader, options);
|
||||||
|
const ShaderRecompiler::IR::Inst *glc_atomic = nullptr;
|
||||||
|
for (const auto *block : glc_result.program.blocks) {
|
||||||
|
for (const auto &inst : *block) {
|
||||||
|
if (inst.GetOpcode() ==
|
||||||
|
ShaderRecompiler::IR::ValueOpcode::BufferAtomicOr64) {
|
||||||
|
glc_atomic = &inst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Check(glc_atomic != nullptr && glc_atomic->UseCount() == 2u,
|
||||||
|
"GLC=1 buffer_atomic_or_x2 did not feed both returned dwords");
|
||||||
|
CheckSpirvBinaryValidates(glc_result.spirv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestNewShaderRecompilerBranchConditionForms() {
|
void TestNewShaderRecompilerBranchConditionForms() {
|
||||||
|
|||||||
Reference in New Issue
Block a user