mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: Use push descriptors instead of per-frame allocations
This commit is contained in:
parent
906d87c4b8
commit
cf523d4215
|
@ -352,16 +352,16 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||||
|
|
||||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||||
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
||||||
layout(set = 2, binding = 0) uniform texture2D RtSampler;
|
layout(set = 1, binding = 2) uniform texture2D RtSampler;
|
||||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||||
#else
|
#else
|
||||||
layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput RtSampler;
|
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PS_DATE > 0
|
#if PS_DATE > 0
|
||||||
layout(set = 2, binding = 1) uniform texture2D PrimMinTexture;
|
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NEEDS_TEX
|
#if NEEDS_TEX
|
||||||
|
|
|
@ -312,6 +312,12 @@ bool GSDeviceVK::SelectDeviceExtensions(ExtensionList* extension_list, bool enab
|
||||||
if (enable_surface && !SupportsExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true))
|
if (enable_surface && !SupportsExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Required extensions.
|
||||||
|
if (!SupportsExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_optional_extensions.vk_ext_provoking_vertex = SupportsExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false);
|
m_optional_extensions.vk_ext_provoking_vertex = SupportsExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false);
|
||||||
m_optional_extensions.vk_ext_memory_budget = SupportsExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false);
|
m_optional_extensions.vk_ext_memory_budget = SupportsExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false);
|
||||||
m_optional_extensions.vk_ext_calibrated_timestamps =
|
m_optional_extensions.vk_ext_calibrated_timestamps =
|
||||||
|
@ -570,7 +576,8 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||||
queue_family_properties[m_graphics_queue_family_index].timestampValidBits,
|
queue_family_properties[m_graphics_queue_family_index].timestampValidBits,
|
||||||
m_device_properties.limits.timestampPeriod);
|
m_device_properties.limits.timestampPeriod);
|
||||||
|
|
||||||
ProcessDeviceExtensions();
|
if (!ProcessDeviceExtensions())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (m_spinning_supported)
|
if (m_spinning_supported)
|
||||||
{
|
{
|
||||||
|
@ -591,7 +598,7 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceVK::ProcessDeviceExtensions()
|
bool GSDeviceVK::ProcessDeviceExtensions()
|
||||||
{
|
{
|
||||||
// advanced feature checks
|
// advanced feature checks
|
||||||
VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
|
VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
|
||||||
|
@ -626,18 +633,28 @@ void GSDeviceVK::ProcessDeviceExtensions()
|
||||||
(attachment_feedback_loop_feature.attachmentFeedbackLoopLayout == VK_TRUE);
|
(attachment_feedback_loop_feature.attachmentFeedbackLoopLayout == VK_TRUE);
|
||||||
|
|
||||||
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
|
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
|
||||||
void** pNext = &properties2.pNext;
|
|
||||||
|
|
||||||
if (m_optional_extensions.vk_khr_driver_properties)
|
if (m_optional_extensions.vk_khr_driver_properties)
|
||||||
{
|
{
|
||||||
m_device_driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
|
m_device_driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
|
||||||
*pNext = &m_device_driver_properties;
|
Vulkan::AddPointerToChain(&properties2, &m_device_driver_properties);
|
||||||
pNext = &m_device_driver_properties.pNext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor_properties = {
|
||||||
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR};
|
||||||
|
Vulkan::AddPointerToChain(&properties2, &push_descriptor_properties);
|
||||||
|
|
||||||
// query
|
// query
|
||||||
vkGetPhysicalDeviceProperties2(m_physical_device, &properties2);
|
vkGetPhysicalDeviceProperties2(m_physical_device, &properties2);
|
||||||
|
|
||||||
|
// confirm we actually support it
|
||||||
|
if (push_descriptor_properties.maxPushDescriptors < NUM_TFX_TEXTURES)
|
||||||
|
{
|
||||||
|
Console.Error("maxPushDescriptors (%u) is below required (%u)", push_descriptor_properties.maxPushDescriptors,
|
||||||
|
NUM_TFX_TEXTURES);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// VK_EXT_calibrated_timestamps checking
|
// VK_EXT_calibrated_timestamps checking
|
||||||
if (m_optional_extensions.vk_ext_calibrated_timestamps)
|
if (m_optional_extensions.vk_ext_calibrated_timestamps)
|
||||||
{
|
{
|
||||||
|
@ -674,14 +691,26 @@ void GSDeviceVK::ProcessDeviceExtensions()
|
||||||
|
|
||||||
Console.WriteLn(
|
Console.WriteLn(
|
||||||
"VK_EXT_provoking_vertex is %s", m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported");
|
"VK_EXT_provoking_vertex is %s", m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported");
|
||||||
Console.WriteLn("VK_EXT_line_rasterization is %s",
|
Console.WriteLn(
|
||||||
m_optional_extensions.vk_ext_line_rasterization ? "supported" : "NOT supported");
|
"VK_EXT_memory_budget is %s", m_optional_extensions.vk_ext_memory_budget ? "supported" : "NOT supported");
|
||||||
Console.WriteLn("VK_EXT_calibrated_timestamps is %s",
|
Console.WriteLn("VK_EXT_calibrated_timestamps is %s",
|
||||||
m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported");
|
m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported");
|
||||||
|
Console.WriteLn("VK_EXT_line_rasterization is %s",
|
||||||
|
m_optional_extensions.vk_ext_line_rasterization ? "supported" : "NOT supported");
|
||||||
Console.WriteLn("VK_EXT_rasterization_order_attachment_access is %s",
|
Console.WriteLn("VK_EXT_rasterization_order_attachment_access is %s",
|
||||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
||||||
Console.WriteLn("VK_EXT_attachment_feedback_loop_layout is %s",
|
Console.WriteLn("VK_EXT_attachment_feedback_loop_layout is %s",
|
||||||
m_optional_extensions.vk_ext_attachment_feedback_loop_layout ? "supported" : "NOT supported");
|
m_optional_extensions.vk_ext_attachment_feedback_loop_layout ? "supported" : "NOT supported");
|
||||||
|
Console.WriteLn("VK_EXT_full_screen_exclusive is %s",
|
||||||
|
m_optional_extensions.vk_ext_full_screen_exclusive ? "supported" : "NOT supported");
|
||||||
|
Console.WriteLn("VK_KHR_driver_properties is %s",
|
||||||
|
m_optional_extensions.vk_khr_driver_properties ? "supported" : "NOT supported");
|
||||||
|
Console.WriteLn("VK_KHR_fragment_shader_barycentric is %s",
|
||||||
|
m_optional_extensions.vk_khr_fragment_shader_barycentric ? "supported" : "NOT supported");
|
||||||
|
Console.WriteLn("VK_KHR_shader_draw_parameters is %s",
|
||||||
|
m_optional_extensions.vk_khr_shader_draw_parameters ? "supported" : "NOT supported");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSDeviceVK::CreateAllocator()
|
bool GSDeviceVK::CreateAllocator()
|
||||||
|
@ -788,26 +817,6 @@ bool GSDeviceVK::CreateCommandBuffers()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vulkan::SetObjectName(m_device, resources.fence, "Frame Fence %u", frame_index);
|
Vulkan::SetObjectName(m_device, resources.fence, "Frame Fence %u", frame_index);
|
||||||
// TODO: A better way to choose the number of descriptors.
|
|
||||||
VkDescriptorPoolSize pool_sizes[] = {
|
|
||||||
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_COMBINED_IMAGE_SAMPLER_DESCRIPTORS_PER_FRAME},
|
|
||||||
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_SAMPLED_IMAGE_DESCRIPTORS_PER_FRAME},
|
|
||||||
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MAX_STORAGE_IMAGE_DESCRIPTORS_PER_FRAME},
|
|
||||||
{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, MAX_INPUT_ATTACHMENT_IMAGE_DESCRIPTORS_PER_FRAME},
|
|
||||||
};
|
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr, 0,
|
|
||||||
MAX_DESCRIPTOR_SETS_PER_FRAME, static_cast<u32>(std::size(pool_sizes)), pool_sizes};
|
|
||||||
|
|
||||||
res = vkCreateDescriptorPool(m_device, &pool_create_info, nullptr, &resources.descriptor_pool);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Vulkan::SetObjectName(
|
|
||||||
m_device, resources.descriptor_pool, "Frame Descriptor Pool %u", frame_index);
|
|
||||||
|
|
||||||
++frame_index;
|
++frame_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,23 +927,6 @@ VkCommandBuffer GSDeviceVK::GetCurrentInitCommandBuffer()
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorSet GSDeviceVK::AllocateDescriptorSet(VkDescriptorSetLayout set_layout)
|
|
||||||
{
|
|
||||||
VkDescriptorSetAllocateInfo allocate_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
|
|
||||||
m_frame_resources[m_current_frame].descriptor_pool, 1, &set_layout};
|
|
||||||
|
|
||||||
VkDescriptorSet descriptor_set;
|
|
||||||
VkResult res = vkAllocateDescriptorSets(m_device, &allocate_info, &descriptor_set);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
// Failing to allocate a descriptor set is not a fatal error, we can
|
|
||||||
// recover by moving to the next command buffer.
|
|
||||||
return VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return descriptor_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDescriptorSet GSDeviceVK::AllocatePersistentDescriptorSet(VkDescriptorSetLayout set_layout)
|
VkDescriptorSet GSDeviceVK::AllocatePersistentDescriptorSet(VkDescriptorSetLayout set_layout)
|
||||||
{
|
{
|
||||||
VkDescriptorSetAllocateInfo allocate_info = {
|
VkDescriptorSetAllocateInfo allocate_info = {
|
||||||
|
@ -1345,11 +1337,6 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: ");
|
LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: ");
|
||||||
|
|
||||||
// Also can do the same for the descriptor pools
|
|
||||||
res = vkResetDescriptorPool(m_device, resources.descriptor_pool, 0);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
LOG_VULKAN_ERROR(res, "vkResetDescriptorPool failed: ");
|
|
||||||
|
|
||||||
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
|
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
|
||||||
if (wants_timestamp)
|
if (wants_timestamp)
|
||||||
{
|
{
|
||||||
|
@ -3472,7 +3459,7 @@ void GSDeviceVK::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
|
||||||
{
|
{
|
||||||
// need to update descriptors to reflect the new layout
|
// need to update descriptors to reflect the new layout
|
||||||
if ((feedback_loop & FeedbackLoopFlag_ReadDS) && vkDs->GetLayout() != GSTextureVK::Layout::FeedbackLoop)
|
if ((feedback_loop & FeedbackLoopFlag_ReadDS) && vkDs->GetLayout() != GSTextureVK::Layout::FeedbackLoop)
|
||||||
m_dirty_flags |= DIRTY_FLAG_TFX_SAMPLERS_DS;
|
m_dirty_flags |= (DIRTY_FLAG_TFX_TEXTURE_0 << TFX_TEXTURE_RT);
|
||||||
|
|
||||||
vkDs->TransitionToLayout((feedback_loop & FeedbackLoopFlag_ReadDS) ?
|
vkDs->TransitionToLayout((feedback_loop & FeedbackLoopFlag_ReadDS) ?
|
||||||
GSTextureVK::Layout::FeedbackLoop :
|
GSTextureVK::Layout::FeedbackLoop :
|
||||||
|
@ -3549,7 +3536,8 @@ static void AddMacro(std::stringstream& ss, const char* name, int value)
|
||||||
|
|
||||||
static void AddShaderHeader(std::stringstream& ss)
|
static void AddShaderHeader(std::stringstream& ss)
|
||||||
{
|
{
|
||||||
const GSDevice::FeatureSupport features(g_gs_device->Features());
|
const GSDeviceVK* dev = GSDeviceVK::GetInstance();
|
||||||
|
const GSDevice::FeatureSupport features = dev->Features();
|
||||||
|
|
||||||
ss << "#version 460 core\n";
|
ss << "#version 460 core\n";
|
||||||
ss << "#extension GL_EXT_samplerless_texture_functions : require\n";
|
ss << "#extension GL_EXT_samplerless_texture_functions : require\n";
|
||||||
|
@ -3561,7 +3549,7 @@ static void AddShaderHeader(std::stringstream& ss)
|
||||||
ss << "#define DISABLE_TEXTURE_BARRIER 1\n";
|
ss << "#define DISABLE_TEXTURE_BARRIER 1\n";
|
||||||
if (!features.dual_source_blend)
|
if (!features.dual_source_blend)
|
||||||
ss << "#define DISABLE_DUAL_SOURCE 1\n";
|
ss << "#define DISABLE_DUAL_SOURCE 1\n";
|
||||||
if (features.texture_barrier && GSDeviceVK::GetInstance()->UseFeedbackLoopLayout())
|
if (features.texture_barrier && dev->UseFeedbackLoopLayout())
|
||||||
ss << "#define HAS_FEEDBACK_LOOP_LAYOUT 1\n";
|
ss << "#define HAS_FEEDBACK_LOOP_LAYOUT 1\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3691,7 +3679,8 @@ bool GSDeviceVK::CreatePipelineLayouts()
|
||||||
// Convert Pipeline Layout
|
// Convert Pipeline Layout
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
dslb.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, NUM_CONVERT_SAMPLERS, VK_SHADER_STAGE_FRAGMENT_BIT);
|
dslb.SetPushFlag();
|
||||||
|
dslb.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, NUM_UTILITY_SAMPLERS, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
if ((m_utility_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
if ((m_utility_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
Vulkan::SetObjectName(dev, m_utility_ds_layout, "Convert descriptor layout");
|
Vulkan::SetObjectName(dev, m_utility_ds_layout, "Convert descriptor layout");
|
||||||
|
@ -3713,23 +3702,21 @@ bool GSDeviceVK::CreatePipelineLayouts()
|
||||||
if ((m_tfx_ubo_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
if ((m_tfx_ubo_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
Vulkan::SetObjectName(dev, m_tfx_ubo_ds_layout, "TFX UBO descriptor layout");
|
Vulkan::SetObjectName(dev, m_tfx_ubo_ds_layout, "TFX UBO descriptor layout");
|
||||||
dslb.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
||||||
dslb.AddBinding(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
dslb.SetPushFlag();
|
||||||
if ((m_tfx_sampler_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
dslb.AddBinding(TFX_TEXTURE_TEXTURE, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
return false;
|
dslb.AddBinding(TFX_TEXTURE_PALETTE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
Vulkan::SetObjectName(dev, m_tfx_sampler_ds_layout, "TFX sampler descriptor layout");
|
dslb.AddBinding(TFX_TEXTURE_RT,
|
||||||
dslb.AddBinding(0,
|
|
||||||
(m_features.texture_barrier && !UseFeedbackLoopLayout()) ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :
|
(m_features.texture_barrier && !UseFeedbackLoopLayout()) ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :
|
||||||
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
dslb.AddBinding(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
dslb.AddBinding(TFX_TEXTURE_PRIMID, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
if ((m_tfx_rt_texture_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
if ((m_tfx_texture_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
Vulkan::SetObjectName(dev, m_tfx_rt_texture_ds_layout, "TFX RT texture descriptor layout");
|
Vulkan::SetObjectName(dev, m_tfx_texture_ds_layout, "TFX texture descriptor layout");
|
||||||
|
|
||||||
plb.AddDescriptorSet(m_tfx_ubo_ds_layout);
|
plb.AddDescriptorSet(m_tfx_ubo_ds_layout);
|
||||||
plb.AddDescriptorSet(m_tfx_sampler_ds_layout);
|
plb.AddDescriptorSet(m_tfx_texture_ds_layout);
|
||||||
plb.AddDescriptorSet(m_tfx_rt_texture_ds_layout);
|
|
||||||
if ((m_tfx_pipeline_layout = plb.Create(dev)) == VK_NULL_HANDLE)
|
if ((m_tfx_pipeline_layout = plb.Create(dev)) == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
Vulkan::SetObjectName(dev, m_tfx_pipeline_layout, "TFX pipeline layout");
|
Vulkan::SetObjectName(dev, m_tfx_pipeline_layout, "TFX pipeline layout");
|
||||||
|
@ -4264,6 +4251,7 @@ bool GSDeviceVK::CompileCASPipelines()
|
||||||
Vulkan::DescriptorSetLayoutBuilder dslb;
|
Vulkan::DescriptorSetLayoutBuilder dslb;
|
||||||
Vulkan::PipelineLayoutBuilder plb;
|
Vulkan::PipelineLayoutBuilder plb;
|
||||||
|
|
||||||
|
dslb.SetPushFlag();
|
||||||
dslb.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT);
|
dslb.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
dslb.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT);
|
dslb.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
if ((m_cas_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
if ((m_cas_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
|
||||||
|
@ -4459,10 +4447,6 @@ bool GSDeviceVK::DoCAS(GSTexture* sTex, GSTexture* dTex, bool sharpen_only, cons
|
||||||
{
|
{
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
|
|
||||||
VkDescriptorSet ds = AllocateDescriptorSet(m_cas_ds_layout);
|
|
||||||
if (ds == VK_NULL_HANDLE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GSTextureVK* const sTexVK = static_cast<GSTextureVK*>(sTex);
|
GSTextureVK* const sTexVK = static_cast<GSTextureVK*>(sTex);
|
||||||
GSTextureVK* const dTexVK = static_cast<GSTextureVK*>(dTex);
|
GSTextureVK* const dTexVK = static_cast<GSTextureVK*>(dTex);
|
||||||
VkCommandBuffer cmdbuf = GetCurrentCommandBuffer();
|
VkCommandBuffer cmdbuf = GetCurrentCommandBuffer();
|
||||||
|
@ -4472,16 +4456,15 @@ bool GSDeviceVK::DoCAS(GSTexture* sTex, GSTexture* dTex, bool sharpen_only, cons
|
||||||
|
|
||||||
// only happening once a frame, so the update isn't a huge deal.
|
// only happening once a frame, so the update isn't a huge deal.
|
||||||
Vulkan::DescriptorSetUpdateBuilder dsub;
|
Vulkan::DescriptorSetUpdateBuilder dsub;
|
||||||
dsub.AddImageDescriptorWrite(ds, 0, sTexVK->GetView(), sTexVK->GetVkLayout());
|
dsub.AddImageDescriptorWrite(VK_NULL_HANDLE, 0, sTexVK->GetView(), sTexVK->GetVkLayout());
|
||||||
dsub.AddStorageImageDescriptorWrite(ds, 1, dTexVK->GetView(), dTexVK->GetVkLayout());
|
dsub.AddStorageImageDescriptorWrite(VK_NULL_HANDLE, 1, dTexVK->GetView(), dTexVK->GetVkLayout());
|
||||||
dsub.Update(m_device, false);
|
dsub.PushUpdate(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, m_cas_pipeline_layout, 0, false);
|
||||||
|
|
||||||
// the actual meat and potatoes! only four commands.
|
// the actual meat and potatoes! only four commands.
|
||||||
static const int threadGroupWorkRegionDim = 16;
|
static const int threadGroupWorkRegionDim = 16;
|
||||||
const int dispatchX = (dTex->GetWidth() + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
const int dispatchX = (dTex->GetWidth() + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
||||||
const int dispatchY = (dTex->GetHeight() + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
const int dispatchY = (dTex->GetHeight() + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, m_cas_pipeline_layout, 0, 1, &ds, 0, nullptr);
|
|
||||||
vkCmdPushConstants(cmdbuf, m_cas_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, NUM_CAS_CONSTANTS * sizeof(u32), constants.data());
|
vkCmdPushConstants(cmdbuf, m_cas_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, NUM_CAS_CONSTANTS * sizeof(u32), constants.data());
|
||||||
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, m_cas_pipelines[static_cast<u8>(sharpen_only)]);
|
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, m_cas_pipelines[static_cast<u8>(sharpen_only)]);
|
||||||
vkCmdDispatch(cmdbuf, dispatchX, dispatchY, 1);
|
vkCmdDispatch(cmdbuf, dispatchX, dispatchY, 1);
|
||||||
|
@ -4580,10 +4563,8 @@ void GSDeviceVK::DestroyResources()
|
||||||
|
|
||||||
if (m_tfx_pipeline_layout != VK_NULL_HANDLE)
|
if (m_tfx_pipeline_layout != VK_NULL_HANDLE)
|
||||||
vkDestroyPipelineLayout(m_device, m_tfx_pipeline_layout, nullptr);
|
vkDestroyPipelineLayout(m_device, m_tfx_pipeline_layout, nullptr);
|
||||||
if (m_tfx_rt_texture_ds_layout != VK_NULL_HANDLE)
|
if (m_tfx_texture_ds_layout != VK_NULL_HANDLE)
|
||||||
vkDestroyDescriptorSetLayout(m_device, m_tfx_rt_texture_ds_layout, nullptr);
|
vkDestroyDescriptorSetLayout(m_device, m_tfx_texture_ds_layout, nullptr);
|
||||||
if (m_tfx_sampler_ds_layout != VK_NULL_HANDLE)
|
|
||||||
vkDestroyDescriptorSetLayout(m_device, m_tfx_sampler_ds_layout, nullptr);
|
|
||||||
if (m_tfx_ubo_ds_layout != VK_NULL_HANDLE)
|
if (m_tfx_ubo_ds_layout != VK_NULL_HANDLE)
|
||||||
vkDestroyDescriptorSetLayout(m_device, m_tfx_ubo_ds_layout, nullptr);
|
vkDestroyDescriptorSetLayout(m_device, m_tfx_ubo_ds_layout, nullptr);
|
||||||
if (m_utility_pipeline_layout != VK_NULL_HANDLE)
|
if (m_utility_pipeline_layout != VK_NULL_HANDLE)
|
||||||
|
@ -4605,8 +4586,6 @@ void GSDeviceVK::DestroyResources()
|
||||||
|
|
||||||
if (resources.fence != VK_NULL_HANDLE)
|
if (resources.fence != VK_NULL_HANDLE)
|
||||||
vkDestroyFence(m_device, resources.fence, nullptr);
|
vkDestroyFence(m_device, resources.fence, nullptr);
|
||||||
if (resources.descriptor_pool != VK_NULL_HANDLE)
|
|
||||||
vkDestroyDescriptorPool(m_device, resources.descriptor_pool, nullptr);
|
|
||||||
if (resources.command_buffers[0] != VK_NULL_HANDLE)
|
if (resources.command_buffers[0] != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
vkFreeCommandBuffers(m_device, resources.command_pool, static_cast<u32>(resources.command_buffers.size()),
|
vkFreeCommandBuffers(m_device, resources.command_pool, static_cast<u32>(resources.command_buffers.size()),
|
||||||
|
@ -4995,10 +4974,7 @@ void GSDeviceVK::ExecuteCommandBufferForReadback()
|
||||||
|
|
||||||
void GSDeviceVK::InvalidateCachedState()
|
void GSDeviceVK::InvalidateCachedState()
|
||||||
{
|
{
|
||||||
m_dirty_flags |= DIRTY_FLAG_TFX_SAMPLERS_DS | DIRTY_FLAG_TFX_RT_TEXTURE_DS | DIRTY_FLAG_TFX_DYNAMIC_OFFSETS |
|
m_dirty_flags = ALL_DIRTY_STATE;
|
||||||
DIRTY_FLAG_UTILITY_TEXTURE | DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH | DIRTY_FLAG_VERTEX_BUFFER |
|
|
||||||
DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_PIPELINE |
|
|
||||||
DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER;
|
|
||||||
if (m_vertex_buffer != VK_NULL_HANDLE)
|
if (m_vertex_buffer != VK_NULL_HANDLE)
|
||||||
m_dirty_flags |= DIRTY_FLAG_VERTEX_BUFFER;
|
m_dirty_flags |= DIRTY_FLAG_VERTEX_BUFFER;
|
||||||
if (m_index_buffer != VK_NULL_HANDLE)
|
if (m_index_buffer != VK_NULL_HANDLE)
|
||||||
|
@ -5084,8 +5060,7 @@ void GSDeviceVK::PSSetShaderResource(int i, GSTexture* sr, bool check_state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_tfx_textures[i] = vkTex;
|
m_tfx_textures[i] = vkTex;
|
||||||
|
m_dirty_flags |= (DIRTY_FLAG_TFX_TEXTURE_0 << i);
|
||||||
m_dirty_flags |= (i < 2) ? DIRTY_FLAG_TFX_SAMPLERS_DS : DIRTY_FLAG_TFX_RT_TEXTURE_DS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceVK::PSSetSampler(GSHWDrawConfig::SamplerSelector sel)
|
void GSDeviceVK::PSSetSampler(GSHWDrawConfig::SamplerSelector sel)
|
||||||
|
@ -5095,7 +5070,7 @@ void GSDeviceVK::PSSetSampler(GSHWDrawConfig::SamplerSelector sel)
|
||||||
|
|
||||||
m_tfx_sampler_sel = sel.key;
|
m_tfx_sampler_sel = sel.key;
|
||||||
m_tfx_sampler = GetSampler(sel);
|
m_tfx_sampler = GetSampler(sel);
|
||||||
m_dirty_flags |= DIRTY_FLAG_TFX_SAMPLERS_DS;
|
m_dirty_flags |= DIRTY_FLAG_TFX_TEXTURE_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceVK::SetUtilityTexture(GSTexture* tex, VkSampler sampler)
|
void GSDeviceVK::SetUtilityTexture(GSTexture* tex, VkSampler sampler)
|
||||||
|
@ -5133,7 +5108,7 @@ void GSDeviceVK::UnbindTexture(GSTextureVK* tex)
|
||||||
if (m_tfx_textures[i] == tex)
|
if (m_tfx_textures[i] == tex)
|
||||||
{
|
{
|
||||||
m_tfx_textures[i] = m_null_texture.get();
|
m_tfx_textures[i] = m_null_texture.get();
|
||||||
m_dirty_flags |= (i < 2) ? DIRTY_FLAG_TFX_SAMPLERS_DS : DIRTY_FLAG_TFX_RT_TEXTURE_DS;
|
m_dirty_flags |= (DIRTY_FLAG_TFX_TEXTURE_0 << i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_utility_texture == tex)
|
if (m_utility_texture == tex)
|
||||||
|
@ -5272,10 +5247,9 @@ bool GSDeviceVK::ApplyTFXState(bool already_execed)
|
||||||
if (m_current_pipeline_layout == PipelineLayout::TFX && m_dirty_flags == 0)
|
if (m_current_pipeline_layout == PipelineLayout::TFX && m_dirty_flags == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const VkDevice dev = m_device;
|
|
||||||
const VkCommandBuffer cmdbuf = GetCurrentCommandBuffer();
|
const VkCommandBuffer cmdbuf = GetCurrentCommandBuffer();
|
||||||
u32 flags = m_dirty_flags;
|
u32 flags = m_dirty_flags;
|
||||||
m_dirty_flags &= ~(DIRTY_TFX_STATE | DIRTY_CONSTANT_BUFFER_STATE | DIRTY_FLAG_TFX_DYNAMIC_OFFSETS);
|
m_dirty_flags &= ~(DIRTY_TFX_STATE | DIRTY_CONSTANT_BUFFER_STATE | DIRTY_FLAG_TFX_UBO);
|
||||||
|
|
||||||
// do cbuffer first, because it's the most likely to cause an exec
|
// do cbuffer first, because it's the most likely to cause an exec
|
||||||
if (flags & DIRTY_FLAG_VS_CONSTANT_BUFFER)
|
if (flags & DIRTY_FLAG_VS_CONSTANT_BUFFER)
|
||||||
|
@ -5296,7 +5270,7 @@ bool GSDeviceVK::ApplyTFXState(bool already_execed)
|
||||||
std::memcpy(m_vertex_uniform_stream_buffer.GetCurrentHostPointer(), &m_vs_cb_cache, sizeof(m_vs_cb_cache));
|
std::memcpy(m_vertex_uniform_stream_buffer.GetCurrentHostPointer(), &m_vs_cb_cache, sizeof(m_vs_cb_cache));
|
||||||
m_tfx_dynamic_offsets[0] = m_vertex_uniform_stream_buffer.GetCurrentOffset();
|
m_tfx_dynamic_offsets[0] = m_vertex_uniform_stream_buffer.GetCurrentOffset();
|
||||||
m_vertex_uniform_stream_buffer.CommitMemory(sizeof(m_vs_cb_cache));
|
m_vertex_uniform_stream_buffer.CommitMemory(sizeof(m_vs_cb_cache));
|
||||||
flags |= DIRTY_FLAG_TFX_DYNAMIC_OFFSETS;
|
flags |= DIRTY_FLAG_TFX_UBO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DIRTY_FLAG_PS_CONSTANT_BUFFER)
|
if (flags & DIRTY_FLAG_PS_CONSTANT_BUFFER)
|
||||||
|
@ -5317,116 +5291,62 @@ bool GSDeviceVK::ApplyTFXState(bool already_execed)
|
||||||
std::memcpy(m_fragment_uniform_stream_buffer.GetCurrentHostPointer(), &m_ps_cb_cache, sizeof(m_ps_cb_cache));
|
std::memcpy(m_fragment_uniform_stream_buffer.GetCurrentHostPointer(), &m_ps_cb_cache, sizeof(m_ps_cb_cache));
|
||||||
m_tfx_dynamic_offsets[1] = m_fragment_uniform_stream_buffer.GetCurrentOffset();
|
m_tfx_dynamic_offsets[1] = m_fragment_uniform_stream_buffer.GetCurrentOffset();
|
||||||
m_fragment_uniform_stream_buffer.CommitMemory(sizeof(m_ps_cb_cache));
|
m_fragment_uniform_stream_buffer.CommitMemory(sizeof(m_ps_cb_cache));
|
||||||
flags |= DIRTY_FLAG_TFX_DYNAMIC_OFFSETS;
|
flags |= DIRTY_FLAG_TFX_UBO;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vulkan::DescriptorSetUpdateBuilder dsub;
|
Vulkan::DescriptorSetUpdateBuilder dsub;
|
||||||
|
if (m_current_pipeline_layout != PipelineLayout::TFX)
|
||||||
std::array<VkDescriptorSet, NUM_TFX_DESCRIPTOR_SETS> dsets;
|
|
||||||
u32 num_dsets = 0;
|
|
||||||
u32 start_dset = 0;
|
|
||||||
const bool layout_changed = (m_current_pipeline_layout != PipelineLayout::TFX);
|
|
||||||
|
|
||||||
if (!layout_changed && flags & DIRTY_FLAG_TFX_DYNAMIC_OFFSETS)
|
|
||||||
dsets[num_dsets++] = m_tfx_ubo_descriptor_set;
|
|
||||||
|
|
||||||
if ((flags & DIRTY_FLAG_TFX_SAMPLERS_DS) || m_tfx_texture_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
m_tfx_texture_descriptor_set = AllocateDescriptorSet(m_tfx_sampler_ds_layout);
|
|
||||||
if (m_tfx_texture_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
if (already_execed)
|
|
||||||
{
|
|
||||||
Console.Error("Failed to allocate TFX texture descriptors");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecuteCommandBufferAndRestartRenderPass(false, "Ran out of TFX texture descriptors");
|
|
||||||
return ApplyTFXState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
dsub.AddCombinedImageSamplerDescriptorWrite(m_tfx_texture_descriptor_set, 0, m_tfx_textures[0]->GetView(),
|
|
||||||
m_tfx_sampler, m_tfx_textures[0]->GetVkLayout());
|
|
||||||
dsub.AddImageDescriptorWrite(
|
|
||||||
m_tfx_texture_descriptor_set, 1, m_tfx_textures[1]->GetView(), m_tfx_textures[1]->GetVkLayout());
|
|
||||||
dsub.Update(dev);
|
|
||||||
|
|
||||||
if (!layout_changed)
|
|
||||||
{
|
|
||||||
start_dset = (num_dsets == 0) ? TFX_DESCRIPTOR_SET_TEXTURES : start_dset;
|
|
||||||
dsets[num_dsets++] = m_tfx_texture_descriptor_set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & DIRTY_FLAG_TFX_RT_TEXTURE_DS) || m_tfx_rt_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
m_tfx_rt_descriptor_set = AllocateDescriptorSet(m_tfx_rt_texture_ds_layout);
|
|
||||||
if (m_tfx_rt_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
if (already_execed)
|
|
||||||
{
|
|
||||||
Console.Error("Failed to allocate TFX sampler descriptors");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecuteCommandBufferAndRestartRenderPass(false, "Ran out of TFX sampler descriptors");
|
|
||||||
return ApplyTFXState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_features.texture_barrier && !UseFeedbackLoopLayout())
|
|
||||||
{
|
|
||||||
dsub.AddInputAttachmentDescriptorWrite(
|
|
||||||
m_tfx_rt_descriptor_set, 0, m_tfx_textures[NUM_TFX_DRAW_TEXTURES]->GetView(), VK_IMAGE_LAYOUT_GENERAL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dsub.AddImageDescriptorWrite(m_tfx_rt_descriptor_set, 0, m_tfx_textures[NUM_TFX_DRAW_TEXTURES]->GetView(),
|
|
||||||
m_tfx_textures[NUM_TFX_DRAW_TEXTURES]->GetVkLayout());
|
|
||||||
}
|
|
||||||
dsub.AddImageDescriptorWrite(m_tfx_rt_descriptor_set, 1, m_tfx_textures[NUM_TFX_DRAW_TEXTURES + 1]->GetView(),
|
|
||||||
m_tfx_textures[NUM_TFX_DRAW_TEXTURES + 1]->GetVkLayout());
|
|
||||||
dsub.Update(dev);
|
|
||||||
|
|
||||||
if (!layout_changed)
|
|
||||||
{
|
|
||||||
// need to add textures in, can't leave a gap
|
|
||||||
if (start_dset == TFX_DESCRIPTOR_SET_UBO && num_dsets == 1)
|
|
||||||
dsets[num_dsets++] = m_tfx_texture_descriptor_set;
|
|
||||||
else
|
|
||||||
start_dset = (num_dsets == 0) ? TFX_DESCRIPTOR_SET_RT : start_dset;
|
|
||||||
|
|
||||||
dsets[num_dsets++] = m_tfx_rt_descriptor_set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layout_changed)
|
|
||||||
{
|
{
|
||||||
m_current_pipeline_layout = PipelineLayout::TFX;
|
m_current_pipeline_layout = PipelineLayout::TFX;
|
||||||
|
flags |= DIRTY_FLAG_TFX_UBO | DIRTY_FLAG_TFX_TEXTURES;
|
||||||
|
|
||||||
dsets[0] = m_tfx_ubo_descriptor_set;
|
// Clear out the RT binding if feedback loop isn't on, because it'll be in the wrong state and make
|
||||||
dsets[1] = m_tfx_texture_descriptor_set;
|
// the validation layer cranky. Not a big deal since we need to write it anyway.
|
||||||
dsets[2] = m_tfx_rt_descriptor_set;
|
const GSTextureVK::Layout rt_tex_layout = m_tfx_textures[TFX_TEXTURE_RT]->GetLayout();
|
||||||
|
if (rt_tex_layout != GSTextureVK::Layout::FeedbackLoop && rt_tex_layout != GSTextureVK::Layout::ShaderReadOnly)
|
||||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_tfx_pipeline_layout, 0,
|
m_tfx_textures[TFX_TEXTURE_RT] = m_null_texture.get();
|
||||||
NUM_TFX_DESCRIPTOR_SETS, dsets.data(), NUM_TFX_DYNAMIC_OFFSETS, m_tfx_dynamic_offsets.data());
|
|
||||||
}
|
}
|
||||||
else if (num_dsets > 0)
|
|
||||||
|
if (flags & DIRTY_FLAG_TFX_UBO)
|
||||||
{
|
{
|
||||||
u32 dynamic_count;
|
// Still need to bind the UBO descriptor set.
|
||||||
const u32* dynamic_offsets;
|
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_tfx_pipeline_layout, 0, 1,
|
||||||
if (start_dset == TFX_DESCRIPTOR_SET_UBO)
|
&m_tfx_ubo_descriptor_set, NUM_TFX_DYNAMIC_OFFSETS, m_tfx_dynamic_offsets.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DIRTY_FLAG_TFX_TEXTURES)
|
||||||
|
{
|
||||||
|
if (flags & DIRTY_FLAG_TFX_TEXTURE_TEX)
|
||||||
{
|
{
|
||||||
dynamic_count = NUM_TFX_DYNAMIC_OFFSETS;
|
dsub.AddCombinedImageSamplerDescriptorWrite(VK_NULL_HANDLE, TFX_TEXTURE_TEXTURE,
|
||||||
dynamic_offsets = m_tfx_dynamic_offsets.data();
|
m_tfx_textures[TFX_TEXTURE_TEXTURE]->GetView(), m_tfx_sampler,
|
||||||
|
m_tfx_textures[TFX_TEXTURE_TEXTURE]->GetVkLayout());
|
||||||
}
|
}
|
||||||
else
|
if (flags & DIRTY_FLAG_TFX_TEXTURE_PALETTE)
|
||||||
{
|
{
|
||||||
dynamic_count = 0;
|
dsub.AddImageDescriptorWrite(VK_NULL_HANDLE, TFX_TEXTURE_PALETTE,
|
||||||
dynamic_offsets = nullptr;
|
m_tfx_textures[TFX_TEXTURE_PALETTE]->GetView(), m_tfx_textures[TFX_TEXTURE_PALETTE]->GetVkLayout());
|
||||||
|
}
|
||||||
|
if (flags & DIRTY_FLAG_TFX_TEXTURE_RT)
|
||||||
|
{
|
||||||
|
if (m_features.texture_barrier && !UseFeedbackLoopLayout())
|
||||||
|
{
|
||||||
|
dsub.AddInputAttachmentDescriptorWrite(
|
||||||
|
VK_NULL_HANDLE, TFX_TEXTURE_RT, m_tfx_textures[TFX_TEXTURE_RT]->GetView(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dsub.AddImageDescriptorWrite(VK_NULL_HANDLE, TFX_TEXTURE_RT, m_tfx_textures[TFX_TEXTURE_RT]->GetView(),
|
||||||
|
m_tfx_textures[TFX_TEXTURE_RT]->GetVkLayout());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags & DIRTY_FLAG_TFX_TEXTURE_PRIMID)
|
||||||
|
{
|
||||||
|
dsub.AddImageDescriptorWrite(VK_NULL_HANDLE, TFX_TEXTURE_PRIMID,
|
||||||
|
m_tfx_textures[TFX_TEXTURE_PRIMID]->GetView(), m_tfx_textures[TFX_TEXTURE_PRIMID]->GetVkLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_tfx_pipeline_layout, start_dset, num_dsets,
|
dsub.PushUpdate(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_tfx_pipeline_layout, TFX_DESCRIPTOR_SET_TEXTURES);
|
||||||
dsets.data(), dynamic_count, dynamic_offsets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyBaseState(flags, cmdbuf);
|
ApplyBaseState(flags, cmdbuf);
|
||||||
|
@ -5443,37 +5363,16 @@ bool GSDeviceVK::ApplyUtilityState(bool already_execed)
|
||||||
u32 flags = m_dirty_flags;
|
u32 flags = m_dirty_flags;
|
||||||
m_dirty_flags &= ~DIRTY_UTILITY_STATE;
|
m_dirty_flags &= ~DIRTY_UTILITY_STATE;
|
||||||
|
|
||||||
bool rebind = (m_current_pipeline_layout != PipelineLayout::Utility);
|
if (m_current_pipeline_layout != PipelineLayout::Utility || flags & DIRTY_FLAG_UTILITY_TEXTURE)
|
||||||
|
|
||||||
if ((flags & DIRTY_FLAG_UTILITY_TEXTURE) || m_utility_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
{
|
||||||
m_utility_descriptor_set = AllocateDescriptorSet(m_utility_ds_layout);
|
m_current_pipeline_layout = PipelineLayout::Utility;
|
||||||
if (m_utility_descriptor_set == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
if (already_execed)
|
|
||||||
{
|
|
||||||
Console.Error("Failed to allocate utility descriptors");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecuteCommandBufferAndRestartRenderPass(false, "Ran out of utility descriptors");
|
|
||||||
return ApplyUtilityState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vulkan::DescriptorSetUpdateBuilder dsub;
|
Vulkan::DescriptorSetUpdateBuilder dsub;
|
||||||
dsub.AddCombinedImageSamplerDescriptorWrite(m_utility_descriptor_set, 0, m_utility_texture->GetView(),
|
dsub.AddCombinedImageSamplerDescriptorWrite(
|
||||||
m_utility_sampler, m_utility_texture->GetVkLayout());
|
VK_NULL_HANDLE, 0, m_utility_texture->GetView(), m_utility_sampler, m_utility_texture->GetVkLayout());
|
||||||
dsub.Update(dev);
|
dsub.PushUpdate(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_utility_pipeline_layout, 0, false);
|
||||||
rebind = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebind)
|
|
||||||
{
|
|
||||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_utility_pipeline_layout, 0, 1,
|
|
||||||
&m_utility_descriptor_set, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_current_pipeline_layout = PipelineLayout::Utility;
|
|
||||||
|
|
||||||
ApplyBaseState(flags, cmdbuf);
|
ApplyBaseState(flags, cmdbuf);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GS/Renderers/Common/GSDevice.h"
|
#include "GS/Renderers/Common/GSDevice.h"
|
||||||
|
#include "GS/GSVector.h"
|
||||||
#include "GS/Renderers/Vulkan/GSTextureVK.h"
|
#include "GS/Renderers/Vulkan/GSTextureVK.h"
|
||||||
#include "GS/Renderers/Vulkan/VKLoader.h"
|
#include "GS/Renderers/Vulkan/VKLoader.h"
|
||||||
#include "GS/Renderers/Vulkan/VKStreamBuffer.h"
|
#include "GS/Renderers/Vulkan/VKStreamBuffer.h"
|
||||||
#include "GS/GSVector.h"
|
|
||||||
|
|
||||||
#include "common/HashCombine.h"
|
#include "common/HashCombine.h"
|
||||||
#include "common/ReadbackSpinManager.h"
|
#include "common/ReadbackSpinManager.h"
|
||||||
|
@ -108,9 +108,6 @@ public:
|
||||||
__fi VKStreamBuffer& GetTextureUploadBuffer() { return m_texture_stream_buffer; }
|
__fi VKStreamBuffer& GetTextureUploadBuffer() { return m_texture_stream_buffer; }
|
||||||
VkCommandBuffer GetCurrentInitCommandBuffer();
|
VkCommandBuffer GetCurrentInitCommandBuffer();
|
||||||
|
|
||||||
/// Allocates a descriptor set from the pool reserved for the current frame.
|
|
||||||
VkDescriptorSet AllocateDescriptorSet(VkDescriptorSetLayout set_layout);
|
|
||||||
|
|
||||||
/// Allocates a descriptor set from the pool reserved for the current frame.
|
/// Allocates a descriptor set from the pool reserved for the current frame.
|
||||||
VkDescriptorSet AllocatePersistentDescriptorSet(VkDescriptorSetLayout set_layout);
|
VkDescriptorSet AllocatePersistentDescriptorSet(VkDescriptorSetLayout set_layout);
|
||||||
|
|
||||||
|
@ -199,12 +196,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
using ExtensionList = std::vector<const char*>;
|
using ExtensionList = std::vector<const char*>;
|
||||||
static bool SelectInstanceExtensions(
|
static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, bool enable_debug_utils);
|
||||||
ExtensionList* extension_list, const WindowInfo& wi, bool enable_debug_utils);
|
|
||||||
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
|
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
|
||||||
bool SelectDeviceFeatures();
|
bool SelectDeviceFeatures();
|
||||||
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
||||||
void ProcessDeviceExtensions();
|
bool ProcessDeviceExtensions();
|
||||||
|
|
||||||
bool CreateAllocator();
|
bool CreateAllocator();
|
||||||
bool CreateCommandBuffers();
|
bool CreateCommandBuffers();
|
||||||
|
@ -237,7 +233,6 @@ private:
|
||||||
// [0] - Init (upload) command buffer, [1] - draw command buffer
|
// [0] - Init (upload) command buffer, [1] - draw command buffer
|
||||||
VkCommandPool command_pool = VK_NULL_HANDLE;
|
VkCommandPool command_pool = VK_NULL_HANDLE;
|
||||||
std::array<VkCommandBuffer, 2> command_buffers{VK_NULL_HANDLE, VK_NULL_HANDLE};
|
std::array<VkCommandBuffer, 2> command_buffers{VK_NULL_HANDLE, VK_NULL_HANDLE};
|
||||||
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
|
||||||
VkFence fence = VK_NULL_HANDLE;
|
VkFence fence = VK_NULL_HANDLE;
|
||||||
u64 fence_counter = 0;
|
u64 fence_counter = 0;
|
||||||
s32 spin_id = -1;
|
s32 spin_id = -1;
|
||||||
|
@ -388,11 +383,7 @@ public:
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
NUM_TFX_DYNAMIC_OFFSETS = 2,
|
NUM_TFX_DYNAMIC_OFFSETS = 2,
|
||||||
NUM_TFX_DRAW_TEXTURES = 2,
|
NUM_UTILITY_SAMPLERS = 1,
|
||||||
NUM_TFX_RT_TEXTURES = 2,
|
|
||||||
NUM_TFX_TEXTURES = NUM_TFX_DRAW_TEXTURES + NUM_TFX_RT_TEXTURES,
|
|
||||||
NUM_CONVERT_TEXTURES = 1,
|
|
||||||
NUM_CONVERT_SAMPLERS = 1,
|
|
||||||
CONVERT_PUSH_CONSTANTS_SIZE = 96,
|
CONVERT_PUSH_CONSTANTS_SIZE = 96,
|
||||||
|
|
||||||
NUM_CAS_PIPELINES = 2,
|
NUM_CAS_PIPELINES = 2,
|
||||||
|
@ -401,10 +392,18 @@ public:
|
||||||
{
|
{
|
||||||
TFX_DESCRIPTOR_SET_UBO,
|
TFX_DESCRIPTOR_SET_UBO,
|
||||||
TFX_DESCRIPTOR_SET_TEXTURES,
|
TFX_DESCRIPTOR_SET_TEXTURES,
|
||||||
TFX_DESCRIPTOR_SET_RT,
|
|
||||||
|
|
||||||
NUM_TFX_DESCRIPTOR_SETS,
|
NUM_TFX_DESCRIPTOR_SETS,
|
||||||
};
|
};
|
||||||
|
enum TFX_TEXTURES : u32
|
||||||
|
{
|
||||||
|
TFX_TEXTURE_TEXTURE,
|
||||||
|
TFX_TEXTURE_PALETTE,
|
||||||
|
TFX_TEXTURE_RT,
|
||||||
|
TFX_TEXTURE_PRIMID,
|
||||||
|
|
||||||
|
NUM_TFX_TEXTURES
|
||||||
|
};
|
||||||
enum DATE_RENDER_PASS : u32
|
enum DATE_RENDER_PASS : u32
|
||||||
{
|
{
|
||||||
DATE_RENDER_PASS_NONE = 0,
|
DATE_RENDER_PASS_NONE = 0,
|
||||||
|
@ -419,8 +418,7 @@ private:
|
||||||
VkPipelineLayout m_utility_pipeline_layout = VK_NULL_HANDLE;
|
VkPipelineLayout m_utility_pipeline_layout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkDescriptorSetLayout m_tfx_ubo_ds_layout = VK_NULL_HANDLE;
|
VkDescriptorSetLayout m_tfx_ubo_ds_layout = VK_NULL_HANDLE;
|
||||||
VkDescriptorSetLayout m_tfx_sampler_ds_layout = VK_NULL_HANDLE;
|
VkDescriptorSetLayout m_tfx_texture_ds_layout = VK_NULL_HANDLE;
|
||||||
VkDescriptorSetLayout m_tfx_rt_texture_ds_layout = VK_NULL_HANDLE;
|
|
||||||
VkPipelineLayout m_tfx_pipeline_layout = VK_NULL_HANDLE;
|
VkPipelineLayout m_tfx_pipeline_layout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VKStreamBuffer m_vertex_stream_buffer;
|
VKStreamBuffer m_vertex_stream_buffer;
|
||||||
|
@ -449,7 +447,8 @@ private:
|
||||||
VkPipeline m_shadeboost_pipeline = {};
|
VkPipeline m_shadeboost_pipeline = {};
|
||||||
|
|
||||||
std::unordered_map<u32, VkShaderModule> m_tfx_vertex_shaders;
|
std::unordered_map<u32, VkShaderModule> m_tfx_vertex_shaders;
|
||||||
std::unordered_map<GSHWDrawConfig::PSSelector, VkShaderModule, GSHWDrawConfig::PSSelectorHash> m_tfx_fragment_shaders;
|
std::unordered_map<GSHWDrawConfig::PSSelector, VkShaderModule, GSHWDrawConfig::PSSelectorHash>
|
||||||
|
m_tfx_fragment_shaders;
|
||||||
std::unordered_map<PipelineSelector, VkPipeline, PipelineSelectorHash> m_tfx_pipelines;
|
std::unordered_map<PipelineSelector, VkPipeline, PipelineSelectorHash> m_tfx_pipelines;
|
||||||
|
|
||||||
VkRenderPass m_utility_color_render_pass_load = VK_NULL_HANDLE;
|
VkRenderPass m_utility_color_render_pass_load = VK_NULL_HANDLE;
|
||||||
|
@ -473,15 +472,18 @@ private:
|
||||||
|
|
||||||
std::string m_tfx_source;
|
std::string m_tfx_source;
|
||||||
|
|
||||||
GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override;
|
GSTexture* CreateSurface(
|
||||||
|
GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override;
|
||||||
|
|
||||||
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
|
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
|
||||||
const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) final;
|
const GSRegEXTBUF& EXTBUF, u32 c, const bool linear) final;
|
||||||
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
|
void DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||||
|
ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb) final;
|
||||||
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;
|
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;
|
||||||
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;
|
void DoFXAA(GSTexture* sTex, GSTexture* dTex) final;
|
||||||
|
|
||||||
bool DoCAS(GSTexture* sTex, GSTexture* dTex, bool sharpen_only, const std::array<u32, NUM_CAS_CONSTANTS>& constants) final;
|
bool DoCAS(
|
||||||
|
GSTexture* sTex, GSTexture* dTex, bool sharpen_only, const std::array<u32, NUM_CAS_CONSTANTS>& constants) final;
|
||||||
|
|
||||||
VkSampler GetSampler(GSHWDrawConfig::SamplerSelector ss);
|
VkSampler GetSampler(GSHWDrawConfig::SamplerSelector ss);
|
||||||
void ClearSamplerCache() final;
|
void ClearSamplerCache() final;
|
||||||
|
@ -520,7 +522,8 @@ public:
|
||||||
|
|
||||||
__fi static GSDeviceVK* GetInstance() { return static_cast<GSDeviceVK*>(g_gs_device.get()); }
|
__fi static GSDeviceVK* GetInstance() { return static_cast<GSDeviceVK*>(g_gs_device.get()); }
|
||||||
|
|
||||||
static void GetAdaptersAndFullscreenModes(std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes);
|
static void GetAdaptersAndFullscreenModes(
|
||||||
|
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes);
|
||||||
|
|
||||||
/// Returns true if Vulkan is suitable as a default for the devices in the system.
|
/// Returns true if Vulkan is suitable as a default for the devices in the system.
|
||||||
static bool IsSuitableDefaultRenderer();
|
static bool IsSuitableDefaultRenderer();
|
||||||
|
@ -571,7 +574,8 @@ public:
|
||||||
bool green, bool blue, bool alpha) override;
|
bool green, bool blue, bool alpha) override;
|
||||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||||
PresentShader shader, float shaderTime, bool linear) override;
|
PresentShader shader, float shaderTime, bool linear) override;
|
||||||
void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
|
void DrawMultiStretchRects(
|
||||||
|
const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
|
||||||
void DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTextureVK* dTex, ShaderConvert shader);
|
void DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTextureVK* dTex, ShaderConvert shader);
|
||||||
|
|
||||||
void BeginRenderPassForStretchRect(
|
void BeginRenderPassForStretchRect(
|
||||||
|
@ -583,8 +587,10 @@ public:
|
||||||
void BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel, GSTexture* dTex, const GSVector4i& dRect,
|
void BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel, GSTexture* dTex, const GSVector4i& dRect,
|
||||||
u32 dLevel, bool linear);
|
u32 dLevel, bool linear);
|
||||||
|
|
||||||
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
|
void UpdateCLUTTexture(
|
||||||
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) override;
|
GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
|
||||||
|
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM,
|
||||||
|
GSTexture* dTex, u32 DBW, u32 DPSM) override;
|
||||||
|
|
||||||
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox);
|
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox);
|
||||||
GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config);
|
GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config);
|
||||||
|
@ -657,25 +663,34 @@ public:
|
||||||
private:
|
private:
|
||||||
enum DIRTY_FLAG : u32
|
enum DIRTY_FLAG : u32
|
||||||
{
|
{
|
||||||
DIRTY_FLAG_TFX_SAMPLERS_DS = (1 << 0),
|
DIRTY_FLAG_TFX_TEXTURE_0 = (1 << 0), // 0, 1, 2, 3
|
||||||
DIRTY_FLAG_TFX_RT_TEXTURE_DS = (1 << 1),
|
DIRTY_FLAG_TFX_UBO = (1 << 4),
|
||||||
DIRTY_FLAG_TFX_DYNAMIC_OFFSETS = (1 << 2),
|
DIRTY_FLAG_UTILITY_TEXTURE = (1 << 5),
|
||||||
DIRTY_FLAG_UTILITY_TEXTURE = (1 << 3),
|
DIRTY_FLAG_BLEND_CONSTANTS = (1 << 6),
|
||||||
DIRTY_FLAG_BLEND_CONSTANTS = (1 << 4),
|
DIRTY_FLAG_LINE_WIDTH = (1 << 7),
|
||||||
DIRTY_FLAG_LINE_WIDTH = (1 << 5),
|
DIRTY_FLAG_VERTEX_BUFFER = (1 << 8),
|
||||||
DIRTY_FLAG_VERTEX_BUFFER = (1 << 6),
|
DIRTY_FLAG_INDEX_BUFFER = (1 << 9),
|
||||||
DIRTY_FLAG_INDEX_BUFFER = (1 << 7),
|
DIRTY_FLAG_VIEWPORT = (1 << 10),
|
||||||
DIRTY_FLAG_VIEWPORT = (1 << 8),
|
DIRTY_FLAG_SCISSOR = (1 << 11),
|
||||||
DIRTY_FLAG_SCISSOR = (1 << 9),
|
DIRTY_FLAG_PIPELINE = (1 << 12),
|
||||||
DIRTY_FLAG_PIPELINE = (1 << 10),
|
DIRTY_FLAG_VS_CONSTANT_BUFFER = (1 << 13),
|
||||||
DIRTY_FLAG_VS_CONSTANT_BUFFER = (1 << 11),
|
DIRTY_FLAG_PS_CONSTANT_BUFFER = (1 << 14),
|
||||||
DIRTY_FLAG_PS_CONSTANT_BUFFER = (1 << 12),
|
|
||||||
|
DIRTY_FLAG_TFX_TEXTURE_TEX = (DIRTY_FLAG_TFX_TEXTURE_0 << 0),
|
||||||
|
DIRTY_FLAG_TFX_TEXTURE_PALETTE = (DIRTY_FLAG_TFX_TEXTURE_0 << 1),
|
||||||
|
DIRTY_FLAG_TFX_TEXTURE_RT = (DIRTY_FLAG_TFX_TEXTURE_0 << 2),
|
||||||
|
DIRTY_FLAG_TFX_TEXTURE_PRIMID = (DIRTY_FLAG_TFX_TEXTURE_0 << 3),
|
||||||
|
|
||||||
|
DIRTY_FLAG_TFX_TEXTURES = DIRTY_FLAG_TFX_TEXTURE_TEX | DIRTY_FLAG_TFX_TEXTURE_PALETTE |
|
||||||
|
DIRTY_FLAG_TFX_TEXTURE_RT | DIRTY_FLAG_TFX_TEXTURE_PRIMID,
|
||||||
|
|
||||||
DIRTY_BASE_STATE = DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE |
|
DIRTY_BASE_STATE = DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE |
|
||||||
DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH,
|
DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_BLEND_CONSTANTS |
|
||||||
DIRTY_TFX_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_TFX_SAMPLERS_DS | DIRTY_FLAG_TFX_RT_TEXTURE_DS,
|
DIRTY_FLAG_LINE_WIDTH,
|
||||||
|
DIRTY_TFX_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_TFX_TEXTURES,
|
||||||
DIRTY_UTILITY_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_UTILITY_TEXTURE,
|
DIRTY_UTILITY_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_UTILITY_TEXTURE,
|
||||||
DIRTY_CONSTANT_BUFFER_STATE = DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER,
|
DIRTY_CONSTANT_BUFFER_STATE = DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER,
|
||||||
|
ALL_DIRTY_STATE = DIRTY_BASE_STATE | DIRTY_TFX_STATE | DIRTY_UTILITY_STATE | DIRTY_CONSTANT_BUFFER_STATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PipelineLayout
|
enum class PipelineLayout
|
||||||
|
|
|
@ -141,6 +141,11 @@ void Vulkan::DescriptorSetLayoutBuilder::Clear()
|
||||||
m_ci.bindingCount = 0;
|
m_ci.bindingCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Vulkan::DescriptorSetLayoutBuilder::SetPushFlag()
|
||||||
|
{
|
||||||
|
m_ci.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
VkDescriptorSetLayout Vulkan::DescriptorSetLayoutBuilder::Create(VkDevice device)
|
VkDescriptorSetLayout Vulkan::DescriptorSetLayoutBuilder::Create(VkDevice device)
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayout layout;
|
VkDescriptorSetLayout layout;
|
||||||
|
@ -724,6 +729,17 @@ void Vulkan::DescriptorSetUpdateBuilder::Update(VkDevice device, bool clear /*=
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Vulkan::DescriptorSetUpdateBuilder::PushUpdate(
|
||||||
|
VkCommandBuffer cmdbuf, VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 set, bool clear /*= true*/)
|
||||||
|
{
|
||||||
|
pxAssert(m_num_writes > 0);
|
||||||
|
|
||||||
|
vkCmdPushDescriptorSetKHR(cmdbuf, bind_point, layout, set, m_num_writes, m_writes.data());
|
||||||
|
|
||||||
|
if (clear)
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Vulkan::DescriptorSetUpdateBuilder::AddImageDescriptorWrite(VkDescriptorSet set, u32 binding, VkImageView view,
|
void Vulkan::DescriptorSetUpdateBuilder::AddImageDescriptorWrite(VkDescriptorSet set, u32 binding, VkImageView view,
|
||||||
VkImageLayout layout /*= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/)
|
VkImageLayout layout /*= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace Vulkan
|
||||||
DescriptorSetLayoutBuilder();
|
DescriptorSetLayoutBuilder();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
void SetPushFlag();
|
||||||
|
|
||||||
VkDescriptorSetLayout Create(VkDevice device);
|
VkDescriptorSetLayout Create(VkDevice device);
|
||||||
|
|
||||||
|
@ -248,6 +249,8 @@ namespace Vulkan
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
void Update(VkDevice device, bool clear = true);
|
void Update(VkDevice device, bool clear = true);
|
||||||
|
void PushUpdate(VkCommandBuffer cmdbuf, VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 set,
|
||||||
|
bool clear = true);
|
||||||
|
|
||||||
void AddImageDescriptorWrite(VkDescriptorSet set, u32 binding, VkImageView view,
|
void AddImageDescriptorWrite(VkDescriptorSet set, u32 binding, VkImageView view,
|
||||||
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
|
|
@ -243,4 +243,7 @@ VULKAN_DEVICE_ENTRY_POINT(vkReleaseFullScreenExclusiveModeEXT, false)
|
||||||
// VK_EXT_calibrated_timestamps
|
// VK_EXT_calibrated_timestamps
|
||||||
VULKAN_DEVICE_ENTRY_POINT(vkGetCalibratedTimestampsEXT, false)
|
VULKAN_DEVICE_ENTRY_POINT(vkGetCalibratedTimestampsEXT, false)
|
||||||
|
|
||||||
|
// VK_KHR_push_descriptor
|
||||||
|
VULKAN_DEVICE_ENTRY_POINT(vkCmdPushDescriptorSetKHR, false)
|
||||||
|
|
||||||
#endif // VULKAN_DEVICE_ENTRY_POINT
|
#endif // VULKAN_DEVICE_ENTRY_POINT
|
||||||
|
|
|
@ -15,4 +15,4 @@
|
||||||
|
|
||||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||||
/// shaders change, to invalidate the cache.
|
/// shaders change, to invalidate the cache.
|
||||||
static constexpr u32 SHADER_CACHE_VERSION = 29;
|
static constexpr u32 SHADER_CACHE_VERSION = 30;
|
||||||
|
|
Loading…
Reference in New Issue