From c3cf9353d34674115caea2d19f137699d2c85234 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Thu, 14 Aug 2025 00:25:01 +0200 Subject: [PATCH] Gpu fixes --- base/sources/backends/direct3d12_gpu.c | 14 +++++------ base/sources/backends/metal_gpu.m | 8 +++--- base/sources/backends/vulkan_gpu.c | 34 +++++++++++++++++++------- base/sources/backends/vulkan_gpu.h | 1 + base/sources/iron.h | 34 +++++--------------------- base/sources/iron_gpu.c | 34 ++++++++++++++++++++++++++ base/sources/iron_gpu.h | 3 +++ base/sources/ts/iron/render_path.ts | 3 +-- 8 files changed, 81 insertions(+), 50 deletions(-) diff --git a/base/sources/backends/direct3d12_gpu.c b/base/sources/backends/direct3d12_gpu.c index 144b2552..3d7739c7 100644 --- a/base/sources/backends/direct3d12_gpu.c +++ b/base/sources/backends/direct3d12_gpu.c @@ -152,10 +152,10 @@ void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) void gpu_destroy() { gpu_wait(); for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { - gpu_texture_destroy(&framebuffers[i]); + gpu_texture_destroy_internal(&framebuffers[i]); } if (framebuffer_depth.width > 0) { - gpu_texture_destroy(&framebuffer_depth); + gpu_texture_destroy_internal(&framebuffer_depth); } if (readback_buffer != NULL) { readback_buffer->lpVtbl->Release(readback_buffer); @@ -448,10 +448,10 @@ void gpu_present_internal() { framebuffer_index = 0; for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { - gpu_texture_destroy(&framebuffers[i]); + gpu_texture_destroy_internal(&framebuffers[i]); } if (framebuffer_depth.width > 0) { - gpu_texture_destroy(&framebuffer_depth); + gpu_texture_destroy_internal(&framebuffer_depth); } window_swapchain->lpVtbl->ResizeBuffers(window_swapchain, GPU_FRAMEBUFFER_COUNT, iron_window_width(), iron_window_height(), DXGI_FORMAT_R8G8B8A8_UNORM, 0); @@ -707,7 +707,7 @@ void gpu_use_linear_sampling(bool b) { device->lpVtbl->CreateSampler(device, &sampler_desc, sampler_handle); } -void gpu_pipeline_destroy(gpu_pipeline_t *pipe) { +void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipe) { if (pipe->impl.pso != NULL) { pipe->impl.pso->lpVtbl->Release(pipe->impl.pso); pipe->impl.pso = NULL; @@ -965,7 +965,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, gpu_execute_and_wait(); //// } -void gpu_texture_destroy(gpu_texture_t *render_target) { +void gpu_texture_destroy_internal(gpu_texture_t *render_target) { if (render_target->impl.image != NULL) { render_target->impl.image->lpVtbl->Release(render_target->impl.image); } @@ -1113,7 +1113,7 @@ void gpu_constant_buffer_unlock(gpu_buffer_t *buffer) { buffer->data = NULL; } -void gpu_buffer_destroy(gpu_buffer_t *buffer) { +void gpu_buffer_destroy_internal(gpu_buffer_t *buffer) { buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer); buffer->impl.buffer = NULL; } diff --git a/base/sources/backends/metal_gpu.m b/base/sources/backends/metal_gpu.m index b13d18b3..7cffe9f4 100644 --- a/base/sources/backends/metal_gpu.m +++ b/base/sources/backends/metal_gpu.m @@ -280,7 +280,7 @@ void gpu_present_internal() { CAMetalLayer *layer = get_metal_layer(); layer.drawableSize = CGSizeMake(iron_window_width(), iron_window_height()); for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { - // gpu_texture_destroy(&framebuffers[i]); + // gpu_texture_destroy_internal(&framebuffers[i]); gpu_render_target_init2(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, i); } resized = false; @@ -418,7 +418,7 @@ void gpu_use_linear_sampling(bool b) { linear_sampling = b; } -void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) { +void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipeline) { id pipe = (__bridge_transfer id)pipeline->impl._pipeline; pipe = nil; pipeline->impl._pipeline = NULL; @@ -572,7 +572,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, bytesPerImage:width * gpu_texture_format_size(format) * height]; } -void gpu_texture_destroy(gpu_texture_t *target) { +void gpu_texture_destroy_internal(gpu_texture_t *target) { id tex = (__bridge_transfer id)target->impl._tex; tex = nil; target->impl._tex = NULL; @@ -632,7 +632,7 @@ void gpu_index_buffer_init(gpu_buffer_t *buffer, int indexCount) { options:options]; } -void gpu_buffer_destroy(gpu_buffer_t *buffer) { +void gpu_buffer_destroy_internal(gpu_buffer_t *buffer) { id buf = (__bridge_transfer id)buffer->impl.metal_buffer; buf = nil; buffer->impl.metal_buffer = NULL; diff --git a/base/sources/backends/vulkan_gpu.c b/base/sources/backends/vulkan_gpu.c index c2a0ae0b..f748b491 100644 --- a/base/sources/backends/vulkan_gpu.c +++ b/base/sources/backends/vulkan_gpu.c @@ -159,10 +159,10 @@ static VkBool32 vk_debug_utils_messenger_callback_ext( const VkDebugUtilsMessengerCallbackDataEXT *pcallback_data, void *puser_data) { if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { - iron_error("Vulkan ERROR: Code %d : %s", pcallback_data->messageIdNumber, pcallback_data->pMessage); + iron_error("Vulkan ERROR: Code %d : %s\n", pcallback_data->messageIdNumber, pcallback_data->pMessage); } else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { - iron_log("Vulkan WARNING: Code %d : %s", pcallback_data->messageIdNumber, pcallback_data->pMessage); + iron_log("Vulkan WARNING: Code %d : %s\n", pcallback_data->messageIdNumber, pcallback_data->pMessage); } return VK_FALSE; } @@ -386,7 +386,7 @@ static void create_descriptors(void) { VkSwapchainKHR cleanup_swapchain() { // for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { - // gpu_texture_destroy(&framebuffers[i]); + // gpu_texture_destroy_internal(&framebuffers[i]); // } VkSwapchainKHR chain = window_swapchain; window_swapchain = VK_NULL_HANDLE; @@ -399,6 +399,7 @@ void gpu_render_target_init2(gpu_texture_t *target, int width, int height, gpu_t target->format = format; target->state = (framebuffer_index >= 0) ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE; target->buffer = NULL; + target->impl.has_storage_bit = false; if (framebuffer_index >= 0) { return; @@ -627,7 +628,7 @@ static void acquire_next_image() { acquire_next_image(); for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { - // gpu_texture_destroy(&framebuffers[i]); + // gpu_texture_destroy_internal(&framebuffers[i]); // gpu_render_target_init2(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, i); framebuffers[i].width = iron_window_width(); framebuffers[i].height = iron_window_height(); @@ -1298,6 +1299,9 @@ void gpu_disable_scissor() { void gpu_set_pipeline(gpu_pipeline_t *pipeline) { current_pipeline = pipeline; vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, current_pipeline->impl.pipeline); + for (int i = 0; i < GPU_MAX_TEXTURES; ++i) { + current_textures[i] = NULL; + } } void gpu_set_vertex_buffer(gpu_buffer_t *buffer) { @@ -1457,7 +1461,7 @@ void gpu_use_linear_sampling(bool b) { linear_sampling = b; } -void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) { +void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipeline) { vkDestroyPipeline(device, pipeline->impl.pipeline, NULL); vkDestroyPipelineLayout(device, pipeline->impl.pipeline_layout, NULL); } @@ -1804,7 +1808,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, gpu_execute_and_wait(); //// } -void gpu_texture_destroy(gpu_texture_t *target) { +void gpu_texture_destroy_internal(gpu_texture_t *target) { if (target->impl.image != NULL) { vkDestroyImage(device, target->impl.image, NULL); vkFreeMemory(device, target->impl.mem, NULL); @@ -1934,7 +1938,7 @@ void gpu_constant_buffer_unlock(gpu_buffer_t *buffer) { buffer->data = NULL; } -void gpu_buffer_destroy(gpu_buffer_t *buffer) { +void gpu_buffer_destroy_internal(gpu_buffer_t *buffer) { vkFreeMemory(device, buffer->impl.mem, NULL); vkDestroyBuffer(device, buffer->impl.buf, NULL); } @@ -3030,8 +3034,9 @@ void gpu_raytrace_set_pipeline(gpu_raytrace_pipeline_t *_pipeline) { } void gpu_raytrace_set_target(gpu_texture_t *_output) { - if (_output != output) { - vkDestroyImage(device, _output->impl.image, NULL); + if (!_output->impl.has_storage_bit) { + _output->impl.has_storage_bit = true; + gpu_texture_destroy(_output); VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, @@ -3049,6 +3054,17 @@ void gpu_raytrace_set_target(gpu_texture_t *_output) { .flags = 0, }; vkCreateImage(device, &image_info, NULL, &_output->impl.image); + + VkMemoryRequirements memory_reqs; + vkGetImageMemoryRequirements(device, _output->impl.image, &memory_reqs); + + VkMemoryAllocateInfo allocation_nfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = NULL, + .allocationSize = memory_reqs.size, + }; + allocation_nfo.memoryTypeIndex = memory_type_from_properties(memory_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vkAllocateMemory(device, &allocation_nfo, NULL, &_output->impl.mem); vkBindImageMemory(device, _output->impl.image, _output->impl.mem, 0); VkImageViewCreateInfo image_view_info = { diff --git a/base/sources/backends/vulkan_gpu.h b/base/sources/backends/vulkan_gpu.h index da0fa186..31649d40 100644 --- a/base/sources/backends/vulkan_gpu.h +++ b/base/sources/backends/vulkan_gpu.h @@ -20,6 +20,7 @@ typedef struct { VkImage image; VkDeviceMemory mem; VkImageView view; + bool has_storage_bit; } gpu_texture_impl_t; typedef struct { diff --git a/base/sources/iron.h b/base/sources/iron.h index c2fd8d8a..bcee9724 100644 --- a/base/sources/iron.h +++ b/base/sources/iron.h @@ -392,12 +392,6 @@ static gpu_raytrace_acceleration_structure_t rt_accel; static bool rt_created = false; static bool rt_accel_created = false; const int rt_constant_buffer_size = 24; -static gpu_texture_t *textures_to_destroy[128]; -static gpu_buffer_t *buffers_to_destroy[128]; -static gpu_pipeline_t *pipelines_to_destroy[32]; -static int textures_to_destroy_count = 0; -static int buffers_to_destroy_count = 0; -static int pipelines_to_destroy_count = 0; void _update(void *data) { #ifdef IRON_WINDOWS @@ -435,22 +429,6 @@ void _update(void *data) { iron_a2_update(); #endif - while (textures_to_destroy_count > 0) { - textures_to_destroy_count--; - gpu_texture_destroy(textures_to_destroy[textures_to_destroy_count]); - free(textures_to_destroy[textures_to_destroy_count]); - } - while (buffers_to_destroy_count > 0) { - buffers_to_destroy_count--; - gpu_buffer_destroy(buffers_to_destroy[buffers_to_destroy_count]); - free(buffers_to_destroy[buffers_to_destroy_count]); - } - while (pipelines_to_destroy_count > 0) { - pipelines_to_destroy_count--; - gpu_pipeline_destroy(pipelines_to_destroy[pipelines_to_destroy_count]); - free(pipelines_to_destroy[pipelines_to_destroy_count]); - } - iron_update(); gpu_present(); } @@ -943,8 +921,8 @@ void iron_set_gamepad_button_callback(void (*callback)(int, int, float)) { #endif void gpu_delete_buffer(gpu_buffer_t *buffer) { - buffers_to_destroy[buffers_to_destroy_count] = buffer; - buffers_to_destroy_count++; + gpu_buffer_destroy(buffer); + free(buffer); } any gpu_create_index_buffer(i32 count) { @@ -1163,8 +1141,8 @@ gpu_pipeline_t *gpu_create_pipeline() { } void gpu_delete_pipeline(gpu_pipeline_t *pipeline) { - pipelines_to_destroy[pipelines_to_destroy_count] = pipeline; - pipelines_to_destroy_count++; + gpu_pipeline_destroy(pipeline); + free(pipeline); } gpu_texture_t *gpu_create_render_target(i32 width, i32 height, i32 format) { @@ -1253,8 +1231,8 @@ gpu_texture_t *iron_load_texture(string_t *file) { } void iron_delete_texture(gpu_texture_t *texture) { - textures_to_destroy[textures_to_destroy_count] = texture; - textures_to_destroy_count++; + gpu_texture_destroy(texture); + free(texture); } #ifdef WITH_AUDIO diff --git a/base/sources/iron_gpu.c b/base/sources/iron_gpu.c index e451a3ef..829da7bb 100644 --- a/base/sources/iron_gpu.c +++ b/base/sources/iron_gpu.c @@ -3,6 +3,12 @@ static gpu_buffer_t constant_buffer; static bool gpu_thrown = false; +static gpu_texture_t textures_to_destroy[128]; +static gpu_buffer_t buffers_to_destroy[128]; +static gpu_pipeline_t pipelines_to_destroy[32]; +static int textures_to_destroy_count = 0; +static int buffers_to_destroy_count = 0; +static int pipelines_to_destroy_count = 0; int constant_buffer_index = 0; int draw_calls = 0; @@ -91,6 +97,19 @@ void gpu_present() { gpu_present_internal(); draw_calls_last = draw_calls; draw_calls = 0; + + while (textures_to_destroy_count > 0) { + textures_to_destroy_count--; + gpu_texture_destroy_internal(&textures_to_destroy[textures_to_destroy_count]); + } + while (buffers_to_destroy_count > 0) { + buffers_to_destroy_count--; + gpu_buffer_destroy_internal(&buffers_to_destroy[buffers_to_destroy_count]); + } + while (pipelines_to_destroy_count > 0) { + pipelines_to_destroy_count--; + gpu_pipeline_destroy_internal(&pipelines_to_destroy[pipelines_to_destroy_count]); + } } void gpu_resize(int width, int height) { @@ -254,6 +273,21 @@ void gpu_create_framebuffers(int depth_buffer_bits) { } } +void gpu_texture_destroy(gpu_texture_t *texture) { + textures_to_destroy[textures_to_destroy_count] = *texture; + textures_to_destroy_count++; +} + +void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) { + pipelines_to_destroy[pipelines_to_destroy_count] = *pipeline; + pipelines_to_destroy_count++; +} + +void gpu_buffer_destroy(gpu_buffer_t *buffer) { + buffers_to_destroy[buffers_to_destroy_count] = *buffer; + buffers_to_destroy_count++; +} + int gpu_vertex_data_size(gpu_vertex_data_t data) { switch (data) { case GPU_VERTEX_DATA_F32_1X: diff --git a/base/sources/iron_gpu.h b/base/sources/iron_gpu.h index 18bea4b9..2fd4d60e 100644 --- a/base/sources/iron_gpu.h +++ b/base/sources/iron_gpu.h @@ -177,6 +177,7 @@ void gpu_set_matrix4(int location, iron_matrix4x4_t value); void gpu_vertex_structure_add(gpu_vertex_structure_t *structure, const char *name, gpu_vertex_data_t data); void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format); void gpu_texture_destroy(gpu_texture_t *texture); +void gpu_texture_destroy_internal(gpu_texture_t *texture); void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format); void gpu_render_target_init2(gpu_texture_t *render_target, int width, int height, gpu_texture_format_t format, int framebuffer_index); void gpu_vertex_buffer_init(gpu_buffer_t *buffer, int count, gpu_vertex_structure_t *structure); @@ -187,11 +188,13 @@ void gpu_constant_buffer_lock(gpu_buffer_t *buffer, int start, int count); void gpu_constant_buffer_unlock(gpu_buffer_t *buffer); void gpu_index_buffer_init(gpu_buffer_t *buffer, int count); void gpu_buffer_destroy(gpu_buffer_t *buffer); +void gpu_buffer_destroy_internal(gpu_buffer_t *buffer); void *gpu_index_buffer_lock(gpu_buffer_t *buffer); void gpu_index_buffer_unlock(gpu_buffer_t *buffer); void gpu_pipeline_init(gpu_pipeline_t *pipeline); void gpu_pipeline_destroy(gpu_pipeline_t *pipeline); +void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipeline); void gpu_pipeline_compile(gpu_pipeline_t *pipeline); void gpu_shader_init(gpu_shader_t *shader, const void *source, size_t length, gpu_shader_type_t type); void gpu_shader_destroy(gpu_shader_t *shader); diff --git a/base/sources/ts/iron/render_path.ts b/base/sources/ts/iron/render_path.ts index 0f65c4c8..c11baa38 100644 --- a/base/sources/ts/iron/render_path.ts +++ b/base/sources/ts/iron/render_path.ts @@ -245,8 +245,7 @@ function render_path_resize() { for (let i: i32 = 0; i < render_targets_keys.length; ++i) { let rt: render_target_t = map_get(render_path_render_targets, render_targets_keys[i]); if (rt != null && rt.width == 0) { - let _image: gpu_texture_t = rt._image; - iron_delete_texture(_image); + iron_delete_texture(rt._image); rt._image = render_path_create_image(rt); } }