mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: Use VK_EXT_provoking_vertex where supported
This commit is contained in:
parent
bf389b94d6
commit
220c7c271b
|
@ -149,6 +149,9 @@ namespace Vulkan
|
|||
m_multisample_state = {};
|
||||
m_multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
|
||||
m_provoking_vertex = {};
|
||||
m_provoking_vertex.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
|
||||
|
||||
// set defaults
|
||||
SetNoCullRasterizationState();
|
||||
SetNoDepthTestState();
|
||||
|
@ -420,6 +423,13 @@ namespace Vulkan
|
|||
m_ci.subpass = subpass;
|
||||
}
|
||||
|
||||
void GraphicsPipelineBuilder::SetProvokingVertex(VkProvokingVertexModeEXT mode)
|
||||
{
|
||||
Util::AddPointerToChain(&m_rasterization_state, &m_provoking_vertex);
|
||||
|
||||
m_provoking_vertex.provokingVertexMode = mode;
|
||||
}
|
||||
|
||||
SamplerBuilder::SamplerBuilder() { Clear(); }
|
||||
|
||||
void SamplerBuilder::Clear()
|
||||
|
|
|
@ -128,6 +128,8 @@ namespace Vulkan
|
|||
void SetPipelineLayout(VkPipelineLayout layout);
|
||||
void SetRenderPass(VkRenderPass render_pass, u32 subpass);
|
||||
|
||||
void SetProvokingVertex(VkProvokingVertexModeEXT mode);
|
||||
|
||||
private:
|
||||
VkGraphicsPipelineCreateInfo m_ci;
|
||||
std::array<VkPipelineShaderStageCreateInfo, MAX_SHADER_STAGES> m_shader_stages;
|
||||
|
@ -152,6 +154,8 @@ namespace Vulkan
|
|||
std::array<VkDynamicState, MAX_DYNAMIC_STATE> m_dynamic_state_values;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo m_multisample_state;
|
||||
|
||||
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT m_provoking_vertex;
|
||||
};
|
||||
|
||||
class SamplerBuilder
|
||||
|
|
|
@ -458,6 +458,9 @@ namespace Vulkan
|
|||
if (enable_surface && !SupportsExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true))
|
||||
return false;
|
||||
|
||||
m_optional_extensions.vk_ext_provoking_vertex =
|
||||
SupportsExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -605,6 +608,15 @@ namespace Vulkan
|
|||
device_info.ppEnabledLayerNames = layer_names;
|
||||
}
|
||||
|
||||
// provoking vertex
|
||||
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
|
||||
if (m_optional_extensions.vk_ext_provoking_vertex)
|
||||
{
|
||||
provoking_vertex_feature.provokingVertexLast = VK_TRUE;
|
||||
Util::AddPointerToChain(&device_info, &provoking_vertex_feature);
|
||||
}
|
||||
|
||||
VkResult res = vkCreateDevice(m_physical_device, &device_info, nullptr, &m_device);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
|
@ -622,9 +634,39 @@ namespace Vulkan
|
|||
{
|
||||
vkGetDeviceQueue(m_device, m_present_queue_family_index, 0, &m_present_queue);
|
||||
}
|
||||
|
||||
ProcessDeviceExtensions();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::ProcessDeviceExtensions()
|
||||
{
|
||||
// advanced feature checks
|
||||
if (vkGetPhysicalDeviceFeatures2)
|
||||
{
|
||||
VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
|
||||
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_features = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
|
||||
void** pNext = &features2.pNext;
|
||||
|
||||
// add in optional feature structs
|
||||
if (m_optional_extensions.vk_ext_provoking_vertex)
|
||||
{
|
||||
*pNext = &provoking_vertex_features;
|
||||
pNext = &provoking_vertex_features.pNext;
|
||||
}
|
||||
|
||||
// query
|
||||
vkGetPhysicalDeviceFeatures2(m_physical_device, &features2);
|
||||
|
||||
// confirm we actually support it
|
||||
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
|
||||
}
|
||||
|
||||
Console.WriteLn("VK_EXT_provoking_vertex is %s",
|
||||
m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported");
|
||||
}
|
||||
|
||||
bool Context::CreateAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo ci = {};
|
||||
|
@ -1124,7 +1166,8 @@ namespace Vulkan
|
|||
void Context::DeferBufferDestruction(VkBuffer object, VmaAllocation allocation)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back([this, object, allocation]() { vmaDestroyBuffer(m_allocator, object, allocation); });
|
||||
resources.cleanup_resources.push_back(
|
||||
[this, object, allocation]() { vmaDestroyBuffer(m_allocator, object, allocation); });
|
||||
}
|
||||
|
||||
void Context::DeferBufferViewDestruction(VkBufferView object)
|
||||
|
|
|
@ -46,6 +46,11 @@ namespace Vulkan
|
|||
TEXTURE_BUFFER_SIZE = 64 * 1024 * 1024,
|
||||
};
|
||||
|
||||
struct OptionalExtensions
|
||||
{
|
||||
bool vk_ext_provoking_vertex : 1;
|
||||
};
|
||||
|
||||
~Context();
|
||||
|
||||
// Determines if the Vulkan validation layer is available on the system.
|
||||
|
@ -89,6 +94,7 @@ namespace Vulkan
|
|||
__fi const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_properties; }
|
||||
__fi const VkPhysicalDeviceFeatures& GetDeviceFeatures() const { return m_device_features; }
|
||||
__fi const VkPhysicalDeviceLimits& GetDeviceLimits() const { return m_device_properties.limits; }
|
||||
__fi const OptionalExtensions& GetOptionalExtensions() const { return m_optional_extensions; }
|
||||
|
||||
// Helpers for getting constants
|
||||
__fi VkDeviceSize GetUniformBufferAlignment() const
|
||||
|
@ -239,6 +245,7 @@ namespace Vulkan
|
|||
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer, const char** required_device_extensions,
|
||||
u32 num_required_device_extensions, const char** required_device_layers, u32 num_required_device_layers,
|
||||
const VkPhysicalDeviceFeatures* required_features);
|
||||
void ProcessDeviceExtensions();
|
||||
|
||||
bool CreateAllocator();
|
||||
void DestroyAllocator();
|
||||
|
@ -323,6 +330,7 @@ namespace Vulkan
|
|||
VkPhysicalDeviceFeatures m_device_features = {};
|
||||
VkPhysicalDeviceProperties m_device_properties = {};
|
||||
VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};
|
||||
OptionalExtensions m_optional_extensions = {};
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -257,6 +257,20 @@ namespace Vulkan
|
|||
command_buffer, src_stage_mask, dst_stage_mask, 0, 0, nullptr, 1, &buffer_info, 0, nullptr);
|
||||
}
|
||||
|
||||
void AddPointerToChain(void* head, const void* ptr)
|
||||
{
|
||||
VkBaseInStructure* last_st = static_cast<VkBaseInStructure*>(head);
|
||||
while (last_st->pNext)
|
||||
{
|
||||
if (last_st->pNext == ptr)
|
||||
return;
|
||||
|
||||
last_st = const_cast<VkBaseInStructure*>(last_st->pNext);
|
||||
}
|
||||
|
||||
last_st->pNext = static_cast<const VkBaseInStructure*>(ptr);
|
||||
}
|
||||
|
||||
const char* VkResultToString(VkResult res)
|
||||
{
|
||||
switch (res)
|
||||
|
|
|
@ -49,6 +49,9 @@ namespace Vulkan
|
|||
VkAccessFlags dst_access_mask, VkDeviceSize offset, VkDeviceSize size, VkPipelineStageFlags src_stage_mask,
|
||||
VkPipelineStageFlags dst_stage_mask);
|
||||
|
||||
// Adds a structure to a chain.
|
||||
void AddPointerToChain(void* head, const void* ptr);
|
||||
|
||||
const char* VkResultToString(VkResult res);
|
||||
void LogVulkanResult(const char* func_name, VkResult res, const char* msg, ...) /*printflike(4, 5)*/;
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@ bool GSDeviceVK::CheckFeatures()
|
|||
m_features.image_load_store = features.fragmentStoresAndAtomics;
|
||||
m_features.texture_barrier = true;
|
||||
m_features.prefer_new_textures = true;
|
||||
m_features.provoking_vertex_last = g_vulkan_context->GetOptionalExtensions().vk_ext_provoking_vertex;
|
||||
|
||||
if (!features.dualSrcBlend)
|
||||
{
|
||||
|
@ -1271,6 +1272,10 @@ bool GSDeviceVK::CompileConvertPipelines()
|
|||
gpb.SetNoBlendingState();
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (ShaderConvert i = ShaderConvert::COPY; static_cast<int>(i) < static_cast<int>(ShaderConvert::Count);
|
||||
i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
{
|
||||
|
@ -1494,6 +1499,10 @@ bool GSDeviceVK::CompileInterlacePipelines()
|
|||
gpb.SetRenderPass(rp, 0);
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(m_interlace.size()); i++)
|
||||
{
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader, StringUtil::StdStringFromFormat("ps_main%d", i).c_str());
|
||||
|
@ -1543,6 +1552,10 @@ bool GSDeviceVK::CompileMergePipelines()
|
|||
gpb.SetRenderPass(rp, 0);
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(m_merge.size()); i++)
|
||||
{
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader, StringUtil::StdStringFromFormat("ps_main%d", i).c_str());
|
||||
|
@ -1872,6 +1885,9 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
|||
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, p.cms.wrgba);
|
||||
}
|
||||
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
VkPipeline pipeline = gpb.Create(g_vulkan_context->GetDevice(), g_vulkan_shader_cache->GetPipelineCache(true));
|
||||
if (pipeline)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue