Vulkan: Support using SSBOs instead texel buffers

This commit is contained in:
Connor McLaughlin 2020-06-24 01:40:01 +10:00
parent 08ef8c1e8d
commit 832c7a1192
2 changed files with 55 additions and 16 deletions

View File

@ -199,6 +199,19 @@ void GPU_HW_Vulkan::SetCapabilities()
m_max_resolution_scale = max_texture_scale;
m_supports_dual_source_blend = g_vulkan_context->GetDeviceFeatures().dualSrcBlend;
#ifdef __APPLE__
// Partial texture buffer uploads appear to be broken in macOS/MoltenVK.
m_use_ssbos_for_vram_writes = true;
#else
const u32 max_texel_buffer_elements = g_vulkan_context->GetDeviceLimits().maxTexelBufferElements;
Log_InfoPrintf("Max texel buffer elements: %u", max_texel_buffer_elements);
if (max_texel_buffer_elements < (VRAM_WIDTH * VRAM_HEIGHT))
{
Log_WarningPrintf("Texel buffer elements insufficient, using shader storage buffers instead.");
m_use_ssbos_for_vram_writes = true;
}
#endif
}
void GPU_HW_Vulkan::DestroyResources()
@ -280,7 +293,10 @@ bool GPU_HW_Vulkan::CreatePipelineLayouts()
if (m_single_sampler_descriptor_set_layout == VK_NULL_HANDLE)
return false;
dslbuilder.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (m_use_ssbos_for_vram_writes)
dslbuilder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
else
dslbuilder.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
m_vram_write_descriptor_set_layout = dslbuilder.Create(device);
if (m_vram_write_descriptor_set_layout == VK_NULL_HANDLE)
return false;
@ -508,23 +524,43 @@ bool GPU_HW_Vulkan::CreateUniformBuffer()
bool GPU_HW_Vulkan::CreateTextureBuffer()
{
if (!m_texture_stream_buffer.Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
return false;
if (m_use_ssbos_for_vram_writes)
{
if (!m_texture_stream_buffer.Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
return false;
Vulkan::BufferViewBuilder bvbuilder;
bvbuilder.Set(m_texture_stream_buffer.GetBuffer(), VK_FORMAT_R16_UINT, 0, m_texture_stream_buffer.GetCurrentSize());
m_texture_stream_buffer_view = bvbuilder.Create(g_vulkan_context->GetDevice());
if (m_texture_stream_buffer_view == VK_NULL_HANDLE)
return false;
m_vram_write_descriptor_set = g_vulkan_context->AllocateGlobalDescriptorSet(m_vram_write_descriptor_set_layout);
if (m_vram_write_descriptor_set == VK_NULL_HANDLE)
return false;
m_vram_write_descriptor_set = g_vulkan_context->AllocateGlobalDescriptorSet(m_vram_write_descriptor_set_layout);
if (m_vram_write_descriptor_set == VK_NULL_HANDLE)
return false;
Vulkan::DescriptorSetUpdateBuilder dsubuilder;
dsubuilder.AddBufferDescriptorWrite(m_vram_write_descriptor_set, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
m_texture_stream_buffer.GetBuffer(), 0,
m_texture_stream_buffer.GetCurrentSize());
dsubuilder.Update(g_vulkan_context->GetDevice());
return true;
}
else
{
if (!m_texture_stream_buffer.Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
return false;
Vulkan::BufferViewBuilder bvbuilder;
bvbuilder.Set(m_texture_stream_buffer.GetBuffer(), VK_FORMAT_R16_UINT, 0, m_texture_stream_buffer.GetCurrentSize());
m_texture_stream_buffer_view = bvbuilder.Create(g_vulkan_context->GetDevice());
if (m_texture_stream_buffer_view == VK_NULL_HANDLE)
return false;
m_vram_write_descriptor_set = g_vulkan_context->AllocateGlobalDescriptorSet(m_vram_write_descriptor_set_layout);
if (m_vram_write_descriptor_set == VK_NULL_HANDLE)
return false;
Vulkan::DescriptorSetUpdateBuilder dsubuilder;
dsubuilder.AddBufferViewDescriptorWrite(m_vram_write_descriptor_set, 0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
m_texture_stream_buffer_view);
dsubuilder.Update(g_vulkan_context->GetDevice());
}
Vulkan::DescriptorSetUpdateBuilder dsubuilder;
dsubuilder.AddBufferViewDescriptorWrite(m_vram_write_descriptor_set, 0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
m_texture_stream_buffer_view);
dsubuilder.Update(g_vulkan_context->GetDevice());
return true;
}
@ -747,7 +783,8 @@ bool GPU_HW_Vulkan::CompilePipelines()
// VRAM write
{
VkShaderModule fs = g_vulkan_shader_cache->GetFragmentShader(shadergen.GenerateVRAMWriteFragmentShader(false));
VkShaderModule fs =
g_vulkan_shader_cache->GetFragmentShader(shadergen.GenerateVRAMWriteFragmentShader(m_use_ssbos_for_vram_writes));
if (fs == VK_NULL_HANDLE)
return false;

View File

@ -121,4 +121,6 @@ private:
// [depth_24][interlace_mode]
DimensionalArray<VkPipeline, 3, 2> m_display_pipelines{};
bool m_use_ssbos_for_vram_writes = false;
};