diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-06-24 16:13:06 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 11:53:27 +0100 |
commit | 1b4281b895f3046ea972256182b18696a25f8316 (patch) | |
tree | 5f6b9c1600a4354f17b29e430a447d08f93ecf25 /drivers/vulkan/rendering_device_vulkan.cpp | |
parent | 42b44f43ee52eb664d3610d0fdae0eff14c00f0a (diff) |
basic 2D engine is more or less working with Vulkan, including editor.
Still a lot to do
Diffstat (limited to 'drivers/vulkan/rendering_device_vulkan.cpp')
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.cpp | 291 |
1 files changed, 231 insertions, 60 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index ed044ceb05..516853a64e 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -24,20 +24,14 @@ void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) { void RenderingDeviceVulkan::_free_dependencies(RID p_id) { //direct dependencies must be freed - List<RID> to_free; + Map<RID, Set<RID> >::Element *E = dependency_map.find(p_id); if (E) { - for (Set<RID>::Element *F = E->get().front(); F; F = F->next()) { - to_free.push_back(F->get()); + while (E->get().size()) { + free(E->get().front()->get()); } - dependency_map.erase(E); - - while (to_free.front()) { - free(to_free.front()->get()); - to_free.pop_front(); - } } //reverse depenencies must be unreferenced @@ -47,9 +41,9 @@ void RenderingDeviceVulkan::_free_dependencies(RID p_id) { for (Set<RID>::Element *F = E->get().front(); F; F = F->next()) { Map<RID, Set<RID> >::Element *G = dependency_map.find(F->get()); - if (G) { - G->get().erase(p_id); - } + ERR_CONTINUE(!G); + ERR_CONTINUE(!G->get().has(p_id)); + G->get().erase(p_id); } reverse_dependency_map.erase(E); @@ -1210,7 +1204,6 @@ Error RenderingDeviceVulkan::_buffer_free(Buffer *p_buffer) { ERR_FAIL_COND_V(p_buffer->size == 0, ERR_INVALID_PARAMETER); vmaDestroyBuffer(allocator, p_buffer->buffer, p_buffer->allocation); - vmaFreeMemory(allocator, p_buffer->allocation); p_buffer->buffer = NULL; p_buffer->allocation = NULL; p_buffer->size = 0; @@ -1455,6 +1448,16 @@ Error RenderingDeviceVulkan::_buffer_update(Buffer *p_buffer, size_t p_offset, c return OK; } +void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) { + + VkMemoryBarrier mem_barrier; + mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + mem_barrier.pNext = NULL; + mem_barrier.srcAccessMask = p_src_access; + mem_barrier.dstAccessMask = p_dst_sccess; + + vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, NULL, 0, NULL); +} /*****************/ /**** TEXTURE ****/ /*****************/ @@ -1753,7 +1756,6 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T if (err) { vmaDestroyImage(allocator, texture.image, texture.allocation); - vmaFreeMemory(allocator, texture.allocation); ERR_FAIL_V(RID()); } @@ -2082,6 +2084,16 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con return OK; } +bool RenderingDeviceVulkan::texture_is_shared(RID p_texture) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!tex, false); + return tex->owner.is_valid(); +} + +bool RenderingDeviceVulkan::texture_is_valid(RID p_texture) { + return texture_owner.owns(p_texture); +} + bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const { ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false); @@ -2487,7 +2499,9 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Poo uint64_t data_size = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); _buffer_update(&buffer, 0, r.ptr(), data_size); + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false); } + return vertex_buffer_owner.make_rid(buffer); } @@ -2498,14 +2512,17 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons VertexDescriptionKey key; key.vertex_formats = p_vertex_formats; - const Map<VertexDescriptionKey, VertexFormatID>::Element *E = vertex_format_cache.find(key); - if (E) { - return E->get(); + + VertexFormatID *idptr = vertex_format_cache.getptr(key); + if (idptr) { + return *idptr; } + //does not exist, create one and cache it VertexDescriptionCache vdcache; vdcache.bindings = memnew_arr(VkVertexInputBindingDescription, p_vertex_formats.size()); vdcache.attributes = memnew_arr(VkVertexInputAttributeDescription, p_vertex_formats.size()); + Set<int> used_locations; for (int i = 0; i < p_vertex_formats.size(); i++) { ERR_CONTINUE(p_vertex_formats[i].format >= DATA_FORMAT_MAX); @@ -2533,9 +2550,10 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons vdcache.create_info.vertexBindingDescriptionCount = p_vertex_formats.size(); vdcache.create_info.pVertexBindingDescriptions = vdcache.bindings; + vdcache.vertex_formats = p_vertex_formats; VertexFormatID id = VertexFormatID(vertex_format_cache.size()) | (VertexFormatID(ID_TYPE_VERTEX_FORMAT) << ID_BASE_SHIFT); - vdcache.E = vertex_format_cache.insert(key, id); + vertex_format_cache[key] = id; vertex_formats[id] = vdcache; return id; } @@ -2547,7 +2565,7 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID()); const VertexDescriptionCache &vd = vertex_formats[p_vertex_format]; - ERR_FAIL_COND_V(vd.E->key().vertex_formats.size() != p_src_buffers.size(), RID()); + ERR_FAIL_COND_V(vd.vertex_formats.size() != p_src_buffers.size(), RID()); for (int i = 0; i < p_src_buffers.size(); i++) { ERR_FAIL_COND_V(!vertex_buffer_owner.owns(p_src_buffers[i]), RID()); @@ -2563,7 +2581,8 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo //validate with buffer { - const VertexDescription &atf = vd.E->key().vertex_formats[i]; + const VertexDescription &atf = vd.vertex_formats[i]; + uint32_t element_size = get_format_vertex_size(atf.format); ERR_FAIL_COND_V(element_size == 0, RID()); //should never happens since this was prevalidated @@ -2641,6 +2660,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff uint64_t data_size = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); _buffer_update(&index_buffer, 0, r.ptr(), data_size); + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false); } return index_buffer_owner.make_rid(index_buffer); } @@ -3314,6 +3334,7 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Po uint64_t data_size = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); _buffer_update(&buffer, 0, r.ptr(), data_size); + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false); } return uniform_buffer_owner.make_rid(buffer); } @@ -3332,6 +3353,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po uint64_t data_size = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); _buffer_update(&buffer, 0, r.ptr(), data_size); + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, false); } return storage_buffer_owner.make_rid(buffer); } @@ -3354,6 +3376,7 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF uint64_t data_size = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); _buffer_update(&texture_buffer.buffer, 0, r.ptr(), data_size); + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, false); } VkBufferViewCreateInfo view_create_info; @@ -3483,6 +3506,9 @@ void RenderingDeviceVulkan::_descriptor_pool_free(const DescriptorPoolKey &p_key vkDestroyDescriptorPool(device, p_pool->pool, NULL); descriptor_pools[p_key].erase(p_pool); memdelete(p_pool); + if (descriptor_pools[p_key].empty()) { + descriptor_pools.erase(p_key); + } } } @@ -3857,16 +3883,29 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) { Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, void *p_data, bool p_sync_with_draw) { _THREAD_SAFE_METHOD_ + VkPipelineStageFlags dst_stage_mask; + VkAccessFlags dst_access; + Buffer *buffer = NULL; if (vertex_buffer_owner.owns(p_buffer)) { + dst_stage_mask = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + dst_access = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; buffer = vertex_buffer_owner.getornull(p_buffer); } else if (index_buffer_owner.owns(p_buffer)) { + dst_stage_mask = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + dst_access = VK_ACCESS_INDEX_READ_BIT; buffer = index_buffer_owner.getornull(p_buffer); } else if (uniform_buffer_owner.owns(p_buffer)) { + dst_stage_mask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dst_access = VK_ACCESS_UNIFORM_READ_BIT; buffer = uniform_buffer_owner.getornull(p_buffer); } else if (texture_buffer_owner.owns(p_buffer)) { + dst_stage_mask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT; buffer = &texture_buffer_owner.getornull(p_buffer)->buffer; } else if (storage_buffer_owner.owns(p_buffer)) { + dst_stage_mask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; buffer = storage_buffer_owner.getornull(p_buffer); } else { ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type."); @@ -3875,7 +3914,14 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER, "Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end."); - return _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_sync_with_draw); + Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_sync_with_draw); + if (err) { + return err; + } + + _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw); + + return err; } /*************************/ @@ -3908,17 +3954,16 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma if (p_vertex_format != INVALID_ID) { //uses vertices, else it does not ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID()); - VertexDescriptionCache &vd = vertex_formats[p_vertex_format]; + const VertexDescriptionCache &vd = vertex_formats[p_vertex_format]; pipeline_vertex_input_state_create_info = vd.create_info; //validate with inputs for (int i = 0; i < shader->vertex_input_locations.size(); i++) { uint32_t location = shader->vertex_input_locations[i]; - const VertexDescriptionKey &k = vd.E->key(); bool found = false; - for (int j = 0; j < k.vertex_formats.size(); j++) { - if (k.vertex_formats[j].location == location) { + for (int j = 0; j < vd.vertex_formats.size(); j++) { + if (vd.vertex_formats[j].location == location) { found = true; } } @@ -4237,6 +4282,11 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma return id; } +bool RenderingDeviceVulkan::render_pipeline_is_valid(RID p_pipeline) { + _THREAD_SAFE_METHOD_ + return pipeline_owner.owns(p_pipeline); +} + /****************/ /**** SCREEN ****/ /****************/ @@ -4244,12 +4294,12 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma int RenderingDeviceVulkan::screen_get_width(int p_screen) const { _THREAD_SAFE_METHOD_ - return context->get_screen_width(p_screen); + return context->window_get_width(p_screen); } int RenderingDeviceVulkan::screen_get_height(int p_screen) const { _THREAD_SAFE_METHOD_ - return context->get_screen_height(p_screen); + return context->window_get_height(p_screen); } RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::screen_get_framebuffer_format() const { @@ -4295,11 +4345,11 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(in VkRenderPassBeginInfo render_pass_begin; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.pNext = NULL; - render_pass_begin.renderPass = context->get_render_pass(); - render_pass_begin.framebuffer = context->get_frame_framebuffer(frame); + render_pass_begin.renderPass = context->window_get_render_pass(p_screen); + render_pass_begin.framebuffer = context->window_get_framebuffer(p_screen); - render_pass_begin.renderArea.extent.width = context->get_screen_width(p_screen); - render_pass_begin.renderArea.extent.height = context->get_screen_height(p_screen); + render_pass_begin.renderArea.extent.width = context->window_get_width(p_screen); + render_pass_begin.renderArea.extent.height = context->window_get_height(p_screen); render_pass_begin.renderArea.offset.x = 0; render_pass_begin.renderArea.offset.y = 0; @@ -4504,6 +4554,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu vkCmdSetScissor(command_buffer, 0, 1, &scissor); + draw_list->viewport = Rect2i(viewport_offset, viewport_size); return ID_TYPE_DRAW_LIST; } @@ -4646,6 +4697,8 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p vkCmdSetScissor(command_buffer, 0, 1, &scissor); r_split_ids[i] = (DrawListID(1) << DrawListID(ID_TYPE_SPLIT_DRAW_LIST)) + i; + + draw_list[i].viewport = Rect2i(viewport_offset, viewport_size); } return OK; @@ -4776,6 +4829,15 @@ void RenderingDeviceVulkan::draw_list_bind_index_array(DrawListID p_list, RID p_ vkCmdBindIndexBuffer(dl->command_buffer, index_array->buffer, index_array->offset, index_array->index_type); } +void RenderingDeviceVulkan::draw_list_set_line_width(DrawListID p_list, float p_width) { + + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!dl); + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); + + vkCmdSetLineWidth(dl->command_buffer, p_width); +} + void RenderingDeviceVulkan::draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size) { DrawList *dl = _get_draw_list_ptr(p_list); ERR_FAIL_COND(!dl); @@ -4873,8 +4935,37 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices } void RenderingDeviceVulkan::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!dl); + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); + + Rect2i rect = p_rect; + rect.position += dl->viewport.position; + + rect = dl->viewport.clip(rect); + + if (rect.get_area() == 0) { + return; + } + VkRect2D scissor; + scissor.offset.x = rect.position.x; + scissor.offset.y = rect.position.y; + scissor.extent.width = rect.size.width; + scissor.extent.height = rect.size.height; + + vkCmdSetScissor(dl->command_buffer, 0, 1, &scissor); } void RenderingDeviceVulkan::draw_list_disable_scissor(DrawListID p_list) { + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!dl); + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); + + VkRect2D scissor; + scissor.offset.x = dl->viewport.position.x; + scissor.offset.y = dl->viewport.position.y; + scissor.extent.width = dl->viewport.size.width; + scissor.extent.height = dl->viewport.size.height; + vkCmdSetScissor(dl->command_buffer, 0, 1, &scissor); } void RenderingDeviceVulkan::draw_list_end() { @@ -4997,6 +5088,7 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) { Buffer b; b.allocation = index_buffer->allocation; b.buffer = index_buffer->buffer; + b.size = index_buffer->size; frames[frame].buffers_to_dispose_of.push_back(b); index_buffer_owner.free(p_id); } else if (index_array_owner.owns(p_id)) { @@ -5050,42 +5142,42 @@ void RenderingDeviceVulkan::finalize_frame() { vkEndCommandBuffer(frames[frame].setup_command_buffer); vkEndCommandBuffer(frames[frame].draw_command_buffer); } + screen_prepared = false; } -void RenderingDeviceVulkan::_free_pending_resources() { +void RenderingDeviceVulkan::_free_pending_resources(int p_frame) { //free in dependency usage order, so nothing weird happens - //pipelines - while (frames[frame].pipelines_to_dispose_of.front()) { - RenderPipeline *pipeline = &frames[frame].pipelines_to_dispose_of.front()->get(); + while (frames[p_frame].pipelines_to_dispose_of.front()) { + RenderPipeline *pipeline = &frames[p_frame].pipelines_to_dispose_of.front()->get(); vkDestroyPipeline(device, pipeline->pipeline, NULL); - frames[frame].pipelines_to_dispose_of.pop_front(); + frames[p_frame].pipelines_to_dispose_of.pop_front(); } //uniform sets - while (frames[frame].uniform_sets_to_dispose_of.front()) { - UniformSet *uniform_set = &frames[frame].uniform_sets_to_dispose_of.front()->get(); + while (frames[p_frame].uniform_sets_to_dispose_of.front()) { + UniformSet *uniform_set = &frames[p_frame].uniform_sets_to_dispose_of.front()->get(); vkFreeDescriptorSets(device, uniform_set->pool->pool, 1, &uniform_set->descriptor_set); _descriptor_pool_free(uniform_set->pool_key, uniform_set->pool); - frames[frame].uniform_sets_to_dispose_of.pop_front(); + frames[p_frame].uniform_sets_to_dispose_of.pop_front(); } //buffer views - while (frames[frame].buffer_views_to_dispose_of.front()) { - VkBufferView buffer_view = frames[frame].buffer_views_to_dispose_of.front()->get(); + while (frames[p_frame].buffer_views_to_dispose_of.front()) { + VkBufferView buffer_view = frames[p_frame].buffer_views_to_dispose_of.front()->get(); vkDestroyBufferView(device, buffer_view, NULL); - frames[frame].buffer_views_to_dispose_of.pop_front(); + frames[p_frame].buffer_views_to_dispose_of.pop_front(); } //shaders - while (frames[frame].shaders_to_dispose_of.front()) { - Shader *shader = &frames[frame].shaders_to_dispose_of.front()->get(); + while (frames[p_frame].shaders_to_dispose_of.front()) { + Shader *shader = &frames[p_frame].shaders_to_dispose_of.front()->get(); //descriptor set layout for each set for (int i = 0; i < shader->sets.size(); i++) { @@ -5100,21 +5192,21 @@ void RenderingDeviceVulkan::_free_pending_resources() { vkDestroyShaderModule(device, shader->pipeline_stages[i].module, NULL); } - frames[frame].shaders_to_dispose_of.pop_front(); + frames[p_frame].shaders_to_dispose_of.pop_front(); } //samplers - while (frames[frame].samplers_to_dispose_of.front()) { - VkSampler sampler = frames[frame].samplers_to_dispose_of.front()->get(); + while (frames[p_frame].samplers_to_dispose_of.front()) { + VkSampler sampler = frames[p_frame].samplers_to_dispose_of.front()->get(); vkDestroySampler(device, sampler, NULL); - frames[frame].samplers_to_dispose_of.pop_front(); + frames[p_frame].samplers_to_dispose_of.pop_front(); } //framebuffers - while (frames[frame].framebuffers_to_dispose_of.front()) { - Framebuffer *framebuffer = &frames[frame].framebuffers_to_dispose_of.front()->get(); + while (frames[p_frame].framebuffers_to_dispose_of.front()) { + Framebuffer *framebuffer = &frames[p_frame].framebuffers_to_dispose_of.front()->get(); for (Map<Framebuffer::VersionKey, Framebuffer::Version>::Element *E = framebuffer->framebuffers.front(); E; E = E->next()) { //first framebuffer, then render pass because it depends on it @@ -5122,12 +5214,12 @@ void RenderingDeviceVulkan::_free_pending_resources() { vkDestroyRenderPass(device, E->get().render_pass, NULL); } - frames[frame].framebuffers_to_dispose_of.pop_front(); + frames[p_frame].framebuffers_to_dispose_of.pop_front(); } //textures - while (frames[frame].textures_to_dispose_of.front()) { - Texture *texture = &frames[frame].textures_to_dispose_of.front()->get(); + while (frames[p_frame].textures_to_dispose_of.front()) { + Texture *texture = &frames[p_frame].textures_to_dispose_of.front()->get(); if (texture->bound) { WARN_PRINT("Deleted a texture while it was bound.."); @@ -5136,19 +5228,25 @@ void RenderingDeviceVulkan::_free_pending_resources() { if (texture->owner.is_null()) { //actually owns the image and the allocation too vmaDestroyImage(allocator, texture->image, texture->allocation); - vmaFreeMemory(allocator, texture->allocation); } - frames[frame].textures_to_dispose_of.pop_front(); + frames[p_frame].textures_to_dispose_of.pop_front(); } //buffers - while (frames[frame].buffers_to_dispose_of.front()) { - _buffer_free(&frames[frame].buffers_to_dispose_of.front()->get()); + while (frames[p_frame].buffers_to_dispose_of.front()) { + + _buffer_free(&frames[p_frame].buffers_to_dispose_of.front()->get()); - frames[frame].buffers_to_dispose_of.pop_front(); + frames[p_frame].buffers_to_dispose_of.pop_front(); } } +void RenderingDeviceVulkan::prepare_screen_for_drawing() { + _THREAD_SAFE_METHOD_ + context->prepare_buffers(); + screen_prepared = true; +} + void RenderingDeviceVulkan::advance_frame() { _THREAD_SAFE_METHOD_ @@ -5157,7 +5255,7 @@ void RenderingDeviceVulkan::advance_frame() { frame = (frame + 1) % frame_count; //erase pending resources - _free_pending_resources(); + _free_pending_resources(frame); //create setup command buffer and set as the setup buffer @@ -5192,7 +5290,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) { context = p_context; device = p_context->get_device(); - frame_count = p_context->get_frame_count(); + frame_count = p_context->get_swapchain_image_count() + 1; //always need one extra to ensure it's unused at any time, without having to use a fence for this. limits = p_context->get_device_limits(); { //initialize allocator @@ -5292,10 +5390,83 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) { draw_list_count = 0; draw_list_split = false; } + +template <class T> +void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) { + List<RID> owned; + p_owner.get_owned_list(&owned); + if (owned.size()) { + WARN_PRINT(itos(owned.size()) + " RIDs of type '" + p_type + "' were leaked."); + for (List<RID>::Element *E = owned.front(); E; E = E->next()) { + free(E->get()); + } + } +} + void RenderingDeviceVulkan::finalize() { + //free all resources + + context->flush(false, false); + + _free_rids(pipeline_owner, "Pipeline"); + _free_rids(uniform_set_owner, "UniformSet"); + _free_rids(texture_buffer_owner, "TextureBuffer"); + _free_rids(storage_buffer_owner, "StorageBuffer"); + _free_rids(uniform_buffer_owner, "UniformBuffer"); + _free_rids(shader_owner, "Shader"); + _free_rids(index_array_owner, "IndexArray"); + _free_rids(index_buffer_owner, "IndexBuffer"); + _free_rids(vertex_array_owner, "VertexArray"); + _free_rids(vertex_buffer_owner, "VertexBuffer"); + _free_rids(framebuffer_owner, "Framebuffer"); + _free_rids(sampler_owner, "Sampler"); + { + //for textures it's a bit more difficult because they may be shared + List<RID> owned; + texture_owner.get_owned_list(&owned); + if (owned.size()) { + WARN_PRINT(itos(owned.size()) + " RIDs of type 'Texture' were leaked."); + //free shared first + for (List<RID>::Element *E = owned.front(); E;) { + + List<RID>::Element *N = E->next(); + if (texture_is_shared(E->get())) { + free(E->get()); + owned.erase(E->get()); + } + E = N; + } + //free non shared second, this will avoid an error trying to free unexisting textures due to dependencies. + for (List<RID>::Element *E = owned.front(); E; E = E->next()) { + free(E->get()); + } + } + } + + //free everything pending + for (int i = 0; i < frame_count; i++) { + int f = (frame + i) % frame_count; + _free_pending_resources(f); + vkDestroyCommandPool(device, frames[i].command_pool, NULL); + } + + for (int i = 0; i < split_draw_list_allocators.size(); i++) { + vkDestroyCommandPool(device, split_draw_list_allocators[i].command_pool, NULL); + } + memdelete_arr(frames); + + for (int i = 0; i < staging_buffer_blocks.size(); i++) { + vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation); + } + + //all these should be clear at this point + ERR_FAIL_COND(descriptor_pools.size()); + ERR_FAIL_COND(dependency_map.size()); + ERR_FAIL_COND(reverse_dependency_map.size()); } RenderingDeviceVulkan::RenderingDeviceVulkan() { + screen_prepared = false; } |