diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 129ac29be7..9336a4b183 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -175,6 +175,18 @@ class Framebuffer void init_render_pass(); }; +struct CommonResources +{ + CommonResources(VkDevice device, + const VkPhysicalDeviceMemoryProperties &memory_properties); + ~CommonResources(); + + unique_ptr vbo_offscreen, vbo_final; + VkSampler samplers[2]; + + VkDevice device; +}; + class Pass { public: @@ -228,6 +240,11 @@ class Pass return pass_info.source_filter; } + void set_common_resources(const CommonResources &common) + { + this->common = &common; + } + private: struct UBO { @@ -251,11 +268,10 @@ class Pass VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; VkDescriptorSetLayout set_layout = VK_NULL_HANDLE; VkDescriptorPool pool = VK_NULL_HANDLE; - VkSampler samplers[2] = { VK_NULL_HANDLE, VK_NULL_HANDLE }; vector> ubos; - unique_ptr vbo; vector sets; + const CommonResources *common = nullptr; Size2D current_framebuffer_size; VkViewport current_viewport; @@ -270,7 +286,6 @@ class Pass bool init_pipeline(); bool init_pipeline_layout(); bool init_buffers(); - bool init_samplers(); void image_layout_transition(VkDevice device, VkCommandBuffer cmd, VkImage image, @@ -330,6 +345,7 @@ struct vulkan_filter_chain vector> passes; vector pass_info; vector>> deferred_calls; + CommonResources common; vulkan_filter_chain_texture input_texture; @@ -351,7 +367,8 @@ vulkan_filter_chain::vulkan_filter_chain( const vulkan_filter_chain_create_info &info) : device(info.device), memory_properties(*info.memory_properties), - cache(info.pipeline_cache) + cache(info.pipeline_cache), + common(info.device, *info.memory_properties) { max_input_size = { info.max_input_size.width, info.max_input_size.height }; set_swapchain_info(info.swapchain); @@ -397,6 +414,7 @@ void vulkan_filter_chain::set_num_passes(unsigned num_passes) { passes.emplace_back(new Pass(device, memory_properties, cache, deferred_calls.size(), i + 1 == num_passes)); + passes.back()->set_common_resources(common); } } @@ -660,18 +678,10 @@ void Pass::clear_vk() if (pipeline_layout != VK_NULL_HANDLE) VKFUNC(vkDestroyPipelineLayout)(device, pipeline_layout, nullptr); - for (auto &samp : samplers) - { - if (samp != VK_NULL_HANDLE) - VKFUNC(vkDestroySampler)(device, samp, nullptr); - samp = VK_NULL_HANDLE; - } - pool = VK_NULL_HANDLE; pipeline = VK_NULL_HANDLE; set_layout = VK_NULL_HANDLE; ubos.clear(); - vbo.reset(); } bool Pass::init_pipeline_layout() @@ -869,8 +879,40 @@ bool Pass::init_pipeline() return true; } -bool Pass::init_samplers() +CommonResources::CommonResources(VkDevice device, + const VkPhysicalDeviceMemoryProperties &memory_properties) + : device(device) { + // The final pass uses an MVP designed for [0, 1] range VBO. + // For in-between passes, we just go with identity matrices, so keep it simple. + const float vbo_data_offscreen[] = { + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, +1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, +1.0f, 1.0f, 1.0f, + }; + + const float vbo_data_final[] = { + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, +1.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, +1.0f, 1.0f, 1.0f, + }; + + vbo_offscreen = unique_ptr(new Buffer(device, + memory_properties, sizeof(vbo_data_offscreen), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); + + void *ptr = vbo_offscreen->map(); + memcpy(ptr, vbo_data_offscreen, sizeof(vbo_data_offscreen)); + vbo_offscreen->unmap(); + + vbo_final = unique_ptr(new Buffer(device, + memory_properties, sizeof(vbo_data_final), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); + + ptr = vbo_final->map(); + memcpy(ptr, vbo_data_final, sizeof(vbo_data_final)); + vbo_final->unmap(); + VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; info.magFilter = VK_FILTER_NEAREST; info.minFilter = VK_FILTER_NEAREST; @@ -886,44 +928,29 @@ bool Pass::init_samplers() info.unnormalizedCoordinates = false; info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - if (VKFUNC(vkCreateSampler)(device, - &info, NULL, &samplers[VULKAN_FILTER_CHAIN_NEAREST]) != VK_SUCCESS) - return false; + VKFUNC(vkCreateSampler)(device, + &info, nullptr, &samplers[VULKAN_FILTER_CHAIN_NEAREST]); info.magFilter = VK_FILTER_LINEAR; info.minFilter = VK_FILTER_LINEAR; - if (VKFUNC(vkCreateSampler)(device, - &info, NULL, &samplers[VULKAN_FILTER_CHAIN_LINEAR]) != VK_SUCCESS) - return false; + VKFUNC(vkCreateSampler)(device, + &info, nullptr, &samplers[VULKAN_FILTER_CHAIN_LINEAR]); +} - return true; +CommonResources::~CommonResources() +{ + for (auto &samp : samplers) + if (samp != VK_NULL_HANDLE) + VKFUNC(vkDestroySampler)(device, samp, nullptr); } bool Pass::init_buffers() { - unsigned i; - // The final pass uses an MVP designed for [0, 1] range VBO. - // For in-between passes, we just go with identity matrices, so keep it simple. - float pos_min = final_pass ? 0.0f : -1.0f; - - const float vbo_data[] = { - pos_min, pos_min, 0.0f, 0.0f, - pos_min, +1.0f, 0.0f, 1.0f, - 1.0f, pos_min, 1.0f, 0.0f, - 1.0f, +1.0f, 1.0f, 1.0f, - }; - ubos.clear(); - for (i = 0; i < num_sync_indices; i++) + for (unsigned i = 0; i < num_sync_indices; i++) ubos.emplace_back(new Buffer(device, memory_properties, sizeof(UBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)); - vbo = unique_ptr(new Buffer(device, - memory_properties, sizeof(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); - - void *ptr = vbo->map(); - memcpy(ptr, vbo_data, sizeof(vbo_data)); - vbo->unmap(); return true; } @@ -943,9 +970,6 @@ bool Pass::build() if (!init_buffers()) return false; - if (!init_samplers()) - return false; - return true; } @@ -1001,7 +1025,7 @@ void Pass::set_texture(VkDescriptorSet set, unsigned binding, const Texture &texture) { VkDescriptorImageInfo image_info; - image_info.sampler = samplers[texture.filter]; + image_info.sampler = common->samplers[texture.filter]; image_info.imageView = texture.texture.view; image_info.imageLayout = texture.texture.layout; @@ -1101,7 +1125,9 @@ void Pass::build_commands( 0, 1, &sets[sync_index], 0, nullptr); VkDeviceSize offset = 0; - VKFUNC(vkCmdBindVertexBuffers)(cmd, 0, 1, &vbo->get_buffer(), &offset); + VKFUNC(vkCmdBindVertexBuffers)(cmd, 0, 1, + final_pass ? &common->vbo_final->get_buffer() : &common->vbo_offscreen->get_buffer(), + &offset); if (final_pass) {