From 920db604d26e2e82b6289807ad8a0607b310eef6 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 6 Sep 2019 22:51:27 -0300 Subject: Rewrote large part of rendering, omni and spot shadows now work. --- drivers/vulkan/rendering_device_vulkan.cpp | 171 +++++++++++++++++++++++++---- drivers/vulkan/rendering_device_vulkan.h | 2 + 2 files changed, 152 insertions(+), 21 deletions(-) (limited to 'drivers/vulkan') diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index a89183d1cc..8cc07c59b1 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1497,6 +1497,23 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas 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); } + +void RenderingDeviceVulkan::_buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) { + + VkBufferMemoryBarrier buffer_mem_barrier; + buffer_mem_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buffer_mem_barrier.pNext = NULL; + buffer_mem_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_mem_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_mem_barrier.srcAccessMask = p_src_access; + buffer_mem_barrier.dstAccessMask = p_dst_sccess; + buffer_mem_barrier.buffer = buffer; + buffer_mem_barrier.offset = p_from; + buffer_mem_barrier.size = p_size; + + vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 0, NULL, 1, &buffer_mem_barrier, 0, NULL); +} + /*****************/ /**** TEXTURE ****/ /*****************/ @@ -1715,7 +1732,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T } if (p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT) { - texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + texture.unbound_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } else { texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } @@ -2526,6 +2543,9 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, ERR_FAIL_COND_V(p_dst_mipmap >= dst_tex->mipmaps, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_dst_layer >= dst_layer_count, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V_MSG(src_tex->read_aspect_mask != dst_tex->read_aspect_mask, ERR_INVALID_PARAMETER, + "Source and destination texture must be of the same type (color or depth)."); + VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer; { @@ -2586,7 +2606,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, image_copy_region.srcOffset.y = p_from.y; image_copy_region.srcOffset.z = p_from.z; - image_copy_region.dstSubresource.aspectMask = src_tex->barrier_aspect_mask; + image_copy_region.dstSubresource.aspectMask = dst_tex->read_aspect_mask; image_copy_region.dstSubresource.baseArrayLayer = p_dst_layer; image_copy_region.dstSubresource.layerCount = 1; image_copy_region.dstSubresource.mipLevel = p_dst_mipmap; @@ -2712,6 +2732,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector::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); + _buffer_memory_barrier(buffer.buffer, 0, data_size, 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); @@ -3223,7 +3246,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff uint64_t data_size = p_data.size(); PoolVector::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); + _buffer_memory_barrier(index_buffer.buffer, 0, data_size, 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); } @@ -3934,7 +3957,7 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Po uint64_t data_size = p_data.size(); PoolVector::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); + _buffer_memory_barrier(buffer.buffer, 0, data_size, 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); } @@ -3953,7 +3976,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po uint64_t data_size = p_data.size(); PoolVector::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); + _buffer_memory_barrier(buffer.buffer, 0, data_size, 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); } @@ -3976,7 +3999,7 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF uint64_t data_size = p_data.size(); PoolVector::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); + _buffer_memory_barrier(texture_buffer.buffer.buffer, 0, data_size, 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; @@ -4400,7 +4423,8 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector &p_uniforms, Buffer *buffer = storage_buffer_owner.getornull(uniform.ids[0]); ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid."); - ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(), + //if 0, then its sized on link time + ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ")."); write.dstArrayElement = 0; @@ -4523,8 +4547,47 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint return err; } - _memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw); - + _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw); +#if 0 + if (p_sync_with_draw) { + VkMemoryBarrier memoryBarrier; + + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = NULL; + memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT | + VK_ACCESS_INDEX_READ_BIT | + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | + VK_ACCESS_UNIFORM_READ_BIT | + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT | + VK_ACCESS_HOST_READ_BIT | + VK_ACCESS_HOST_WRITE_BIT; + memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT | + VK_ACCESS_INDEX_READ_BIT | + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | + VK_ACCESS_UNIFORM_READ_BIT | + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_READ_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT | + VK_ACCESS_HOST_READ_BIT | + VK_ACCESS_HOST_WRITE_BIT; + + vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, NULL, 0, NULL); + } +#endif return err; } @@ -5145,6 +5208,47 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff return OK; } +void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector &p_clear_colors) { + Vector clear_attachments; + int color_index = 0; + for (int i = 0; i < framebuffer->texture_ids.size(); i++) { + Texture *texture = texture_owner.getornull(framebuffer->texture_ids[i]); + VkClearAttachment clear_at; + if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + ERR_FAIL_INDEX(color_index, p_clear_colors.size()); //a bug + Color clear_color = p_clear_colors[color_index]; + clear_at.clearValue.color.float32[0] = clear_color.r; + clear_at.clearValue.color.float32[1] = clear_color.g; + clear_at.clearValue.color.float32[2] = clear_color.b; + clear_at.clearValue.color.float32[3] = clear_color.a; + clear_at.colorAttachment = color_index++; + clear_at.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + + clear_at.clearValue.depthStencil.depth = 1.0; + clear_at.clearValue.depthStencil.stencil = 0; + clear_at.colorAttachment = 0; + clear_at.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (format_has_stencil(texture->format)) { + clear_at.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } else { + ERR_CONTINUE(true); + } + clear_attachments.push_back(clear_at); + } + + VkClearRect cr; + cr.baseArrayLayer = 0; + cr.layerCount = 1; + cr.rect.offset.x = viewport_offset.x; + cr.rect.offset.y = viewport_offset.y; + cr.rect.extent.width = viewport_size.width; + cr.rect.extent.height = viewport_size.height; + + vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr); +} + RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector &p_clear_colors, const Rect2 &p_region) { _THREAD_SAFE_METHOD_ @@ -5154,8 +5258,9 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu Point2i viewport_offset; Point2i viewport_size = framebuffer->size; + bool needs_clear_region = false; - if (p_region != Rect2()) { //check custom region + if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region Rect2i viewport(viewport_offset, viewport_size); Rect2i regioni = p_region; if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) && @@ -5166,6 +5271,11 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu viewport_offset = regioni.position; viewport_size = regioni.size; + + if (p_initial_action == INITIAL_ACTION_CLEAR) { + p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH; + needs_clear_region = true; + } } if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values @@ -5196,6 +5306,10 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu draw_list_count = 0; draw_list_split = false; + if (needs_clear_region) { + _draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, p_clear_colors); + } + VkViewport viewport; viewport.x = viewport_offset.x; viewport.y = viewport_offset.y; @@ -5230,7 +5344,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p Point2i viewport_offset; Point2i viewport_size = framebuffer->size; - if (p_region != Rect2()) { //check custom region + bool needs_clear_region = false; + + if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region Rect2i viewport(viewport_offset, viewport_size); Rect2i regioni = p_region; if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) && @@ -5241,6 +5357,11 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p viewport_offset = regioni.position; viewport_size = regioni.size; + + if (p_initial_action == INITIAL_ACTION_CLEAR) { + p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH; + needs_clear_region = true; + } } if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values @@ -5340,6 +5461,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p #ifdef DEBUG_ENABLED draw_list[i].validation.framebuffer_format = framebuffer->format_id; #endif + if (i == 0 && needs_clear_region) { + _draw_list_insert_clear_region(&draw_list[i], framebuffer, viewport_offset, viewport_size, p_clear_colors); + } VkViewport viewport; viewport.x = viewport_offset.x; @@ -5754,6 +5878,11 @@ void RenderingDeviceVulkan::draw_list_end() { } } draw_list_bound_textures.clear(); + + // To ensure proper synchronization, we must make sure rendering is done before: + // * Some buffer is copied + // * Another render pass happens (since we may be done + _memory_barrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, true); } #if 0 void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_framebuffer, ID *p_draw_lists, uint32_t p_draw_list_count, InitialAction p_initial_action, FinalAction p_final_action, const Vector &p_clear_colors) { diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index d9fb65bb47..c4e5b789bd 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -216,6 +216,7 @@ class RenderingDeviceVulkan : public RenderingDevice { Error _buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer = false, uint32_t p_required_align = 32); void _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); + void _buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw); /*********************/ /**** FRAMEBUFFER ****/ @@ -790,6 +791,7 @@ class RenderingDeviceVulkan : public RenderingDevice { Vector draw_list_bound_textures; bool draw_list_unbind_textures; + void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector &p_clear_colors); Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass); Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector &p_clear_colors, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents); _FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id); -- cgit v1.2.3