You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
basic 2D engine is more or less working with Vulkan, including editor.
Still a lot to do
This commit is contained in:
@@ -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()) {
|
||||
|
||||
frames[frame].buffers_to_dispose_of.pop_front();
|
||||
_buffer_free(&frames[p_frame].buffers_to_dispose_of.front()->get());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user