diff --git a/base/sources/backends/apple_video.m b/base/sources/backends/apple_video.m index 6f82032e..c80a1eec 100644 --- a/base/sources/backends/apple_video.m +++ b/base/sources/backends/apple_video.m @@ -228,7 +228,7 @@ // CGSize size = CVImageBufferGetDisplaySize(pixelBuffer); // video->impl.myWidth = size.width; // video->impl.myHeight = size.height; -// gpu_texture_init(&video->impl.image, iron_video_width(video), iron_video_height(video), IRON_IMAGE_FORMAT_BGRA32); +// gpu_texture_init(&video->impl.image, iron_video_width(video), iron_video_height(video), GPU_TEXTURE_FORMAT_BGRA32); // video->impl.image_initialized = true; // } diff --git a/base/sources/backends/direct3d12_gpu.c b/base/sources/backends/direct3d12_gpu.c index aafbd8fd..d1b77e78 100644 --- a/base/sources/backends/direct3d12_gpu.c +++ b/base/sources/backends/direct3d12_gpu.c @@ -2,7 +2,6 @@ #define WIN32_LEAN_AND_MEAN #define HEAP_SIZE 1024 #define TEXTURE_COUNT 16 -#define FRAMEBUFFER_COUNT 2 #include #include #include @@ -18,21 +17,14 @@ void iron_memory_emergency(); bool gpu_transpose_mat = false; -bool gpu_in_use = false; -static bool gpu_thrown = false; static ID3D12Device *device = NULL; static ID3D12CommandQueue *queue; static struct IDXGISwapChain *window_swapchain; static ID3D12RootSignature *root_signature = NULL; static struct ID3D12CommandAllocator *command_allocator; static struct ID3D12GraphicsCommandList *command_list; -static bool command_list_open = true; -static gpu_texture_t framebuffers[FRAMEBUFFER_COUNT]; -static int framebuffer_index = 0; static gpu_pipeline_t *current_pipeline; static gpu_texture_t *current_textures[TEXTURE_COUNT]; -static gpu_texture_t *current_render_targets[8]; -static int current_render_targets_count = 0; static bool window_vsync; static int index_count; static struct ID3D12DescriptorHeap *srv_heap; @@ -40,7 +32,7 @@ static int srv_heap_index; static UINT64 fence_value; static ID3D12Fence *fence; static HANDLE fence_event; -static UINT64 frame_fence_values[FRAMEBUFFER_COUNT]; +static UINT64 frame_fence_values[GPU_FRAMEBUFFER_COUNT]; static D3D12_BLEND convert_blend_factor(gpu_blending_factor_t factor) { switch (factor) { @@ -90,19 +82,19 @@ static D3D12_COMPARISON_FUNC convert_compare_mode(gpu_compare_mode_t compare) { } } -static DXGI_FORMAT convert_format(iron_image_format_t format) { +static DXGI_FORMAT convert_format(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return DXGI_FORMAT_R32G32B32A32_FLOAT; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return DXGI_FORMAT_R16G16B16A16_FLOAT; - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_R32: return DXGI_FORMAT_R32_FLOAT; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return DXGI_FORMAT_R16_FLOAT; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return DXGI_FORMAT_R8_UNORM; - case IRON_IMAGE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_RGBA32: default: return DXGI_FORMAT_R8G8B8A8_UNORM; } @@ -123,6 +115,17 @@ static int format_size(DXGI_FORMAT format) { } } +static D3D12_RESOURCE_STATES convert_texture_state(gpu_texture_state_t state) { + switch (state) { + case GPU_TEXTURE_STATE_SHADER_RESOURCE: + return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + case GPU_TEXTURE_STATE_RENDER_TARGET: + return D3D12_RESOURCE_STATE_RENDER_TARGET; + case GPU_TEXTURE_STATE_PRESENT: + return D3D12_RESOURCE_STATE_PRESENT; + } +} + static void wait_for_fence(ID3D12Fence *fence, UINT64 completion_value, HANDLE wait_event) { if (fence->lpVtbl->GetCompletedValue(fence) < completion_value) { fence->lpVtbl->SetEventOnCompletion(fence, completion_value, wait_event); @@ -139,25 +142,25 @@ static UINT64 get_footprint(ID3D12Resource *destinationResource, UINT FirstSubre return requiredSize; } -static void gpu_barrier(gpu_texture_t *render_target, D3D12_RESOURCE_STATES state_after) { - if (render_target->impl.state == state_after) { +void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) { + if (render_target->state == state_after) { return; } D3D12_RESOURCE_BARRIER barrier = { .Transition.pResource = render_target->impl.render_target, .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, - .Transition.StateBefore = render_target->impl.state, - .Transition.StateAfter = state_after, + .Transition.StateBefore = convert_texture_state(render_target->state), + .Transition.StateAfter = convert_texture_state(state_after), .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, }; command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier); - render_target->impl.state = state_after; + render_target->state = state_after; } void gpu_destroy() { gpu_wait(); - for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { + for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { gpu_texture_destroy(&framebuffers[i]); } command_list->lpVtbl->Release(command_list); @@ -171,7 +174,7 @@ void gpu_destroy() { device->lpVtbl->Release(device); } -static void render_target_init(gpu_texture_t *render_target, int width, int height, iron_image_format_t format, int depth_buffer_bits, int framebuffer_index) { +static void render_target_init(gpu_texture_t *render_target, int width, int height, gpu_texture_format_t format, int depth_buffer_bits, int framebuffer_index) { render_target->width = render_target->width = width; render_target->height = render_target->height = height; render_target->impl.stage = 0; @@ -181,7 +184,7 @@ static void render_target_init(gpu_texture_t *render_target, int width, int heig render_target->impl.upload_image = NULL; render_target->data = NULL; render_target->uploaded = true; - render_target->impl.state = (framebuffer_index >= 0) ? D3D12_RESOURCE_STATE_PRESENT : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + render_target->state = (framebuffer_index >= 0) ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE; DXGI_FORMAT dxgi_format = convert_format(format); @@ -429,7 +432,7 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) { HWND hwnd = iron_windows_window_handle(); DXGI_SWAP_CHAIN_DESC swapchain_desc = { - .BufferCount = FRAMEBUFFER_COUNT, + .BufferCount = GPU_FRAMEBUFFER_COUNT, .BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM, .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT, .BufferDesc.Width = iron_window_width(), @@ -448,9 +451,9 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) { fence_event = CreateEvent(NULL, FALSE, FALSE, NULL); device->lpVtbl->CreateFence(device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, &fence); - for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { + for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { frame_fence_values[i] = 0; - render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), IRON_IMAGE_FORMAT_RGBA32, depth_buffer_bits, i); + render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, depth_buffer_bits, i); } for (int i = 0; i < TEXTURE_COUNT; ++i) { @@ -474,48 +477,15 @@ int gpu_max_bound_textures(void) { return TEXTURE_COUNT; } -void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { - if (gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("End before you begin"); - } - gpu_in_use = true; - - if (!command_list_open) { - gpu_wait(); - command_allocator->lpVtbl->Reset(command_allocator); - command_list->lpVtbl->Reset(command_list, command_allocator, NULL); - command_list_open = true; - } - - if (current_render_targets_count > 0 && current_render_targets[0] != &framebuffers[framebuffer_index]) { - for (int i = 0; i < current_render_targets_count; ++i) { - gpu_barrier(current_render_targets[i], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - } - } - - if (targets == NULL) { - current_render_targets[0] = &framebuffers[framebuffer_index]; - current_render_targets_count = 1; - } - else { - for (int i = 0; i < count; ++i) { - current_render_targets[i] = targets[i]; - } - current_render_targets_count = count; - } - - gpu_texture_t *target = current_render_targets[0]; - - for (int i = 0; i < current_render_targets_count; ++i) { - gpu_barrier(current_render_targets[i], D3D12_RESOURCE_STATE_RENDER_TARGET); - } +void gpu_begin_internal(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { D3D12_CPU_DESCRIPTOR_HANDLE target_descriptors[16]; for (int i = 0; i < current_render_targets_count; ++i) { current_render_targets[i]->impl.descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(current_render_targets[i]->impl.descriptor_heap, &target_descriptors[i]); } + gpu_texture_t *target = current_render_targets[0]; + if (target->impl.depth_descriptor_heap != NULL) { D3D12_CPU_DESCRIPTOR_HANDLE heapStart; target->impl.depth_descriptor_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(target->impl.depth_descriptor_heap, &heapStart); @@ -548,16 +518,10 @@ void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned colo } } -void gpu_end() { - if (!gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("Begin before you end"); - } - gpu_in_use = false; - +void gpu_end_internal() { for (int i = 0; i < current_render_targets_count; ++i) { gpu_barrier(current_render_targets[i], - current_render_targets[i] == &framebuffers[framebuffer_index] ? D3D12_RESOURCE_STATE_PRESENT : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + current_render_targets[i] == &framebuffers[framebuffer_index] ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE); } current_render_targets_count = 0; } @@ -568,7 +532,6 @@ void gpu_wait() { void gpu_present() { command_list->lpVtbl->Close(command_list); - command_list_open = false; ID3D12CommandList *command_lists[] = {(ID3D12CommandList *)command_list}; queue->lpVtbl->ExecuteCommandLists(queue, 1, command_lists); @@ -579,8 +542,12 @@ void gpu_present() { queue->lpVtbl->Signal(queue, fence, ++fence_value); frame_fence_values[framebuffer_index] = fence_value; - framebuffer_index = (framebuffer_index + 1) % FRAMEBUFFER_COUNT; + framebuffer_index = (framebuffer_index + 1) % GPU_FRAMEBUFFER_COUNT; wait_for_fence(fence, frame_fence_values[framebuffer_index], fence_event); + + gpu_wait(); + command_allocator->lpVtbl->Reset(command_allocator); + command_list->lpVtbl->Reset(command_list, command_allocator, NULL); } void gpu_internal_resize(int width, int height) { @@ -591,11 +558,11 @@ void gpu_internal_resize(int width, int height) { return; } - for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { + for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { gpu_texture_destroy(&framebuffers[i]); - render_target_init(&framebuffers[i], width, height, IRON_IMAGE_FORMAT_RGBA32, 0, i); + render_target_init(&framebuffers[i], width, height, GPU_TEXTURE_FORMAT_RGBA32, 0, i); } - window_swapchain->lpVtbl->ResizeBuffers(window_swapchain, FRAMEBUFFER_COUNT, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0); + window_swapchain->lpVtbl->ResizeBuffers(window_swapchain, GPU_FRAMEBUFFER_COUNT, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0); } bool gpu_raytrace_supported() { @@ -989,7 +956,7 @@ void gpu_shader_destroy(gpu_shader_t *shader) { free(shader->impl.data); } -void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, iron_image_format_t format) { +void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) { memset(&texture->impl, 0, sizeof(texture->impl)); texture->impl.stage = 0; texture->impl.stage_depth = -1; @@ -999,7 +966,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, texture->uploaded = false; texture->format = format; texture->data = data; - texture->impl.state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; texture->impl.render_target = NULL; DXGI_FORMAT d3d_format = convert_format(format); @@ -1110,7 +1077,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, device->lpVtbl->CreateShaderResourceView(device, texture->impl.image, &srv_desc, handle); } -void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_format_t format) { +void gpu_texture_init(gpu_texture_t *texture, int width, int height, gpu_texture_format_t format) { memset(&texture->impl, 0, sizeof(texture->impl)); texture->impl.stage = 0; texture->impl.stage_depth = -1; @@ -1220,7 +1187,7 @@ void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_ texture->uploaded = true; - texture->impl.state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; texture->format = format; } @@ -1253,7 +1220,7 @@ void gpu_texture_generate_mipmaps(gpu_texture_t *texture, int levels) {} void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int level) {} -void gpu_render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depth_buffer_bits) { +void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depth_buffer_bits) { render_target_init(target, width, height, format, depth_buffer_bits, -1); } diff --git a/base/sources/backends/direct3d12_gpu.h b/base/sources/backends/direct3d12_gpu.h index 1730ae45..2de7f74e 100644 --- a/base/sources/backends/direct3d12_gpu.h +++ b/base/sources/backends/direct3d12_gpu.h @@ -66,7 +66,6 @@ typedef struct { struct ID3D12Resource *depth_texture; struct D3D12Viewport viewport; struct D3D12Rect scissor; - enum D3D12_RESOURCE_STATES state; } gpu_texture_impl_t; typedef struct { diff --git a/base/sources/backends/metal_gpu.m b/base/sources/backends/metal_gpu.m index 189c6fce..eb9b80b2 100644 --- a/base/sources/backends/metal_gpu.m +++ b/base/sources/backends/metal_gpu.m @@ -7,29 +7,23 @@ #import #import -#define FRAMEBUFFER_COUNT 1 +#define GPU_FRAMEBUFFER_COUNT 1 id getMetalLayer(void); id getMetalDevice(void); id getMetalQueue(void); -extern int constant_buffer_index; + bool gpu_transpose_mat = true; -bool gpu_in_use = false; -static bool gpu_thrown = false; static id command_buffer = nil; static id command_encoder = nil; static id argument_encoder = nil; static id argument_buffer = nil; -static int argument_buffer_step; static id drawable; -static bool has_depth = false; -static gpu_texture_t *current_render_targets[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; -static int current_render_targets_count = 0; -static gpu_buffer_t *current_index_buffer; static id linear_sampler; -static gpu_texture_t framebuffers[FRAMEBUFFER_COUNT]; -static int framebuffer_index = 0; +static bool has_depth = false; +static int argument_buffer_step; +static gpu_buffer_t *current_index_buffer; static MTLBlendFactor convert_blending_factor(gpu_blending_factor_t factor) { switch (factor) { @@ -77,37 +71,37 @@ static MTLCullMode convert_cull_mode(gpu_cull_mode_t cull) { } } -static MTLPixelFormat convert_render_target_format(iron_image_format_t format) { +static MTLPixelFormat convert_render_target_format(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return MTLPixelFormatRGBA32Float; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return MTLPixelFormatRGBA16Float; - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_R32: return MTLPixelFormatR32Float; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return MTLPixelFormatR16Float; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return MTLPixelFormatR8Unorm; - case IRON_IMAGE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_RGBA32: default: return MTLPixelFormatBGRA8Unorm; } } -static MTLPixelFormat convert_image_format(iron_image_format_t format) { +static MTLPixelFormat convert_image_format(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_RGBA32: return MTLPixelFormatRGBA8Unorm; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return MTLPixelFormatR8Unorm; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return MTLPixelFormatR16Float; - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_R32: return MTLPixelFormatR32Float; - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return MTLPixelFormatRGBA32Float; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return MTLPixelFormatRGBA16Float; } } @@ -127,31 +121,31 @@ static int format_size(MTLPixelFormat format) { } } -static int format_byte_size(iron_image_format_t format) { +static int format_byte_size(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return 16; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return 8; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return 2; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return 1; - case IRON_IMAGE_FORMAT_RGBA32: - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_R32: default: return 4; } } -static void render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depth_buffer_bits, int framebuffer_index) { +static void render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depth_buffer_bits, int framebuffer_index) { id device = getMetalDevice(); memset(target, 0, sizeof(gpu_texture_t)); target->width = width; target->height = height; target->data = NULL; target->uploaded = true; - target->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET; + target->state = GPU_TEXTURE_STATE_RENDER_TARGET; target->impl._texReadback = NULL; target->impl._depthTex = NULL; @@ -267,30 +261,14 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) { // argument_buffer_step += (align - (argument_buffer_step % align)) % align; argument_buffer = [device newBufferWithLength:(argument_buffer_step * 2048) options:MTLResourceStorageModeShared]; - for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { - render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), IRON_IMAGE_FORMAT_RGBA32, depth_buffer_bits, i); + for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { + render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, depth_buffer_bits, i); } next_drawable(); } -void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { - if (gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("End before you begin"); - } - gpu_in_use = true; - - if (targets == NULL) { - current_render_targets[0] = &framebuffers[framebuffer_index]; - current_render_targets_count = 1; - } - else { - for (int i = 0; i < count; ++i) { - current_render_targets[i] = targets[i]; - } - current_render_targets_count = count; - } +void gpu_begin_internal(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { has_depth = current_render_targets[0]->impl._depthTex != nil; @@ -332,13 +310,7 @@ void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned colo command_encoder = [command_buffer renderCommandEncoderWithDescriptor:desc]; } -void gpu_end() { - if (!gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("Begin before you end"); - } - gpu_in_use = false; - +void gpu_end_internal() { [command_encoder endEncoding]; current_render_targets_count = 0; } @@ -358,6 +330,9 @@ void gpu_present() { next_drawable(); } +void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) { +} + int gpu_max_bound_textures(void) { return 16; } @@ -646,7 +621,7 @@ static void create_texture(gpu_texture_t *texture, int width, int height, int fo texture->impl.has_mipmaps = false; id device = getMetalDevice(); - MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:convert_image_format((iron_image_format_t)format) + MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:convert_image_format((gpu_texture_format_t)format) width:width height:height mipmapped:NO]; @@ -654,7 +629,7 @@ static void create_texture(gpu_texture_t *texture, int width, int height, int fo descriptor.width = width; descriptor.height = height; descriptor.depth = 1; - descriptor.pixelFormat = convert_image_format((iron_image_format_t)format); + descriptor.pixelFormat = convert_image_format((gpu_texture_format_t)format); descriptor.arrayLength = 1; descriptor.mipmapLevelCount = 1; // TODO: Make less textures writable @@ -665,25 +640,25 @@ static void create_texture(gpu_texture_t *texture, int width, int height, int fo texture->impl._tex = (__bridge_retained void *)[device newTextureWithDescriptor:descriptor]; } -void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_format_t format) { +void gpu_texture_init(gpu_texture_t *texture, int width, int height, gpu_texture_format_t format) { texture->width = width; texture->height = height; texture->format = format; - texture->impl.data = malloc(width * height * (format == IRON_IMAGE_FORMAT_R8 ? 1 : 4)); + texture->impl.data = malloc(width * height * (format == GPU_TEXTURE_FORMAT_R8 ? 1 : 4)); create_texture(texture, width, height, format, true); texture->uploaded = true; texture->data = NULL; - texture->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; } -void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, iron_image_format_t format) { +void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) { texture->width = width; texture->height = height; texture->format = format; texture->data = data; texture->uploaded = false; texture->impl.data = NULL; - texture->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; create_texture(texture, width, height, format, true); id tex = (__bridge id)texture->impl._tex; [tex replaceRegion:MTLRegionMake2D(0, 0, texture->width, texture->height) @@ -715,14 +690,14 @@ void gpu_texture_destroy(gpu_texture_t *target) { int gpu_texture_stride(gpu_texture_t *texture) { switch (texture->format) { - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return texture->width; - case IRON_IMAGE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_RGBA32: default: return texture->width * 4; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return texture->width * 8; - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return texture->width * 16; } } @@ -733,7 +708,7 @@ void gpu_texture_generate_mipmaps(gpu_texture_t *texture, int levels) { void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int level) { if (!texture->impl.has_mipmaps) { id device = getMetalDevice(); - MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:convert_image_format((iron_image_format_t)texture->format) + MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:convert_image_format((gpu_texture_format_t)texture->format) width:texture->width height:texture->height mipmapped:YES]; @@ -741,7 +716,7 @@ void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int l descriptor.width = texture->width; descriptor.height = texture->height; descriptor.depth = 1; - descriptor.pixelFormat = convert_image_format((iron_image_format_t)texture->format); + descriptor.pixelFormat = convert_image_format((gpu_texture_format_t)texture->format); descriptor.arrayLength = 1; bool writable = true; if (writable) { @@ -780,11 +755,11 @@ void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int l bytesPerRow:mipmap->width * format_byte_size(mipmap->format)]; } -void gpu_render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depth_buffer_bits) { +void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depth_buffer_bits) { render_target_init(target, width, height, format, depth_buffer_bits, -1); target->width = width; target->height = height; - target->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET; + target->state = GPU_TEXTURE_STATE_RENDER_TARGET; target->uploaded = true; } diff --git a/base/sources/backends/vulkan_gpu.c b/base/sources/backends/vulkan_gpu.c index 28bedc7f..cae4c09b 100644 --- a/base/sources/backends/vulkan_gpu.c +++ b/base/sources/backends/vulkan_gpu.c @@ -15,7 +15,6 @@ #include #include "vulkan_gpu.h" -#define FRAMEBUFFER_COUNT 2 #define MAX_DESCRIPTOR_SETS 1024 typedef struct descriptor_set { @@ -26,18 +25,11 @@ typedef struct descriptor_set { } descriptor_set_t; bool gpu_transpose_mat = true; -bool gpu_in_use = false; -static bool gpu_thrown = false; static gpu_texture_t *current_textures[16] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static gpu_texture_t *current_render_targets[8] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -static int current_render_targets_count = 0; - static VkSemaphore framebuffer_available_semaphore; static VkSemaphore rendering_finished_semaphore; static VkFence fence; @@ -53,8 +45,6 @@ static VkPhysicalDeviceMemoryProperties memory_properties; static VkSampler immutable_sampler; static int index_count; static VkCommandBuffer command_buffer; -static gpu_texture_t framebuffers[FRAMEBUFFER_COUNT]; -static int framebuffer_index = 0; static bool command_buffer_open = true; static VkInstance instance; @@ -80,19 +70,19 @@ void iron_vulkan_get_instance_extensions(const char **extensions, int *index); VkBool32 iron_vulkan_get_physical_device_presentation_support(VkPhysicalDevice physical_device, uint32_t queue_family_index); VkResult iron_vulkan_create_surface(VkInstance instance, VkSurfaceKHR *surface); -static VkFormat convert_image_format(iron_image_format_t format) { +static VkFormat convert_image_format(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return VK_FORMAT_R32G32B32A32_SFLOAT; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return VK_FORMAT_R16G16B16A16_SFLOAT; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return VK_FORMAT_R8_UNORM; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return VK_FORMAT_R16_SFLOAT; - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_R32: return VK_FORMAT_R32_SFLOAT; - case IRON_IMAGE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_RGBA32: // return VK_FORMAT_R8G8B8A8_UNORM; return VK_FORMAT_B8G8R8A8_UNORM; default: @@ -163,6 +153,17 @@ static VkBlendOp convert_blend_operation(gpu_blending_operation_t op) { } } +static VkImageLayout convert_texture_state(gpu_texture_state_t state) { + switch (state) { + case GPU_TEXTURE_STATE_SHADER_RESOURCE: + return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case GPU_TEXTURE_STATE_RENDER_TARGET: + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case GPU_TEXTURE_STATE_PRESENT: + return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + } +} + static VkBool32 vk_debug_utils_messenger_callback_ext( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, @@ -235,18 +236,18 @@ static VkAccessFlags access_mask(VkImageLayout layout) { return 0; } -static void gpu_barrier(gpu_texture_t *render_target, VkImageLayout state_after) { - if (render_target->impl.state == state_after) { +void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) { + if (render_target->state == state_after) { return; } VkImageMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = NULL, - .srcAccessMask = access_mask(render_target->impl.state), - .dstAccessMask = access_mask(state_after), - .oldLayout = render_target->impl.state, - .newLayout = state_after, + .srcAccessMask = access_mask(convert_texture_state(render_target->state)), + .dstAccessMask = access_mask(convert_texture_state(state_after)), + .oldLayout = convert_texture_state(render_target->state), + .newLayout = convert_texture_state(state_after), .image = render_target->impl.image, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -262,10 +263,10 @@ static void gpu_barrier(gpu_texture_t *render_target, VkImageLayout state_after) VkImageMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = NULL, - .srcAccessMask = access_mask(render_target->impl.state), - .dstAccessMask = access_mask(state_after), - .oldLayout = render_target->impl.state == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : render_target->impl.state, - .newLayout = state_after == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : state_after, + .srcAccessMask = access_mask(convert_texture_state(render_target->state)), + .dstAccessMask = access_mask(convert_texture_state(state_after)), + .oldLayout = convert_texture_state(render_target->state) == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : convert_texture_state(render_target->state), + .newLayout = convert_texture_state(state_after) == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : convert_texture_state(state_after), .image = render_target->impl.depthImage, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, @@ -278,7 +279,7 @@ static void gpu_barrier(gpu_texture_t *render_target, VkImageLayout state_after) vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier); } - render_target->impl.state = state_after; + render_target->state = state_after; } static void set_image_layout(VkImage image, VkImageAspectFlags aspect_mask, VkImageLayout old_layout, VkImageLayout new_layout) { @@ -400,7 +401,7 @@ void gpu_internal_resize(int width, int height) { } VkSwapchainKHR cleanup_swapchain() { - // for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { + // for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { // gpu_texture_destroy(&framebuffers[i]); // } VkSwapchainKHR chain = window_swapchain; @@ -408,7 +409,7 @@ VkSwapchainKHR cleanup_swapchain() { return chain; } -static void render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depth_bits, int framebuffer_index) { +static void render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depth_bits, int framebuffer_index) { target->width = width; target->height = height; target->data = NULL; @@ -417,10 +418,9 @@ static void render_target_init(gpu_texture_t *target, int width, int height, iro target->impl.stage = 0; target->impl.stage_depth = -1; target->impl.readback_buffer_created = false; - target->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; - target->depth_state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; + target->depth_state = GPU_TEXTURE_STATE_SHADER_RESOURCE; target->uploaded = true; - target->impl.state = (framebuffer_index >= 0) ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + target->state = (framebuffer_index >= 0) ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE; if (framebuffer_index >= 0) { return; @@ -1075,8 +1075,8 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) { }; vkBeginCommandBuffer(command_buffer, &begin_info); - for (int i = 0; i < FRAMEBUFFER_COUNT; ++i) { - render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), IRON_IMAGE_FORMAT_RGBA32, depth_buffer_bits, i); + for (int i = 0; i < GPU_FRAMEBUFFER_COUNT; ++i) { + render_target_init(&framebuffers[i], iron_window_width(), iron_window_height(), GPU_TEXTURE_FORMAT_RGBA32, depth_buffer_bits, i); } create_swapchain(); @@ -1143,36 +1143,10 @@ static void set_viewport_and_scissor() { vkCmdSetScissor(command_buffer, 0, 1, &scissor); } -void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { - if (gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("End before you begin"); - } - gpu_in_use = true; - - if (current_render_targets_count > 0 && current_render_targets[0] != &framebuffers[framebuffer_index]) { - for (int i = 0; i < current_render_targets_count; ++i) { - gpu_barrier(current_render_targets[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - } - - if (targets == NULL) { - current_render_targets[0] = &framebuffers[framebuffer_index]; - current_render_targets_count = 1; - } - else { - for (int i = 0; i < count; ++i) { - current_render_targets[i] = targets[i]; - } - current_render_targets_count = count; - } +void gpu_begin_internal(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { gpu_texture_t *target = current_render_targets[0]; - for (int i = 0; i < current_render_targets_count; ++i) { - gpu_barrier(current_render_targets[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - VkRect2D render_area = { .offset = {0, 0} }; @@ -1268,18 +1242,12 @@ void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned colo } } -void gpu_end() { - if (!gpu_in_use && !gpu_thrown) { - gpu_thrown = true; - iron_log("Begin before you end"); - } - gpu_in_use = false; - +void gpu_end_internal() { vkCmdEndRendering(command_buffer); for (int i = 0; i < current_render_targets_count; ++i) { gpu_barrier(current_render_targets[i], - current_render_targets[i] == &framebuffers[framebuffer_index] ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + current_render_targets[i] == &framebuffers[framebuffer_index] ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE); } current_render_targets_count = 0; } @@ -1976,7 +1944,7 @@ static void update_stride(gpu_texture_t *texture) { texture->impl.stride = (int)layout.rowPitch; } -void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, iron_image_format_t format) { +void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) { texture->width = width; texture->height = height; texture->uploaded = false; @@ -1984,8 +1952,8 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, texture->data = data; texture->impl.stage = 0; texture->impl.stage_depth = -1; - texture->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; - texture->depth_state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; + texture->depth_state = GPU_TEXTURE_STATE_SHADER_RESOURCE; const VkFormat tex_format = convert_image_format(format); VkFormatProperties props; @@ -2058,7 +2026,7 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, vkCreateImageView(device, &view, NULL, &texture->impl.view); } -void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_format_t format) { +void gpu_texture_init(gpu_texture_t *texture, int width, int height, gpu_texture_format_t format) { texture->width = width; texture->height = height; texture->uploaded = true; @@ -2066,8 +2034,8 @@ void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_ texture->data = NULL; texture->impl.stage = 0; texture->impl.stage_depth = -1; - texture->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; - texture->depth_state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE; + texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE; + texture->depth_state = GPU_TEXTURE_STATE_SHADER_RESOURCE; VkFormat tex_format = convert_image_format(format); VkFormatProperties props; @@ -2185,7 +2153,7 @@ void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int l // texture->uploaded = true; } -void gpu_render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depth_bits) { +void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depth_bits) { render_target_init(target, width, height, format, depth_bits, -1); } diff --git a/base/sources/backends/vulkan_gpu.h b/base/sources/backends/vulkan_gpu.h index 23db18f6..4dd7532b 100644 --- a/base/sources/backends/vulkan_gpu.h +++ b/base/sources/backends/vulkan_gpu.h @@ -39,7 +39,6 @@ typedef struct { bool readback_buffer_created; int stage; int stage_depth; - VkImageLayout state; } gpu_texture_impl_t; typedef struct { diff --git a/base/sources/backends/webgpu_gpu.c b/base/sources/backends/webgpu_gpu.c index b2f82570..d43f74f0 100644 --- a/base/sources/backends/webgpu_gpu.c +++ b/base/sources/backends/webgpu_gpu.c @@ -50,8 +50,38 @@ void gpu_init_internal(int depthBufferBits, bool vsync) { swapChain = wgpuDeviceCreateSwapChain(device, surface, &scDesc); } -void gpu_begin(struct gpu_texture **targets, int count, unsigned flags, unsigned color, float depth) {} -void gpu_end() {} +void gpu_begin_internal(struct gpu_texture **targets, int count, unsigned flags, unsigned color, float depth) { + WGPUCommandEncoderDescriptor ceDesc; + memset(&ceDesc, 0, sizeof(ceDesc)); + encoder = wgpuDeviceCreateCommandEncoder(device, &ceDesc); + + WGPURenderPassColorAttachment attachment; + memset(&attachment, 0, sizeof(attachment)); + attachment.view = wgpuSwapChainGetCurrentTextureView(swapChain);; + attachment.loadOp = WGPULoadOp_Clear; + attachment.storeOp = WGPUStoreOp_Store; + WGPUColor color = {0, 0, 0, 1}; + attachment.clearValue = color; + + WGPURenderPassDescriptor passDesc; + memset(&passDesc, 0, sizeof(passDesc)); + passDesc.colorAttachmentCount = 1; + passDesc.colorAttachments = &attachment; + + pass = wgpuCommandEncoderBeginRenderPass(encoder, &passDesc); +} +void gpu_end_internal() { + wgpuRenderPassEncoderEnd(pass); + + WGPUCommandBufferDescriptor cbDesc; + memset(&cbDesc, 0, sizeof(cbDesc)); + WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, &cbDesc); + wgpuQueueSubmit(queue, 1, &commands); +} + +void gpu_present() { + +} bool gpu_raytrace_supported() { return false; @@ -129,7 +159,7 @@ int gpu_index_buffer_count(gpu_buffer_t *buffer) { return buffer->impl.count; } -void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_format_t format) { +void gpu_texture_init(gpu_texture_t *texture, int width, int height, gpu_texture_format_t format) { // WGPUExtent3D size = {}; // size.width = iron_window_width(); // size.height = iron_window_height(); @@ -155,7 +185,7 @@ void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_ texture->data = NULL; } -void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, iron_image_format_t format) {} +void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) {} void gpu_texture_init_from_encoded_data(gpu_texture_t *texture, void *data, int size, const char *format, bool readable) {} void gpu_texture_init_from_data(gpu_texture_t *texture, void *data, int width, int height, int format, bool readable) {} void gpu_texture_destroy(gpu_texture_t *texture) {} @@ -167,15 +197,15 @@ int gpu_texture_stride(gpu_texture_t *texture) { void gpu_texture_generate_mipmaps(gpu_texture_t *texture, int levels) {} void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int level) {} -void gpu_render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depthBufferBits) { +void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depthBufferBits) { target->width = target->width = width; target->height = target->height = height; - target->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET; + target->state = GPU_TEXTURE_STATE_RENDER_TARGET; target->data = NULL; target->uploaded = true; } -void gpu_render_target_init_framebuffer(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depthBufferBits) {} +void gpu_render_target_init_framebuffer(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depthBufferBits) {} void gpu_render_target_set_depth_from(gpu_texture_t *renderTarget, gpu_texture_t *source) {} void gpu_pipeline_init(gpu_pipeline_t *pipe) { @@ -291,42 +321,11 @@ void gpu_shader_init(gpu_shader_t *shader, const void *source, size_t length, gp } void gpu_shader_destroy(gpu_shader_t *shader) {} -void gpu_init() {} void gpu_destroy() {} -void gpu_begin() { - WGPUCommandEncoderDescriptor ceDesc; - memset(&ceDesc, 0, sizeof(ceDesc)); - encoder = wgpuDeviceCreateCommandEncoder(device, &ceDesc); - - WGPURenderPassColorAttachment attachment; - memset(&attachment, 0, sizeof(attachment)); - attachment.view = wgpuSwapChainGetCurrentTextureView(swapChain);; - attachment.loadOp = WGPULoadOp_Clear; - attachment.storeOp = WGPUStoreOp_Store; - WGPUColor color = {0, 0, 0, 1}; - attachment.clearValue = color; - - WGPURenderPassDescriptor passDesc; - memset(&passDesc, 0, sizeof(passDesc)); - passDesc.colorAttachmentCount = 1; - passDesc.colorAttachments = &attachment; - - pass = wgpuCommandEncoderBeginRenderPass(encoder, &passDesc); -} - -void gpu_end() { - wgpuRenderPassEncoderEnd(pass); - - WGPUCommandBufferDescriptor cbDesc; - memset(&cbDesc, 0, sizeof(cbDesc)); - WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, &cbDesc); - wgpuQueueSubmit(queue, 1, &commands); -} - void gpu_barrier(gpu_texture_t *renderTarget, int state_after) {} -void gpu_draw() { +void gpu_draw_internal() { wgpuRenderPassEncoderDrawIndexed(pass, indexCount, 1, 0, 0, 0); } diff --git a/base/sources/iron.h b/base/sources/iron.h index 399a9d61..90915521 100644 --- a/base/sources/iron.h +++ b/base/sources/iron.h @@ -1090,8 +1090,8 @@ void gpu_delete_pipeline(gpu_pipeline_t *pipeline) { free(pipeline); } -bool _load_image(iron_file_reader_t *reader, const char *filename, unsigned char **output, int *width, int *height, iron_image_format_t *format) { - *format = IRON_IMAGE_FORMAT_RGBA32; +bool _load_image(iron_file_reader_t *reader, const char *filename, unsigned char **output, int *width, int *height, gpu_texture_format_t *format) { + *format = GPU_TEXTURE_FORMAT_RGBA32; int size = (int)iron_file_reader_size(reader); bool success = true; unsigned char *data = (unsigned char *)malloc(size); @@ -1117,7 +1117,7 @@ bool _load_image(iron_file_reader_t *reader, const char *filename, unsigned char int output_size = *width * *height * 16; *output = (unsigned char *)malloc(output_size); LZ4_decompress_safe((char *)(data + 12), (char *)*output, compressed_size, output_size); - *format = IRON_IMAGE_FORMAT_RGBA128; + *format = GPU_TEXTURE_FORMAT_RGBA128; #ifdef IRON_IOS // No RGBA128 filtering, convert to RGBA64 uint32_t *_output32 = (uint32_t *)*output; @@ -1127,7 +1127,7 @@ bool _load_image(iron_file_reader_t *reader, const char *filename, unsigned char uint32_t x = *((uint32_t *)&_output32[i]); _output16[i] = ((x >> 16) & 0x8000) | ((((x & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | ((x >> 13) & 0x03ff); } - *format = IRON_IMAGE_FORMAT_RGBA64; + *format = GPU_TEXTURE_FORMAT_RGBA64; free(*output); *output = _output; #endif @@ -1143,7 +1143,7 @@ bool _load_image(iron_file_reader_t *reader, const char *filename, unsigned char iron_error(stbi_failure_reason()); success = false; } - *format = IRON_IMAGE_FORMAT_RGBA128; + *format = GPU_TEXTURE_FORMAT_RGBA128; } else { // jpg, png, .. int comp; @@ -1176,7 +1176,7 @@ gpu_texture_t *iron_load_image(string_t *file, bool readable) { unsigned char *image_data; int image_width; int image_height; - iron_image_format_t image_format; + gpu_texture_format_t image_format; if (!_load_image(&reader, file, &image_data, &image_width, &image_height, &image_format)) { return NULL; } @@ -1266,7 +1266,7 @@ bool iron_display_is_primary(i32 index) { gpu_texture_t *gpu_create_render_target(i32 width, i32 height, i32 format, i32 depth_buffer_bits) { gpu_texture_t *render_target = (gpu_texture_t *)malloc(sizeof(gpu_texture_t)); - gpu_render_target_init(render_target, width, height, (iron_image_format_t)format, depth_buffer_bits); + gpu_render_target_init(render_target, width, height, (gpu_texture_format_t)format, depth_buffer_bits); render_target->buffer = NULL; return render_target; } @@ -1282,7 +1282,7 @@ gpu_texture_t *gpu_create_texture_from_bytes(buffer_t *data, i32 width, i32 heig else { image_data = data->buffer; } - gpu_texture_init_from_bytes(texture, image_data, width, height, (iron_image_format_t)format); + gpu_texture_init_from_bytes(texture, image_data, width, height, (gpu_texture_format_t)format); return texture; } @@ -1293,7 +1293,7 @@ gpu_texture_t *gpu_create_texture_from_encoded_bytes(buffer_t *data, string_t *f unsigned char *content_data = (unsigned char *)data->buffer; int content_length = (int)data->length; unsigned char *image_data; - iron_image_format_t image_format; + gpu_texture_format_t image_format; int image_width; int image_height; @@ -1311,24 +1311,24 @@ gpu_texture_t *gpu_create_texture_from_encoded_bytes(buffer_t *data, string_t *f int output_size = image_width * image_height * 4; image_data = (unsigned char *)malloc(output_size); LZ4_decompress_safe((char *)content_data + 12, (char *)image_data, compressed_size, output_size); - image_format = IRON_IMAGE_FORMAT_RGBA32; + image_format = GPU_TEXTURE_FORMAT_RGBA32; } else if (strcmp(fourcc, "LZ4F") == 0) { int output_size = image_width * image_height * 16; image_data = (unsigned char *)malloc(output_size); LZ4_decompress_safe((char *)content_data + 12, (char *)image_data, compressed_size, output_size); - image_format = IRON_IMAGE_FORMAT_RGBA128; + image_format = GPU_TEXTURE_FORMAT_RGBA128; } } else if (ends_with(format, "hdr")) { int comp; image_data = (unsigned char *)stbi_loadf_from_memory(content_data, content_length, &image_width, &image_height, &comp, 4); - image_format = IRON_IMAGE_FORMAT_RGBA128; + image_format = GPU_TEXTURE_FORMAT_RGBA128; } else { // jpg, png, .. int comp; image_data = stbi_load_from_memory(content_data, content_length, &image_width, &image_height, &comp, 4); - image_format = IRON_IMAGE_FORMAT_RGBA32; + image_format = GPU_TEXTURE_FORMAT_RGBA32; } gpu_texture_init_from_bytes(texture, image_data, image_width, image_height, image_format); @@ -1339,18 +1339,18 @@ gpu_texture_t *gpu_create_texture_from_encoded_bytes(buffer_t *data, string_t *f return texture; } -int _format_byte_size(iron_image_format_t format) { +int _format_byte_size(gpu_texture_format_t format) { switch (format) { - case IRON_IMAGE_FORMAT_RGBA128: + case GPU_TEXTURE_FORMAT_RGBA128: return 16; - case IRON_IMAGE_FORMAT_RGBA64: + case GPU_TEXTURE_FORMAT_RGBA64: return 8; - case IRON_IMAGE_FORMAT_R8: + case GPU_TEXTURE_FORMAT_R8: return 1; - case IRON_IMAGE_FORMAT_R16: + case GPU_TEXTURE_FORMAT_R16: return 2; - case IRON_IMAGE_FORMAT_RGBA32: - case IRON_IMAGE_FORMAT_R32: + case GPU_TEXTURE_FORMAT_RGBA32: + case GPU_TEXTURE_FORMAT_R32: default: return 4; } diff --git a/base/sources/iron_draw.c b/base/sources/iron_draw.c index bddfed32..18567e1b 100644 --- a/base/sources/iron_draw.c +++ b/base/sources/iron_draw.c @@ -450,7 +450,7 @@ bool draw_font_load(draw_font_t *font, int size) { img->chars = baked; img->first_unused_y = status; img->tex = (gpu_texture_t *)malloc(sizeof(gpu_texture_t)); - gpu_texture_init_from_bytes(img->tex, pixels, width, height, IRON_IMAGE_FORMAT_R8); + gpu_texture_init_from_bytes(img->tex, pixels, width, height, GPU_TEXTURE_FORMAT_R8); free(pixels); return true; } @@ -592,7 +592,7 @@ void draw_font_13(draw_font_t *font) { img->height = 128; img->first_unused_y = 0; img->tex = (gpu_texture_t *)malloc(sizeof(gpu_texture_t)); - gpu_texture_init_from_bytes(img->tex, (void *)iron_font_13_pixels, 128, 128, IRON_IMAGE_FORMAT_R8); + gpu_texture_init_from_bytes(img->tex, (void *)iron_font_13_pixels, 128, 128, GPU_TEXTURE_FORMAT_R8); stbtt_bakedchar *baked = (stbtt_bakedchar *)malloc(95 * sizeof(stbtt_bakedchar)); for (int i = 0; i < 95; ++i) { diff --git a/base/sources/iron_gpu.c b/base/sources/iron_gpu.c index 85716492..76f910c5 100644 --- a/base/sources/iron_gpu.c +++ b/base/sources/iron_gpu.c @@ -1,9 +1,18 @@ #include "iron_gpu.h" +#include #define CONSTANT_BUFFER_SIZE 256 #define CONSTANT_BUFFER_MULTIPLE 2048 -int constant_buffer_index = 0; + static gpu_buffer_t constant_buffer; +static bool gpu_thrown = false; + +int constant_buffer_index = 0; +bool gpu_in_use = false; +gpu_texture_t *current_render_targets[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +int current_render_targets_count = 0; +gpu_texture_t framebuffers[GPU_FRAMEBUFFER_COUNT]; +int framebuffer_index = 0; void gpu_init(int depth_buffer_bits, bool vsync) { gpu_init_internal(depth_buffer_bits, vsync); @@ -11,6 +20,37 @@ void gpu_init(int depth_buffer_bits, bool vsync) { gpu_constant_buffer_lock(&constant_buffer, 0, CONSTANT_BUFFER_SIZE); } +void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth) { + if (gpu_in_use && !gpu_thrown) { + gpu_thrown = true; + iron_log("End before you begin"); + } + gpu_in_use = true; + + if (current_render_targets_count > 0 && current_render_targets[0] != &framebuffers[framebuffer_index]) { + for (int i = 0; i < current_render_targets_count; ++i) { + gpu_barrier(current_render_targets[i], GPU_TEXTURE_STATE_SHADER_RESOURCE); + } + } + + if (targets == NULL) { + current_render_targets[0] = &framebuffers[framebuffer_index]; + current_render_targets_count = 1; + } + else { + for (int i = 0; i < count; ++i) { + current_render_targets[i] = targets[i]; + } + current_render_targets_count = count; + } + + for (int i = 0; i < current_render_targets_count; ++i) { + gpu_barrier(current_render_targets[i], GPU_TEXTURE_STATE_RENDER_TARGET); + } + + gpu_begin_internal(targets, count, flags, color, depth); +} + void gpu_draw() { gpu_constant_buffer_unlock(&constant_buffer); gpu_set_constant_buffer(&constant_buffer, constant_buffer_index * CONSTANT_BUFFER_SIZE, CONSTANT_BUFFER_SIZE); @@ -23,6 +63,16 @@ void gpu_draw() { gpu_constant_buffer_lock(&constant_buffer, constant_buffer_index * CONSTANT_BUFFER_SIZE, CONSTANT_BUFFER_SIZE); } +void gpu_end() { + if (!gpu_in_use && !gpu_thrown) { + gpu_thrown = true; + iron_log("Begin before you end"); + } + gpu_in_use = false; + + gpu_end_internal(); +} + void gpu_set_int(int location, int value) { int *ints = (int *)(&constant_buffer.data[location]); ints[0] = value; @@ -158,7 +208,7 @@ void gpu_internal_pipeline_init(gpu_pipeline_t *pipe) { pipe->color_write_mask_green[i] = true; pipe->color_write_mask_blue[i] = true; pipe->color_write_mask_alpha[i] = true; - pipe->color_attachment[i] = IRON_IMAGE_FORMAT_RGBA32; + pipe->color_attachment[i] = GPU_TEXTURE_FORMAT_RGBA32; } pipe->color_attachment_count = 1; pipe->depth_attachment_bits = 0; diff --git a/base/sources/iron_gpu.h b/base/sources/iron_gpu.h index c39b9478..9857adf1 100644 --- a/base/sources/iron_gpu.h +++ b/base/sources/iron_gpu.h @@ -13,32 +13,28 @@ #define GPU_CLEAR_COLOR 1 #define GPU_CLEAR_DEPTH 2 #define GPU_MAX_VERTEX_ELEMENTS 16 +#define GPU_FRAMEBUFFER_COUNT 2 -typedef enum iron_internal_render_target_state { - IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET, - IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE -} iron_internal_render_target_state_t; +typedef enum gpu_texture_state { + GPU_TEXTURE_STATE_SHADER_RESOURCE, + GPU_TEXTURE_STATE_RENDER_TARGET, + GPU_TEXTURE_STATE_PRESENT +} gpu_texture_state_t; -typedef enum iron_image_compression { - IRON_IMAGE_COMPRESSION_NONE, - IRON_IMAGE_COMPRESSION_DXT5, - IRON_IMAGE_COMPRESSION_ASTC -} iron_image_compression_t; +typedef enum gpu_texture_compression { + GPU_TEXTURE_COMPRESSION_NONE, + GPU_TEXTURE_COMPRESSION_DXT5, + GPU_TEXTURE_COMPRESSION_ASTC +} gpu_texture_compression_t; -typedef enum iron_image_format { - IRON_IMAGE_FORMAT_RGBA32, - IRON_IMAGE_FORMAT_RGBA64, - IRON_IMAGE_FORMAT_RGBA128, - IRON_IMAGE_FORMAT_R8, - IRON_IMAGE_FORMAT_R16, - IRON_IMAGE_FORMAT_R32 -} iron_image_format_t; - -typedef enum { - GPU_USAGE_STATIC, - GPU_USAGE_DYNAMIC, - GPU_USAGE_READABLE -} gpu_usage_t; +typedef enum gpu_texture_format { + GPU_TEXTURE_FORMAT_RGBA32, + GPU_TEXTURE_FORMAT_RGBA64, + GPU_TEXTURE_FORMAT_RGBA128, + GPU_TEXTURE_FORMAT_R8, + GPU_TEXTURE_FORMAT_R16, + GPU_TEXTURE_FORMAT_R32 +} gpu_texture_format_t; typedef enum gpu_vertex_data { GPU_VERTEX_DATA_F32_1X, @@ -46,7 +42,7 @@ typedef enum gpu_vertex_data { GPU_VERTEX_DATA_F32_3X, GPU_VERTEX_DATA_F32_4X, GPU_VERTEX_DATA_I16_2X_NORM, - GPU_VERTEX_DATA_I16_4X_NORM, + GPU_VERTEX_DATA_I16_4X_NORM } gpu_vertex_data_t; typedef enum gpu_shader_type { @@ -83,12 +79,12 @@ typedef enum gpu_compare_mode { typedef struct gpu_texture { int width; int height; - iron_image_format_t format; - iron_image_compression_t compression; + gpu_texture_format_t format; + gpu_texture_compression_t compression; void *data; bool uploaded; - iron_internal_render_target_state_t state; - iron_internal_render_target_state_t depth_state; + gpu_texture_state_t state; + gpu_texture_state_t depth_state; buffer_t *buffer; gpu_texture_impl_t impl; } gpu_texture_t; @@ -130,7 +126,7 @@ typedef struct gpu_pipeline { bool color_write_mask_green[8]; bool color_write_mask_blue[8]; bool color_write_mask_alpha[8]; - iron_image_format_t color_attachment[8]; + gpu_texture_format_t color_attachment[8]; int color_attachment_count; int depth_attachment_bits; gpu_pipeline_impl_t impl; @@ -145,12 +141,15 @@ typedef struct gpu_raytrace_acceleration_structure { gpu_raytrace_acceleration_structure_impl_t impl; } gpu_raytrace_acceleration_structure_t; - int gpu_max_bound_textures(void); void gpu_begin(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth); +void gpu_begin_internal(gpu_texture_t **targets, int count, unsigned flags, unsigned color, float depth); void gpu_end(void); +void gpu_end_internal(void); void gpu_wait(void); void gpu_present(void); +void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after); +void gpu_init(int depth_buffer_bits, bool vsync); void gpu_init_internal(int depth_buffer_bits, bool vsync); void gpu_destroy(void); void gpu_draw(void); @@ -167,16 +166,15 @@ void gpu_set_floats(int location, f32_array_t *values); void gpu_set_bool(int location, bool value); void gpu_set_matrix3(int location, iron_matrix3x3_t value); void gpu_set_matrix4(int location, iron_matrix4x4_t value); -void gpu_init(int depth_buffer_bits, bool vsync); void gpu_vertex_structure_add(gpu_vertex_structure_t *structure, const char *name, gpu_vertex_data_t data); -void gpu_texture_init(gpu_texture_t *texture, int width, int height, iron_image_format_t format); -void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, iron_image_format_t format); +void gpu_texture_init(gpu_texture_t *texture, int width, int height, gpu_texture_format_t format); +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_generate_mipmaps(gpu_texture_t *texture, int levels); void gpu_texture_set_mipmap(gpu_texture_t *texture, gpu_texture_t *mipmap, int level); int gpu_texture_stride(gpu_texture_t *texture); -void gpu_render_target_init(gpu_texture_t *target, int width, int height, iron_image_format_t format, int depthBufferBits); +void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int depthBufferBits); void gpu_render_target_set_depth_from(gpu_texture_t *target, gpu_texture_t *source); void gpu_vertex_buffer_init(gpu_buffer_t *buffer, int count, gpu_vertex_structure_t *structure); float *gpu_vertex_buffer_lock(gpu_buffer_t *buffer); @@ -227,8 +225,6 @@ void gpu_raytrace_set_pipeline(gpu_raytrace_pipeline_t *pipeline); void gpu_raytrace_set_target(gpu_texture_t *output); void gpu_raytrace_dispatch_rays(); -extern bool gpu_transpose_mat; - static inline int gpu_vertex_data_size(gpu_vertex_data_t data) { switch (data) { case GPU_VERTEX_DATA_F32_1X: @@ -253,3 +249,10 @@ static inline int gpu_vertex_struct_size(gpu_vertex_structure_t *s) { } return size; } + +extern bool gpu_transpose_mat; +extern gpu_texture_t *current_render_targets[8]; +extern int current_render_targets_count; +extern int constant_buffer_index; +extern gpu_texture_t framebuffers[GPU_FRAMEBUFFER_COUNT]; +extern int framebuffer_index; diff --git a/base/sources/iron_ui.c b/base/sources/iron_ui.c index f586275e..c6d4431c 100644 --- a/base/sources/iron_ui.c +++ b/base/sources/iron_ui.c @@ -512,7 +512,7 @@ void ui_resize(ui_handle_t *handle, int w, int h) { if (h < 1) { h = 1; } - gpu_render_target_init(&handle->texture, w, h, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(&handle->texture, w, h, GPU_TEXTURE_FORMAT_RGBA32, 0); } bool ui_input_in_rect(float x, float y, float w, float h) { @@ -901,7 +901,7 @@ void ui_bake_elements() { gpu_texture_destroy(¤t->check_select_image); } float r = UI_CHECK_SELECT_SIZE(); - gpu_render_target_init(¤t->check_select_image, r, r, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(¤t->check_select_image, r, r, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(¤t->check_select_image, true, 0x00000000); draw_set_color(0xffffffff); draw_line(0, r / 2.0, r / 2.0 - 2.0 * UI_SCALE(), r - 2.0 * UI_SCALE(), 2.0 * UI_SCALE()); @@ -912,7 +912,7 @@ void ui_bake_elements() { gpu_texture_destroy(¤t->radio_image); } r = UI_CHECK_SIZE(); - gpu_render_target_init(¤t->radio_image, r, r, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(¤t->radio_image, r, r, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(¤t->radio_image, true, 0x00000000); draw_set_color(0xffaaaaaa); draw_filled_circle(r / 2.0, r / 2.0, r / 2.0, 0); @@ -924,7 +924,7 @@ void ui_bake_elements() { gpu_texture_destroy(¤t->radio_select_image); } r = UI_CHECK_SELECT_SIZE(); - gpu_render_target_init(¤t->radio_select_image, r, r, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(¤t->radio_select_image, r, r, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(¤t->radio_select_image, true, 0x00000000); draw_set_color(0xffaaaaaa); draw_filled_circle(r / 2.0, r / 2.0, 4.5 * UI_SCALE(), 0); @@ -937,7 +937,7 @@ void ui_bake_elements() { gpu_texture_destroy(¤t->filled_round_corner_image); } r = 4.0 * UI_SCALE(); - gpu_render_target_init(¤t->filled_round_corner_image, r, r, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(¤t->filled_round_corner_image, r, r, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(¤t->filled_round_corner_image, true, 0x00000000); draw_set_color(0xffffffff); draw_filled_circle(r, r, r, 0); @@ -946,7 +946,7 @@ void ui_bake_elements() { if (current->round_corner_image.width != 0) { gpu_texture_destroy(¤t->round_corner_image); } - gpu_render_target_init(¤t->round_corner_image, r, r, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(¤t->round_corner_image, r, r, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(¤t->round_corner_image, true, 0x00000000); draw_set_color(0xffffffff); draw_circle(r, r, r, 0, 1); diff --git a/base/sources/iron_ui_nodes.c b/base/sources/iron_ui_nodes.c index 998189cf..056b4c19 100644 --- a/base/sources/iron_ui_nodes.c +++ b/base/sources/iron_ui_nodes.c @@ -238,7 +238,7 @@ void ui_nodes_bake_elements() { if (ui_socket_image.width != 0) { gpu_texture_destroy(&ui_socket_image); } - gpu_render_target_init(&ui_socket_image, 24, 24, IRON_IMAGE_FORMAT_RGBA32, 0); + gpu_render_target_init(&ui_socket_image, 24, 24, GPU_TEXTURE_FORMAT_RGBA32, 0); draw_begin(&ui_socket_image, true, 0x00000000); draw_set_color(0xff111111); draw_filled_circle(12, 12, 11, 0);