mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 18:25:28 +03:00
Implement primitive restart support
Maxwell3D also supports using an arbitrary restart index value however no games are known to use this so leave it for now.
This commit is contained in:
parent
3f3acc31d8
commit
feb179fcff
@ -126,7 +126,17 @@ namespace skyline::gpu {
|
|||||||
const vk::raii::PhysicalDevice &physicalDevice,
|
const vk::raii::PhysicalDevice &physicalDevice,
|
||||||
decltype(vk::DeviceQueueCreateInfo::queueCount) &vkQueueFamilyIndex,
|
decltype(vk::DeviceQueueCreateInfo::queueCount) &vkQueueFamilyIndex,
|
||||||
TraitManager &traits) {
|
TraitManager &traits) {
|
||||||
auto deviceFeatures2{physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures, vk::PhysicalDeviceShaderDrawParametersFeatures, vk::PhysicalDeviceProvokingVertexFeaturesEXT>()};
|
auto deviceFeatures2{physicalDevice.getFeatures2<
|
||||||
|
vk::PhysicalDeviceFeatures2,
|
||||||
|
vk::PhysicalDeviceCustomBorderColorFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceShaderFloat16Int8Features,
|
||||||
|
vk::PhysicalDeviceShaderAtomicInt64Features,
|
||||||
|
vk::PhysicalDeviceUniformBufferStandardLayoutFeatures,
|
||||||
|
vk::PhysicalDeviceShaderDrawParametersFeatures,
|
||||||
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT,
|
||||||
|
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>()};
|
||||||
decltype(deviceFeatures2) enabledFeatures2{}; // We only want to enable features we required due to potential overhead from unused features
|
decltype(deviceFeatures2) enabledFeatures2{}; // We only want to enable features we required due to potential overhead from unused features
|
||||||
|
|
||||||
#define FEAT_REQ(structName, feature) \
|
#define FEAT_REQ(structName, feature) \
|
||||||
@ -156,7 +166,11 @@ namespace skyline::gpu {
|
|||||||
throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension.data());
|
throw exception("Cannot find Vulkan device extension: \"{}\"", requiredExtension.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deviceProperties2{physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceDriverProperties, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>()};
|
auto deviceProperties2{physicalDevice.getProperties2<
|
||||||
|
vk::PhysicalDeviceProperties2,
|
||||||
|
vk::PhysicalDeviceDriverProperties,
|
||||||
|
vk::PhysicalDeviceFloatControlsProperties,
|
||||||
|
vk::PhysicalDeviceSubgroupProperties>()};
|
||||||
|
|
||||||
traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
|
traits = TraitManager(deviceFeatures2, enabledFeatures2, deviceExtensions, enabledExtensions, deviceProperties2);
|
||||||
traits.ApplyDriverPatches(context);
|
traits.ApplyDriverPatches(context);
|
||||||
|
@ -1743,6 +1743,33 @@ namespace skyline::gpu::interconnect {
|
|||||||
private:
|
private:
|
||||||
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState{};
|
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState{};
|
||||||
|
|
||||||
|
void ValidatePrimitiveRestartState() {
|
||||||
|
if (inputAssemblyState.primitiveRestartEnable) {
|
||||||
|
switch (inputAssemblyState.topology) {
|
||||||
|
case vk::PrimitiveTopology::eLineStrip:
|
||||||
|
case vk::PrimitiveTopology::eTriangleStrip:
|
||||||
|
case vk::PrimitiveTopology::eTriangleFan:
|
||||||
|
case vk::PrimitiveTopology::eLineStripWithAdjacency:
|
||||||
|
case vk::PrimitiveTopology::eTriangleStripWithAdjacency:
|
||||||
|
break; // Doesn't need any extension
|
||||||
|
|
||||||
|
case vk::PrimitiveTopology::ePointList:
|
||||||
|
case vk::PrimitiveTopology::eLineList:
|
||||||
|
case vk::PrimitiveTopology::eTriangleList:
|
||||||
|
case vk::PrimitiveTopology::eLineListWithAdjacency:
|
||||||
|
case vk::PrimitiveTopology::eTriangleListWithAdjacency:
|
||||||
|
if (!gpu.traits.supportsTopologyListRestart)
|
||||||
|
Logger::Warn("GPU doesn't support primitive restart with list topologies");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vk::PrimitiveTopology::ePatchList:
|
||||||
|
if (!gpu.traits.supportsTopologyPatchListRestart)
|
||||||
|
Logger::Warn("GPU doesn't support primitive restart with patch list topology");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetPrimitiveTopology(maxwell3d::PrimitiveTopology topology) {
|
void SetPrimitiveTopology(maxwell3d::PrimitiveTopology topology) {
|
||||||
auto[vkTopology, shaderTopology] = [topology]() -> std::tuple<vk::PrimitiveTopology, ShaderCompiler::InputTopology> {
|
auto[vkTopology, shaderTopology] = [topology]() -> std::tuple<vk::PrimitiveTopology, ShaderCompiler::InputTopology> {
|
||||||
@ -1778,6 +1805,10 @@ namespace skyline::gpu::interconnect {
|
|||||||
UpdateRuntimeInformation(runtimeInfo.input_topology, shaderTopology, maxwell3d::PipelineStage::Geometry);
|
UpdateRuntimeInformation(runtimeInfo.input_topology, shaderTopology, maxwell3d::PipelineStage::Geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPrimitiveRestartEnabled(bool enable) {
|
||||||
|
inputAssemblyState.primitiveRestartEnable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
/* Index Buffer */
|
/* Index Buffer */
|
||||||
private:
|
private:
|
||||||
struct IndexBuffer {
|
struct IndexBuffer {
|
||||||
@ -2540,6 +2571,8 @@ namespace skyline::gpu::interconnect {
|
|||||||
public:
|
public:
|
||||||
template<bool IsIndexed>
|
template<bool IsIndexed>
|
||||||
void Draw(u32 count, u32 first, i32 vertexOffset = 0) {
|
void Draw(u32 count, u32 first, i32 vertexOffset = 0) {
|
||||||
|
ValidatePrimitiveRestartState();
|
||||||
|
|
||||||
// Shader + Binding Setup
|
// Shader + Binding Setup
|
||||||
auto programState{CompileShaderProgramState()};
|
auto programState{CompileShaderProgramState()};
|
||||||
auto descriptorSet{gpu.descriptor.AllocateSet(*programState.descriptorSetLayout)};
|
auto descriptorSet{gpu.descriptor.AllocateSet(*programState.descriptorSetLayout)};
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace skyline::gpu {
|
namespace skyline::gpu {
|
||||||
TraitManager::TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2) : quirks(deviceProperties2.get<vk::PhysicalDeviceProperties2>().properties, deviceProperties2.get<vk::PhysicalDeviceDriverProperties>()) {
|
TraitManager::TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2) : quirks(deviceProperties2.get<vk::PhysicalDeviceProperties2>().properties, deviceProperties2.get<vk::PhysicalDeviceDriverProperties>()) {
|
||||||
bool hasCustomBorderColorExt{}, hasShaderAtomicInt64Ext{}, hasShaderFloat16Int8Ext{}, hasShaderDemoteToHelperExt, hasVertexAttributeDivisorExt, hasProvokingVertexExt{};
|
bool hasCustomBorderColorExt{}, hasShaderAtomicInt64Ext{}, hasShaderFloat16Int8Ext{}, hasShaderDemoteToHelperExt{}, hasVertexAttributeDivisorExt{}, hasProvokingVertexExt{}, hasPrimitiveTopologyListRestartExt{};
|
||||||
bool supportsUniformBufferStandardLayout{}; // We require VK_KHR_uniform_buffer_standard_layout but assume it is implicitly supported even when not present
|
bool supportsUniformBufferStandardLayout{}; // We require VK_KHR_uniform_buffer_standard_layout but assume it is implicitly supported even when not present
|
||||||
|
|
||||||
for (auto &extension : deviceExtensions) {
|
for (auto &extension : deviceExtensions) {
|
||||||
@ -42,6 +42,7 @@ namespace skyline::gpu {
|
|||||||
EXT_SET("VK_KHR_shader_float16_int8", hasShaderFloat16Int8Ext);
|
EXT_SET("VK_KHR_shader_float16_int8", hasShaderFloat16Int8Ext);
|
||||||
EXT_SET("VK_KHR_shader_float_controls", supportsFloatControls);
|
EXT_SET("VK_KHR_shader_float_controls", supportsFloatControls);
|
||||||
EXT_SET("VK_KHR_uniform_buffer_standard_layout", supportsUniformBufferStandardLayout);
|
EXT_SET("VK_KHR_uniform_buffer_standard_layout", supportsUniformBufferStandardLayout);
|
||||||
|
EXT_SET("VK_EXT_primitive_topology_list_restart", hasPrimitiveTopologyListRestartExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef EXT_SET
|
#undef EXT_SET
|
||||||
@ -110,6 +111,13 @@ namespace skyline::gpu {
|
|||||||
Logger::Warn("Cannot find VK_KHR_uniform_buffer_standard_layout, assuming implicit support");
|
Logger::Warn("Cannot find VK_KHR_uniform_buffer_standard_layout, assuming implicit support");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasPrimitiveTopologyListRestartExt) {
|
||||||
|
FEAT_SET(vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, primitiveTopologyListRestart, supportsTopologyListRestart)
|
||||||
|
FEAT_SET(vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, primitiveTopologyPatchListRestart, supportsTopologyPatchListRestart)
|
||||||
|
} else {
|
||||||
|
enabledFeatures2.unlink<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
#undef FEAT_SET
|
#undef FEAT_SET
|
||||||
|
|
||||||
if (supportsFloatControls)
|
if (supportsFloatControls)
|
||||||
@ -122,8 +130,8 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
std::string TraitManager::Summary() {
|
std::string TraitManager::Summary() {
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
"\n* Supports U8 Indices: {}\n* Supports Sampler Mirror Clamp To Edge: {}\n* Supports Sampler Reduction Mode: {}\n* Supports Custom Border Color (Without Format): {}\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}\n* Supports Vertex Attribute Zero Divisor: {}\n* Supports Multiple Viewports: {}\n* Supports Shader Viewport Index: {}\n* Supports SPIR-V 1.4: {}\n* Supports Shader Invocation Demotion: {}\n* Supports 16-bit FP: {}\n* Supports 8-bit Integers: {}\n* Supports 16-bit Integers: {}\n* Supports 64-bit Integers: {}\n* Supports Atomic 64-bit Integers: {}\n* Supports Floating Point Behavior Control: {}\n* Supports Image Read Without Format: {}\n* Supports Subgroup Vote: {}\n* Subgroup Size: {}",
|
"\n* Supports U8 Indices: {}\n* Supports Sampler Mirror Clamp To Edge: {}\n* Supports Sampler Reduction Mode: {}\n* Supports Custom Border Color (Without Format): {}\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}\n* Supports Vertex Attribute Zero Divisor: {}\n* Supports Multiple Viewports: {}\n* Supports Shader Viewport Index: {}\n* Supports SPIR-V 1.4: {}\n* Supports Shader Invocation Demotion: {}\n* Supports 16-bit FP: {}\n* Supports 8-bit Integers: {}\n* Supports 16-bit Integers: {}\n* Supports 64-bit Integers: {}\n* Supports Atomic 64-bit Integers: {}\n* Supports Floating Point Behavior Control: {}\n* Supports Image Read Without Format: {}\n* Supports List Primitive Topology Restart: {}\n* Supports Patch List Primitive Topology Restart: {}\n* Supports Subgroup Vote: {}\n* Subgroup Size: {}",
|
||||||
supportsUint8Indices, supportsSamplerMirrorClampToEdge, supportsSamplerReductionMode, supportsCustomBorderColor, supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor, supportsVertexAttributeZeroDivisor, supportsMultipleViewports, supportsShaderViewportIndexLayer, supportsSpirv14, supportsShaderDemoteToHelper, supportsFloat16, supportsInt8, supportsInt16, supportsInt64, supportsAtomicInt64, supportsFloatControls, supportsImageReadWithoutFormat, supportsSubgroupVote, subgroupSize
|
supportsUint8Indices, supportsSamplerMirrorClampToEdge, supportsSamplerReductionMode, supportsCustomBorderColor, supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor, supportsVertexAttributeZeroDivisor, supportsMultipleViewports, supportsShaderViewportIndexLayer, supportsSpirv14, supportsShaderDemoteToHelper, supportsFloat16, supportsInt8, supportsInt16, supportsInt64, supportsAtomicInt64, supportsFloatControls, supportsImageReadWithoutFormat, supportsTopologyListRestart, supportsTopologyPatchListRestart, supportsSubgroupVote, subgroupSize
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ namespace skyline::gpu {
|
|||||||
bool supportsFloatControls{}; //!< If extensive control over FP behavior is exposed (with VK_KHR_shader_float_controls)
|
bool supportsFloatControls{}; //!< If extensive control over FP behavior is exposed (with VK_KHR_shader_float_controls)
|
||||||
vk::PhysicalDeviceFloatControlsProperties floatControls{}; //!< Specifics of FP behavior control (All members will be zero'd out when unavailable)
|
vk::PhysicalDeviceFloatControlsProperties floatControls{}; //!< Specifics of FP behavior control (All members will be zero'd out when unavailable)
|
||||||
bool supportsImageReadWithoutFormat{}; //!< If a storage image can be read without a format
|
bool supportsImageReadWithoutFormat{}; //!< If a storage image can be read without a format
|
||||||
|
bool supportsTopologyListRestart{}; //!< If the device supports using primitive restart for topology lists (with VK_EXT_primitive_topology_list_restart)
|
||||||
|
bool supportsTopologyPatchListRestart{}; //!< If the device supports using primitive restart for topology patch lists (with VK_EXT_primitive_topology_list_restart)
|
||||||
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
|
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
|
||||||
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
|
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
|
||||||
|
|
||||||
@ -56,9 +58,23 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
TraitManager() = default;
|
TraitManager() = default;
|
||||||
|
|
||||||
using DeviceProperties2 = vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceDriverProperties, vk::PhysicalDeviceFloatControlsProperties, vk::PhysicalDeviceSubgroupProperties>;
|
using DeviceProperties2 = vk::StructureChain<
|
||||||
|
vk::PhysicalDeviceProperties2,
|
||||||
|
vk::PhysicalDeviceDriverProperties,
|
||||||
|
vk::PhysicalDeviceFloatControlsProperties,
|
||||||
|
vk::PhysicalDeviceSubgroupProperties>;
|
||||||
|
|
||||||
using DeviceFeatures2 = vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, vk::PhysicalDeviceShaderFloat16Int8Features, vk::PhysicalDeviceShaderAtomicInt64Features, vk::PhysicalDeviceUniformBufferStandardLayoutFeatures, vk::PhysicalDeviceShaderDrawParametersFeatures, vk::PhysicalDeviceProvokingVertexFeaturesEXT>;
|
using DeviceFeatures2 = vk::StructureChain<
|
||||||
|
vk::PhysicalDeviceFeatures2,
|
||||||
|
vk::PhysicalDeviceCustomBorderColorFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT,
|
||||||
|
vk::PhysicalDeviceShaderFloat16Int8Features,
|
||||||
|
vk::PhysicalDeviceShaderAtomicInt64Features,
|
||||||
|
vk::PhysicalDeviceUniformBufferStandardLayoutFeatures,
|
||||||
|
vk::PhysicalDeviceShaderDrawParametersFeatures,
|
||||||
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT,
|
||||||
|
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>;
|
||||||
|
|
||||||
TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2);
|
TraitManager(const DeviceFeatures2 &deviceFeatures2, DeviceFeatures2 &enabledFeatures2, const std::vector<vk::ExtensionProperties> &deviceExtensions, std::vector<std::array<char, VK_MAX_EXTENSION_NAME_SIZE>> &enabledExtensions, const DeviceProperties2 &deviceProperties2);
|
||||||
|
|
||||||
|
@ -494,6 +494,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
context.SetPrimitiveTopology(vertexBeginGl.topology);
|
context.SetPrimitiveTopology(vertexBeginGl.topology);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ENGINE_CASE(primitiveRestartEnable, {
|
||||||
|
context.SetPrimitiveRestartEnabled(primitiveRestartEnable);
|
||||||
|
})
|
||||||
|
|
||||||
ENGINE_STRUCT_CASE(constantBufferSelector, size, {
|
ENGINE_STRUCT_CASE(constantBufferSelector, size, {
|
||||||
context.SetConstantBufferSelectorSize(size);
|
context.SetConstantBufferSelectorSize(size);
|
||||||
})
|
})
|
||||||
|
@ -227,6 +227,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
Register<0x585, u32> vertexEndGl; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw
|
Register<0x585, u32> vertexEndGl; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw
|
||||||
Register<0x586, type::VertexBeginGl> vertexBeginGl; //!< Similar to glVertexBegin semantically, supplies a primitive topology for draws alongside instancing data
|
Register<0x586, type::VertexBeginGl> vertexBeginGl; //!< Similar to glVertexBegin semantically, supplies a primitive topology for draws alongside instancing data
|
||||||
|
|
||||||
|
Register<0x591, u32> primitiveRestartEnable;
|
||||||
|
Register<0x592, u32> primitiveRestartIndex;
|
||||||
|
|
||||||
Register<0x5A1, u32> provokingVertexIsLast;
|
Register<0x5A1, u32> provokingVertexIsLast;
|
||||||
|
|
||||||
Register<0x5F2, type::IndexBuffer> indexBuffer;
|
Register<0x5F2, type::IndexBuffer> indexBuffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user