mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +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;
|
||||
};
|
||||
|
||||
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 features {};
|
||||
features.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
|
||||
@@ -217,6 +228,7 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
||||
device_features2.pNext = &features13;
|
||||
|
||||
device.getFeatures2(&device_features2);
|
||||
const auto required_features12 = WindowContext::RequiredVulkan12Features();
|
||||
const auto required_features13 = WindowContext::RequiredVulkan13Features();
|
||||
|
||||
const auto queue_family = VulkanFindQueueFamily(device, surface);
|
||||
@@ -249,14 +261,31 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
||||
}
|
||||
#endif
|
||||
|
||||
if (features12.samplerMirrorClampToEdge != VK_TRUE) {
|
||||
if (required_features12.samplerMirrorClampToEdge == VK_TRUE &&
|
||||
features12.samplerMirrorClampToEdge != VK_TRUE) {
|
||||
LOGF("samplerMirrorClampToEdge is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (features12.timelineSemaphore != VK_TRUE) {
|
||||
if (required_features12.timelineSemaphore == VK_TRUE &&
|
||||
features12.timelineSemaphore != VK_TRUE) {
|
||||
LOGF("timelineSemaphore is not supported\n");
|
||||
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) {
|
||||
LOGF("robustImageAccess is not supported\n");
|
||||
skip_device = true;
|
||||
@@ -291,11 +320,6 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
||||
LOGF("largePoints is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (features12.shaderOutputLayer != VK_TRUE) {
|
||||
LOGF("shaderOutputLayer is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
|
||||
if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) {
|
||||
LOGF("fragmentStoresAndAtomics is not supported\n");
|
||||
skip_device = true;
|
||||
@@ -547,10 +571,8 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
||||
#endif
|
||||
depth_clip_control.depthClipControl = VK_TRUE;
|
||||
|
||||
vk::PhysicalDeviceVulkan12Features features12 {};
|
||||
features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
|
||||
features12.pNext = &depth_clip_control;
|
||||
features12.samplerMirrorClampToEdge = VK_TRUE;
|
||||
auto features12 = WindowContext::RequiredVulkan12Features();
|
||||
features12.pNext = &depth_clip_control;
|
||||
|
||||
vk::PhysicalDeviceVulkan13Features supported_features13 {};
|
||||
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.pNext = &supported_features13;
|
||||
physical_device.getFeatures2(&supported_features2);
|
||||
const auto required_features12 = WindowContext::RequiredVulkan12Features();
|
||||
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 &&
|
||||
supported_features13.dynamicRendering != 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.shaderInt64 != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.vertexPipelineStoresAndAtomics != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features12.shaderOutputLayer != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features12.bufferDeviceAddress != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features12.shaderBufferInt64Atomics != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(required_features12.shaderOutputLayer == VK_TRUE &&
|
||||
supported_features12.shaderOutputLayer != 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__)
|
||||
EXIT_NOT_IMPLEMENTED(supported_fragment_barycentric.fragmentShaderBarycentric != VK_TRUE);
|
||||
#endif
|
||||
features12.timelineSemaphore = VK_TRUE;
|
||||
features12.shaderOutputLayer = VK_TRUE;
|
||||
features12.bufferDeviceAddress = VK_TRUE;
|
||||
features12.shaderBufferInt64Atomics = VK_TRUE;
|
||||
|
||||
vk::PhysicalDeviceFeatures device_features {};
|
||||
device_features.fragmentStoresAndAtomics = VK_TRUE;
|
||||
device_features.samplerAnisotropy = VK_TRUE;
|
||||
|
||||
@@ -35,6 +35,7 @@ struct WindowContext {
|
||||
~WindowContext();
|
||||
KYTY_CLASS_NO_COPY(WindowContext);
|
||||
|
||||
[[nodiscard]] static vk::PhysicalDeviceVulkan12Features RequiredVulkan12Features() noexcept;
|
||||
[[nodiscard]] static vk::PhysicalDeviceVulkan13Features RequiredVulkan13Features() noexcept;
|
||||
[[nodiscard]] static uint32_t InitialWindowFlags(bool fullscreen) noexcept;
|
||||
void CreateVulkan();
|
||||
|
||||
@@ -523,20 +523,14 @@ bool Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
|
||||
const auto resource = GetBufferResource(memory);
|
||||
const auto address = ReadBufferAddress(inst, 1);
|
||||
const auto data_src = MemorySourceAt(inst, 0);
|
||||
IR::Value data = ReadU32(data_src);
|
||||
if (memory.data_dwords == 2u) {
|
||||
data = ir.ConstructU64(ReadU32(data_src), ReadU32(OffsetOperand(data_src, 1u)));
|
||||
}
|
||||
const IR::Value data =
|
||||
memory.data_dwords == 2u ? IR::Value(ReadU64(data_src)) : IR::Value(ReadU32(data_src));
|
||||
const auto result = ir.Emit(opcode,
|
||||
{resource, address.index, address.offset, address.soffset, data,
|
||||
ir.GetExec()},
|
||||
AddMemoryInfo(memory, inst.pc));
|
||||
if (inst.glc) {
|
||||
WriteOperand(inst.dst,
|
||||
memory.data_dwords == 1u ? result : ir.CompositeExtract(result, 0u));
|
||||
if (memory.data_dwords == 2u) {
|
||||
WriteOperand(OffsetOperand(inst.dst, 1u), ir.CompositeExtract(result, 1u));
|
||||
}
|
||||
WriteOperand(inst.dst, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8618,10 +8618,41 @@ void TestCapturedBufferAtomicOrX2() {
|
||||
"64-bit buffer atomic storage view does not use eight-byte elements");
|
||||
Check(CountSourceOccurrences(source, "Aliased") == 2u,
|
||||
"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,
|
||||
"buffer_atomic_or_x2 must lower to exactly one OpAtomicOr");
|
||||
Check(Common::ContainsStr(source, "OpMemoryBarrier"),
|
||||
"64-bit buffer atomic SPIR-V lacks its device-memory barrier");
|
||||
Check(memory_barrier != Common::FIND_INVALID_INDEX && atomic < 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() {
|
||||
|
||||
Reference in New Issue
Block a user