diff options
| author | Markus Wick <degasus@users.noreply.github.com> | 2017-04-03 10:46:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-03 10:46:13 +0200 |
| commit | 3bd184a255753b0d6a8b645a6035f90a8228e404 (patch) | |
| tree | aa67a05cc10e9be7021b5f831b9fa5fdf68d5d50 /Source/Core/VideoBackends/Vulkan/Util.cpp | |
| parent | ee0e6fa09c085877ef1d0af5399278b0d10efcdb (diff) | |
| parent | 105be9b514d3a5a8eb648e8e4e09ce36a73c57df (diff) | |
Merge pull request #4467 from stenzek/gpu-texture-decoding
VideoBackends: GPU Texture Decoding
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/Util.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/Util.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/Util.cpp b/Source/Core/VideoBackends/Vulkan/Util.cpp index f49ca90580..02ad129972 100644 --- a/Source/Core/VideoBackends/Vulkan/Util.cpp +++ b/Source/Core/VideoBackends/Vulkan/Util.cpp @@ -250,6 +250,18 @@ VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code, bo return CreateShaderModule(code.data(), code.size()); } +VkShaderModule CompileAndCreateComputeShader(const std::string& source_code, bool prepend_header) +{ + ShaderCompiler::SPIRVCodeVector code; + if (!ShaderCompiler::CompileComputeShader(&code, source_code.c_str(), source_code.length(), + prepend_header)) + { + return VK_NULL_HANDLE; + } + + return CreateShaderModule(code.data(), code.size()); +} + } // namespace Util UtilityShaderDraw::UtilityShaderDraw(VkCommandBuffer command_buffer, @@ -670,4 +682,157 @@ bool UtilityShaderDraw::BindPipeline() return true; } +ComputeShaderDispatcher::ComputeShaderDispatcher(VkCommandBuffer command_buffer, + VkPipelineLayout pipeline_layout, + VkShaderModule compute_shader) + : m_command_buffer(command_buffer) +{ + // Populate minimal pipeline state + m_pipeline_info.pipeline_layout = pipeline_layout; + m_pipeline_info.cs = compute_shader; +} + +u8* ComputeShaderDispatcher::AllocateUniformBuffer(size_t size) +{ + if (!g_object_cache->GetUtilityShaderUniformBuffer()->ReserveMemory( + size, g_vulkan_context->GetUniformBufferAlignment(), true, true, true)) + PanicAlert("Failed to allocate util uniforms"); + + return g_object_cache->GetUtilityShaderUniformBuffer()->GetCurrentHostPointer(); +} + +void ComputeShaderDispatcher::CommitUniformBuffer(size_t size) +{ + m_uniform_buffer.buffer = g_object_cache->GetUtilityShaderUniformBuffer()->GetBuffer(); + m_uniform_buffer.offset = 0; + m_uniform_buffer.range = size; + m_uniform_buffer_offset = + static_cast<u32>(g_object_cache->GetUtilityShaderUniformBuffer()->GetCurrentOffset()); + + g_object_cache->GetUtilityShaderUniformBuffer()->CommitMemory(size); +} + +void ComputeShaderDispatcher::SetPushConstants(const void* data, size_t data_size) +{ + _assert_(static_cast<u32>(data_size) < PUSH_CONSTANT_BUFFER_SIZE); + + vkCmdPushConstants(m_command_buffer, m_pipeline_info.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, + 0, static_cast<u32>(data_size), data); +} + +void ComputeShaderDispatcher::SetSampler(size_t index, VkImageView view, VkSampler sampler) +{ + m_samplers[index].sampler = sampler; + m_samplers[index].imageView = view; + m_samplers[index].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +} + +void ComputeShaderDispatcher::SetStorageImage(VkImageView view, VkImageLayout image_layout) +{ + m_storage_image.sampler = VK_NULL_HANDLE; + m_storage_image.imageView = view; + m_storage_image.imageLayout = image_layout; +} + +void ComputeShaderDispatcher::SetTexelBuffer(size_t index, VkBufferView view) +{ + m_texel_buffers[index] = view; +} + +void ComputeShaderDispatcher::Dispatch(u32 groups_x, u32 groups_y, u32 groups_z) +{ + BindDescriptors(); + if (!BindPipeline()) + return; + + vkCmdDispatch(m_command_buffer, groups_x, groups_y, groups_z); +} + +void ComputeShaderDispatcher::BindDescriptors() +{ + VkDescriptorSet set = g_command_buffer_mgr->AllocateDescriptorSet( + g_object_cache->GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT_COMPUTE)); + if (set == VK_NULL_HANDLE) + { + PanicAlert("Failed to allocate descriptor set for compute dispatch"); + return; + } + + // Reserve enough descriptors to write every binding. + std::array<VkWriteDescriptorSet, 7> set_writes = {}; + u32 num_set_writes = 0; + + if (m_uniform_buffer.buffer != VK_NULL_HANDLE) + { + set_writes[num_set_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + nullptr, + set, + 0, + 0, + 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + nullptr, + &m_uniform_buffer, + nullptr}; + } + + // Samplers + for (size_t i = 0; i < m_samplers.size(); i++) + { + const VkDescriptorImageInfo& info = m_samplers[i]; + if (info.imageView != VK_NULL_HANDLE && info.sampler != VK_NULL_HANDLE) + { + set_writes[num_set_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + nullptr, + set, + static_cast<u32>(1 + i), + 0, + 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &info, + nullptr, + nullptr}; + } + } + + for (size_t i = 0; i < m_texel_buffers.size(); i++) + { + if (m_texel_buffers[i] != VK_NULL_HANDLE) + { + set_writes[num_set_writes++] = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, set, 5 + static_cast<u32>(i), 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, nullptr, nullptr, &m_texel_buffers[i]}; + } + } + + if (m_storage_image.imageView != VK_NULL_HANDLE) + { + set_writes[num_set_writes++] = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, set, 7, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_storage_image, nullptr, nullptr}; + } + + if (num_set_writes > 0) + { + vkUpdateDescriptorSets(g_vulkan_context->GetDevice(), num_set_writes, set_writes.data(), 0, + nullptr); + } + + vkCmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_pipeline_info.pipeline_layout, 0, 1, &set, 1, &m_uniform_buffer_offset); +} + +bool ComputeShaderDispatcher::BindPipeline() +{ + VkPipeline pipeline = g_object_cache->GetComputePipeline(m_pipeline_info); + if (pipeline == VK_NULL_HANDLE) + { + PanicAlert("Failed to get pipeline for backend compute dispatch"); + return false; + } + + vkCmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); + return true; +} + } // namespace Vulkan |
