diff --git a/src/assets.c b/src/assets.c index 1d3416d..2629bc7 100644 --- a/src/assets.c +++ b/src/assets.c @@ -85,8 +85,6 @@ static Asset apLoadShader(ShaderAsset asset_id) if (asset.bytes == NULL) { AssetFile *asset_info = Shader_Assets + asset_id; - - Printfln("%llu %llu", asset_info->len, asset_info->data_offset); asset.bytes = FLMemAlloc(asset_info->len); MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len); @@ -97,36 +95,31 @@ static Asset apLoadShader(ShaderAsset asset_id) return asset; } -static void apUnloadTexture(Asset asset) +static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id) { - Assert(asset.bytes != NULL, "UnloadTextureAsset assert failure: ptr is NULL"); + AssetFile *asset_file = Texture_Assets + asset_id; + return asset_file->texture_meta; +} - for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++) +static void apUnloadTexture(TextureAsset asset_id) +{ + Asset *asset = Texture_Asset_Lookup + asset_id; + if (asset->bytes != NULL) { - if (asset.bytes == Texture_Asset_Lookup[i].bytes) - { - Texture_Asset_Lookup[i].bytes = NULL; - Texture_Asset_Lookup[i].len = 0; - FLMemFree(asset.bytes); - break; - } + FLMemFree(asset->bytes); + asset->bytes = NULL; + asset->len = 0; } } -static void apUnloadShader(Asset asset) +static void apUnloadShader(ShaderAsset asset_id) { - Assert(asset.bytes != NULL, "UnloadShaderAsset assert failure: ptr is NULL"); - - for (u32 i = 0; i < SHADER_ASSET_MAX; i++) + Asset *asset = Shader_Asset_Lookup + asset_id; + if (asset->bytes != NULL) { - if (asset.bytes == Shader_Asset_Lookup[i].bytes) - { - Shader_Asset_Lookup[i].bytes = NULL; - Shader_Asset_Lookup[i].len = 0; - FLMemFree(asset.bytes); - - break; - } + FLMemFree(asset->bytes); + asset->bytes = NULL; + asset->len = 0; } } diff --git a/src/assets.h b/src/assets.h index f78b1d1..f81b853 100644 --- a/src/assets.h +++ b/src/assets.h @@ -117,8 +117,9 @@ static void apInit(); static Asset apLoadTexture(TextureAsset asset_id); static Asset apLoadShader(ShaderAsset asset_id); -static void apUnloadTexture(Asset asset); -static void apUnloadShader(Asset asset); +static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id); +static void apUnloadTexture(TextureAsset asset_id); +static void apUnloadShader(ShaderAsset asset_id); // ::Assets::Util::Functions::Header:: diff --git a/src/game.c b/src/game.c index c508745..7bc8df2 100644 --- a/src/game.c +++ b/src/game.c @@ -77,7 +77,7 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) rViewportSize(&ctx->pc.res); - //rDescHandle pattermon = rTextureCreateAndUpload(PATTERMON_OBESE); + rDescHandle pattermon = rTextureCreateAndUpload(PATTERMON_OBESE); rawptr vert_buffer = rBufferGUIVertMapping(); rawptr idx_buffer = rBufferGUIIdxMapping(); @@ -85,20 +85,7 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) MemCpy(vert_buffer, ctx->gui.vertices, sizeof(rUIVertex) * ctx->gui.vertices_len); MemCpy(idx_buffer, ctx->gui.indices, sizeof(u32) * ctx->gui.indices_len); - /* - rRenderBuffer *vertex_buffer = MakeArray(ctx->arena, rRenderBuffer, 1); - vertex_buffer->type = rRBT_VERTEX; - vertex_buffer->size = sizeof(rUIVertex) * ctx->gui.vertices_len; - - rRenderBuffer *index_buffer = MakeArray(ctx->arena, rRenderBuffer, 1); - index_buffer->type = rRBT_INDEX, - index_buffer->size = sizeof(u32) * ctx->gui.indices_len, - - rBufferCreateAndUpload(vertex_buffer, ctx->gui.vertices); - rBufferCreateAndUpload(index_buffer, ctx->gui.indices); - */ - - WaitForBufferQueue(); + vBufferQueueWait(); rFrameBegin(); @@ -106,11 +93,6 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) rPushConstantsSet(&ctx->pc); - /* - rBufferBindVertex(vertex_buffer); - rBufferBindIndex(index_buffer); - */ - rBufferBindGUIVertex(); rBufferBindGUIIndex(); @@ -118,11 +100,6 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) rFrameFinish(); - /* - rBufferFree(vertex_buffer, 1); - rBufferFree(index_buffer, 1); - */ - ctx->gui.vertices_len = 0; ctx->gui.indices_len = 0; ctx->gui.instance_count = 0; diff --git a/src/renderer_vulkan.c b/src/renderer_vulkan.c index 97860cb..a218979 100644 --- a/src/renderer_vulkan.c +++ b/src/renderer_vulkan.c @@ -81,7 +81,7 @@ static inline VkSemaphore vFrameSwapSem() static inline vBufferAllocPtrArray *vFrameBuffers() { - return v_Renderer.buffers.frame + vFrameIndex(); + return v_Renderer.buffers.frame_buffers + vFrameIndex(); } static inline void vImageCopyToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext) @@ -331,6 +331,85 @@ static void vSwapchainResize() // ::Vulkan::Images::Functions::Start:: +static b32 vImageViewCreate(vImageView *view, u32 width, u32 height, u32 channels) +{ + b32 success = true; + + VmaAllocationCreateInfo alloc_create_info = { + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + }; + + VkImageCreateInfo image_info = { + .sType = STYPE(IMAGE_CREATE_INFO), + .imageType = VK_IMAGE_TYPE_2D, + .mipLevels = 1, + .arrayLayers = 1, + .format = VK_FORMAT_R8G8B8A8_SRGB, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .samples = VK_SAMPLE_COUNT_1_BIT, + .extent = { + .width = width, + .height = height, + .depth = 1, + }, + }; + + if (v_Renderer.state.vk.single_queue) + { + image_info.sharingMode = VK_SHARING_MODE_CONCURRENT; + image_info.queueFamilyIndexCount = 2; + image_info.pQueueFamilyIndices = (u32[]){v_Renderer.state.vk.gfx_queue_idx, v_Renderer.state.vk.tfer_queue_idx}; + } + + VkResult result = vmaCreateImage(v_Renderer.handles.vma_alloc, &image_info, &alloc_create_info, + &view->image.image, &view->image.alloc, NULL); + if (result != VK_SUCCESS) + { + Printfln("vImageViewCreate error: vmaCreateImage failure: %s", vVkResultStr(result)); + success = false; + } + + VkImageViewCreateInfo view_info = { + .sType = STYPE(IMAGE_VIEW_CREATE_INFO), + .image = view->image.image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = VK_FORMAT_R8G8B8A8_SRGB, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1, + }, + }; + + result = vkCreateImageView(v_Renderer.handles.device, &view_info, NULL, &view->view); + if (result != VK_SUCCESS) + { + Printfln("vImageViewCreate error: vkCreateImageView failure: %s", vVkResultStr(result)); + success = false; + } + + return success; +} + +static vImageView *vImageLookupExisting(TextureAsset asset_id) +{ + vImageView *view = NULL; + + HashTable *table = &v_Renderer.buffers.images; + + KeyValuePair *pair = HashTableSearchU64(table, asset_id); + if (pair != NULL) + { + view = (vImageView *)pair->value_rawptr; + } + + return view; +} + static b32 vSamplerCreate(rTextureBuffer *buffer) { /* @@ -494,6 +573,30 @@ static void vImageUpload(rTextureBuffer *buffer, u8 *data, u32 thread_idx) // ::Vulkan::Descriptors::Functions::Start:: +static u32 vDescPushImage(vImageView *view) +{ + u32 index = vDescIndexPop(vDT_SAMPLED_IMAGE); + + VkDescriptorImageInfo image_info = { + .imageView = view->view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + + VkWriteDescriptorSet desc_write = { + .sType = STYPE(WRITE_DESCRIPTOR_SET), + .dstSet = v_Renderer.handles.desc_sets[vDT_SAMPLED_IMAGE], + .dstBinding = 0, + .descriptorCount = 1, + .dstArrayElement = index, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .pImageInfo = &image_info, + }; + + vkUpdateDescriptorSets(v_Renderer.handles.device, 1, &desc_write, 0, NULL); + + return index; +} + static void vDescIndexPush(vDescType type, u32 index) { vDescBindings *bindings = v_Renderer.desc_bindings + type; @@ -532,7 +635,7 @@ static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id) return asset_info; } -static void DescriptorTableInsert(vDescType type, rDescHandle handle) +static void vDescHandleInsert(vDescType type, rDescHandle handle) { HashTable *table = &v_Renderer.desc_bindings[type].lookup_table; HashTablePushU64U64Split(table, handle.asset_id, handle.asset_id, handle.desc_index); @@ -1048,6 +1151,7 @@ static b32 vDeviceFunctionsInit() { INIT_DEV_FN(vkDeviceWaitIdle); INIT_DEV_FN(vkCmdClearColorImage); INIT_DEV_FN(vkCreateSampler); + INIT_DEV_FN(vkDestroySampler); return true; } @@ -1530,8 +1634,8 @@ static b32 vPipelinesInit() vkDestroyShaderModule(device, cube_vert, NULL); vkDestroyShaderModule(device, cube_frag, NULL); - apUnloadShader(quad_vert_shader); - apUnloadShader(quad_frag_shader); + apUnloadShader(QUAD_VERT_SPIRV_SHADER); + apUnloadShader(QUAD_FRAG_SPIRV_SHADER); Asset gui_vert_shader = apLoadShader(GUI_VERT_SPIRV_SHADER); Asset gui_frag_shader = apLoadShader(GUI_FRAG_SPIRV_SHADER); @@ -1570,8 +1674,8 @@ static b32 vPipelinesInit() vkDestroyShaderModule(device, gui_vert, NULL); vkDestroyShaderModule(device, gui_frag, NULL); - apUnloadShader(gui_vert_shader); - apUnloadShader(gui_frag_shader); + apUnloadShader(GUI_VERT_SPIRV_SHADER); + apUnloadShader(GUI_FRAG_SPIRV_SHADER); return success; } @@ -1602,15 +1706,13 @@ static b32 vBuffersInit() vRBuffers *buf = &v_Renderer.buffers; Arena *arena = v_Renderer.mem.perm_arena; - buf->perm.data = MakeArray(arena, vBufferAlloc *, 1024); - buf->perm.cap = 1024; - buf->perm.length = 0; + HashTableInit(&buf->buffers, 8); + HashTableInit(&buf->images, 8); for (u32 i = 0; i < FRAME_OVERLAP; i++) { - buf->frame[i].data = MakeArray(arena, vBufferAlloc *, 512); - buf->frame[i].cap = 512; - buf->frame[i].length = 0; + InitArrayType(buf->frame_buffers[i], arena, vBufferAlloc *, 128); + InitArrayType(buf->frame_images[i], arena, vImageView *, 128); } b32 success = true; @@ -1618,28 +1720,31 @@ static b32 vBuffersInit() if (success) { - result = vBufferCreate(&buf->gui_vert.alloc, rRBT_VERTEX | rRBT_HOST, MB(32)); + result = vBufferCreate(&buf->gui_vert.alloc, rRBT_VERTEX | rRBT_HOST, VERTEX_BUFFER_CAP); if (result != VK_SUCCESS) success = false; } if (success) { - result = vBufferCreate(&buf->gui_idx.alloc, rRBT_INDEX | rRBT_HOST, MB(8)); // TODO: figure out ratio of memory alloc from vertex -> index + result = vBufferCreate(&buf->gui_idx.alloc, rRBT_INDEX | rRBT_HOST, INDEX_BUFFER_CAP); // TODO: figure out ratio of memory alloc from vertex -> index if (result != VK_SUCCESS) success = false; } if (success) { - result = vBufferCreate(&buf->transfer.alloc, rRBT_STAGING, MB(64)); + result = vBufferCreate(&buf->transfer.alloc, rRBT_STAGING, TRANSFER_BUFFER_CAP); if (result != VK_SUCCESS) success = false; } buf->gui_vert.ptr = vMapBuffer(buf->gui_vert.alloc.alloc); + buf->gui_vert.cap = MB(32); buf->gui_idx.ptr = vMapBuffer(buf->gui_idx.alloc.alloc); + buf->gui_idx.cap = MB(8); buf->transfer.ptr = vMapBuffer(buf->transfer.alloc.alloc); + buf->transfer.cap = MB(64); return success; } @@ -1764,6 +1869,110 @@ static u32 vLoaderProcessSamplers(u32 thread_index) return 0; } +static void vTransferUpload(vTransfer **transfers, u32 count, u32 idx) +{ + VkCommandPool pool = v_Renderer.imm_handles.data[idx].pool; + VkCommandBuffer buffer = v_Renderer.imm_handles.data[idx].buffer; + VkFence fence = v_Renderer.imm_handles.data[idx].fence; + VkDevice device = v_Renderer.handles.device; + VkQueue queue = v_Renderer.handles.tfer_queue; + vMappedBuffer *transfer = &v_Renderer.buffers.transfer; + + rawptr data_ptr = NULL; + u64 data_len = 0; + + rawptr ptr = transfer->ptr; + u64 ptr_pos = 0; + b32 imm_started = false; + u32 i = 0; + for (;;) + { + if (i == count) + break; + + if (data_ptr == NULL) + { + data_ptr = transfers[i]->data; + + if (transfers[i]->type == vTT_IMAGE) + { + data_len = transfers[i]->w * transfers[i]->h * transfers[i]->ch; + } + else + { + data_len = transfers[i]->size; + } + } + + if (ptr_pos == transfer->cap) + { + vImmSubmitFinish(device, fence, buffer, queue); + vkWaitForFences(device, 1, &fence, VK_TRUE, 999999999); + imm_started = false; + } + + if (!imm_started) + { + Assert(vImmSubmitBegin(device, fence, buffer), "vTransferUpload failure: vImmSubmitBegin failed"); // TODO: handle this + imm_started = true; + } + + if (transfers[i]->type == vTT_NONE) {} + else if (transfers[i]->type == vTT_IMAGE) + { + u64 remaining = Diff(TRANSFER_BUFFER_CAP, ptr_pos); + u64 transfer_size = data_len; + if (transfer_size > remaining) + transfer_size = remaining; + + MemCpy(ptr, transfers[i]->data, transfer_size); + + ptr = PtrAdd(ptr, transfer_size); + PtrAddAdjustLen(data_ptr, data_len, transfer_size); + + MemZero(&transfers[i]->image_copy, sizeof(VkBufferImageCopy)); + + transfers[i]->image_copy.bufferRowLength = transfers[i]->w; + transfers[i]->image_copy.bufferImageHeight = transfers[i]->h; + transfers[i]->image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + transfers[i]->image_copy.imageSubresource.layerCount = 1; + transfers[i]->image_copy.imageExtent.width = transfers[i]->w; + transfers[i]->image_copy.imageExtent.height = transfers[i]->h; + transfers[i]->image_copy.imageExtent.depth = 1; + + vImageTransitionLayout(buffer, + transfers[i]->image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vkCmdCopyBufferToImage(buffer, + transfer->alloc.buffer, + transfers[i]->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &transfers[i]->image_copy); + + vImageTransitionLayout(buffer, + transfers[i]->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + if (data_len == 0) + { + data_ptr = NULL; + data_len = 0; + i += 1; + } + } + else if (transfers[i]->type == vTT_BUFFER) + { + i += 1; + } + } + + if (imm_started) + vImmSubmitFinish(device, fence, buffer, queue); +} #ifdef __linux__ @@ -1774,54 +1983,56 @@ void *vLoaderStart(void *i) pthread_mutex_t mut; pthread_mutex_init(&mut, NULL); - u32 processed_count = 0; - u32 iter_count = 0; - /* for (;;) - { - for (u32 i = 0; i < vDT_MAX; i++) + { + + TicketMutLock(&v_Renderer.upload.mut); + u32 job_count = JobQueueGetCount(&v_Renderer.upload.job_queue); + if (job_count > 0) { - Mut *mut = &renderer.upload_queues[i].mut; - if (MutTryLock(mut)) + vTransfer **transfers = MakeArray(vFrameArena(), vTransfer *, job_count); + + u32 unqueued_count = 0; + for (u32 i = 0; i < job_count; i++) { - switch (i) - { - case vDT_MATERIAL: - { - processed_count += vLoaderProcessBuffers(index); - } break; - case vDT_SAMPLED_IMAGE: - { - processed_count += vLoaderProcessSamplers(index); - } break; - default: - break; - } - - MutUnlock(mut); + unqueued_count += 1; + transfers[i] = v_Renderer.upload.transfers[i]; } + + JobQueueMarkUnqueued(&v_Renderer.upload.job_queue, unqueued_count); + + TicketMutUnlock(&v_Renderer.upload.mut); + + vTransferUpload(transfers, job_count, index); + + for (u32 i = 0; i < job_count; i++) + { + if (transfers[i]->type == vTT_IMAGE) + apUnloadTexture(transfers[i]->asset_id); + } + + JobQueueMarkCompleted(&v_Renderer.upload.job_queue, job_count); } - - iter_count += 1; - - if (processed_count < 0) - pthread_exit(NULL); - else if (processed_count == 0 && iter_count >= 3) + else if (job_count == 0) { - iter_count = 0; pu8AtomicIncr(&v_Renderer.async.sleeping); + TicketMutUnlock(&v_Renderer.upload.mut); pthread_mutex_lock(&mut); pthread_cond_wait(&v_Renderer.async.cond, &mut); pthread_mutex_unlock(&mut); pu8AtomicFetchSub(&v_Renderer.async.sleeping, 1); } + else + { + TicketMutUnlock(&v_Renderer.upload.mut); + pthread_exit(NULL); + } } - */ pthread_exit(NULL); } -void vLoaderWake() +static void vLoaderWake() { for (u32 i = 0; i < v_Renderer.async.count; i++) pthread_cond_signal(&v_Renderer.async.cond); diff --git a/src/renderer_vulkan.h b/src/renderer_vulkan.h index e2bc24b..d4d976b 100644 --- a/src/renderer_vulkan.h +++ b/src/renderer_vulkan.h @@ -31,7 +31,11 @@ static char *vulkan_libs[] = { #error Not yet implemented #endif -#define V_THREAD_MAX 2 +#define V_THREAD_MAX 1 + +#define VERTEX_BUFFER_CAP MB(32) +#define INDEX_BUFFER_CAP MB(8) +#define TRANSFER_BUFFER_CAP MB(64) // ::Vulkan::Macros::Header:: @@ -154,6 +158,7 @@ VK_DECLARE(vkCmdDraw); VK_DECLARE(vkDeviceWaitIdle); VK_DECLARE(vkCmdClearColorImage); VK_DECLARE(vkCreateSampler); +VK_DECLARE(vkDestroySampler); #include "vma/vk_mem_alloc.h" @@ -220,6 +225,7 @@ typedef struct vImageView VkImageView view; } vImageView; +PtrArrayType(vImageView); ArrayType(vImageView); typedef struct vSampler @@ -289,10 +295,10 @@ typedef struct vFrameHandles typedef struct vAsync { - u32 thread_idx[V_THREAD_MAX]; + u32 thread_idx[V_THREAD_MAX]; #ifdef __linux__ - pthread_t threads[V_THREAD_MAX]; - pthread_cond_t cond; + pthread_t threads[V_THREAD_MAX]; + pthread_cond_t cond; #elif _WIN32 # error not yet implemented #endif @@ -339,14 +345,15 @@ typedef struct vMappedBuffer { vBufferAlloc alloc; rawptr ptr; - u64 used; u64 cap; } vMappedBuffer; typedef struct vRBuffers { - vBufferAllocPtrArray perm; - vBufferAllocPtrArray frame[FRAME_OVERLAP]; + HashTable buffers; + vBufferAllocPtrArray frame_buffers[FRAME_OVERLAP]; + HashTable images; + vImageViewPtrArray frame_images[FRAME_OVERLAP]; vMappedBuffer transfer; vMappedBuffer gui_vert; vMappedBuffer gui_idx; @@ -363,12 +370,27 @@ typedef struct vTransfer { vTransferType type; rawptr data; - u64 size; + u32 asset_id; + union + { + u64 size; + struct + { + u32 w; + u32 h; + u8 ch; + }; + }; union { VkBuffer buffer; VkImage image; }; + union + { + VkBufferCopy buffer_copy; + VkBufferImageCopy image_copy; + }; } vTransfer; typedef struct vUploadQueue @@ -486,7 +508,8 @@ static inline void vImageCopyToImage(VkCommandBuffer cmd, VkImage src, VkImage d // ::Vulkan::Async::Functions::Header:: -void vLoaderWake(); +static void vBufferQueueWait(); +static void vLoaderWake(); static u32 vLoaderProcessBuffers(u32 thread_index); static u32 vLoaderProcessSamplers(u32 thread_index); @@ -511,15 +534,19 @@ static void vSwapchainResize(); // ::Vulkan::Images::Functions::Header:: +static b32 vImageViewCreate(vImageView *view, u32 width, u32 height, u32 channels); static b32 vSamplerCreate(rTextureBuffer *buffer); static void vImageUpload(rTextureBuffer *buffer, u8 *data, u32 thread_idx); +static vImageView *vImageLookupExisting(TextureAsset asset_id); // ::Vulkan::Descriptors::Functions::Header:: static void vDescIndexPush(vDescType type, u32 index); static u32 vDescIndexPop(vDescType type); static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id); +static void vDescHandleInsert(vDescType type, rDescHandle handle); static void vDescHandleDelete(vDescType type, u32 asset_id); +static u32 vDescPushImage(vImageView *view); // ::Vulkan::Buffers::Functions::Header:: diff --git a/src/renderer_vulkan_public.c b/src/renderer_vulkan_public.c index 3548745..c4e0523 100644 --- a/src/renderer_vulkan_public.c +++ b/src/renderer_vulkan_public.c @@ -38,8 +38,7 @@ void rDestroy() { VkDevice device = v_Renderer.handles.device; VkInstance instance = v_Renderer.handles.inst; - vBufferAllocPtrArray *frame_buffers = v_Renderer.buffers.frame; - vBufferAllocPtrArray buffers = v_Renderer.buffers.perm; + vBufferAllocPtrArray *frame_buffers = v_Renderer.buffers.frame_buffers; vImmHandlesArray imm = v_Renderer.imm_handles; VmaAllocator vma_alloc = v_Renderer.handles.vma_alloc; VkSwapchainKHR swapchain = v_Renderer.handles.swapchain; @@ -48,9 +47,12 @@ void rDestroy() VkDescriptorSetLayout *desc_layouts = v_Renderer.handles.desc_layouts; VkDescriptorPool desc_pool = v_Renderer.handles.desc_pool; vAsync async = v_Renderer.async; + VkSampler nearest_sampler = v_Renderer.handles.nearest_sampler; vkDeviceWaitIdle(device); + vkDestroySampler(device, nearest_sampler, NULL); + for (u32 i = R_PIPELINE_CUBE; i < R_PIPELINE_MAX; i++) vkDestroyPipeline(device, pipelines[i], NULL); @@ -289,39 +291,45 @@ static void rBufferCreateAndUpload(ModelAsset asset_id) static rDescHandle rTextureCreateAndUpload(TextureAsset asset_id) { + rDescHandle handle = vDescHandleSearch(vDT_SAMPLED_IMAGE, asset_id); - // TODO: replace it, store asset information (vertex count, res, etc) in asset header files and pull them for use in draw commands, etc. - /* - vAssetInfo *info = vDescHandleSearch(vDT_SAMPLED_IMAGE, asset_id); - if (info == NULL) + if (handle.asset_id == UINT32_MAX) { + vImageView *view = FLMemAlloc(sizeof(vImageView)); + Asset asset = apLoadTexture(asset_id); + TextureAssetMeta meta = apGetTextureMeta(asset_id); - rTextureBuffer *buffer = FLMemAlloc(sizeof(rTextureBuffer)); - buffer->type = rTBT_SAMPLER; - buffer->width = asset.texture_meta.w; - buffer->height = asset.texture_meta.h; - buffer->channels = asset.texture_meta.ch; + // TODO: handle errors instead of failing + Assert(vImageViewCreate(view, meta.w, meta.h, meta.ch), "rTextureCreateAndUpload failure: vImageViewCreate failed"); - TicketMutLock(&renderer.upload_queues[vDT_SAMPLED_IMAGE].ticket_mut); + handle.asset_id = asset_id; + handle.desc_index = vDescPushImage(view); - u32 job_idx = JobQueueAdd(&renderer.upload_queues[vDT_SAMPLED_IMAGE].job_queue, 1); - renderer.upload_queues[vDT_SAMPLED_IMAGE].queued_textures[job_idx] = buffer; - renderer.upload_queues[vDT_SAMPLED_IMAGE].data[job_idx] = asset.bytes; + TicketMutLock(&v_Renderer.upload.mut); - handle = vDescIndexPop(vDT_SAMPLED_IMAGE); + Arena *arena = vFrameArena(); - TicketMutUnlock(&renderer.upload_queues[vDT_SAMPLED_IMAGE].ticket_mut); + vTransfer *transfer = MakeArray(arena, vTransfer, 1); + + transfer->type = vTT_IMAGE; + transfer->data = asset.bytes; + transfer->w = meta.w; + transfer->h = meta.h; + transfer->ch = meta.ch; + transfer->asset_id = asset_id; + transfer->image = view->image.image; + + u32 job_idx = JobQueueAdd(&v_Renderer.upload.job_queue, 1); + + v_Renderer.upload.transfers[job_idx] = transfer; + + vDescHandleInsert(vDT_SAMPLED_IMAGE, handle); + + TicketMutUnlock(&v_Renderer.upload.mut); vLoaderWake(); } - else - { - handle = info->handle; - } - */ - - rDescHandle handle = {UINT32_MAX}; return handle; } @@ -366,18 +374,12 @@ static rAssetHandle rTextureLoad(TextureAsset asset_id) return handle; } -static void WaitForBufferQueue() +static void vBufferQueueWait() { - for (u32 i = 0; i < vDT_MAX; i++) + while (!JobQueueCompleted(&v_Renderer.upload.job_queue)) { - // TODO: replace - /* - while (!JobQueueCompleted(&renderer.upload_queues[vDT_MATERIAL].job_queue)) - { - if (v_Renderer.state.renderer.height > 0) - vLoaderWake(); - } - */ + if (v_Renderer.async.sleeping > 0) + vLoaderWake(); } } diff --git a/src/util.c b/src/util.c index 9f1c333..fdc3bf5 100644 --- a/src/util.c +++ b/src/util.c @@ -339,11 +339,13 @@ static inline u32 JobQueueGetCount(JobQueue *queue) static inline void JobQueueMarkUnqueued(JobQueue *queue, u32 count) { + Assert(queue->queued != 0, "queue queued is 0 before trying to mark dequeued"); pu32AtomicFetchSub(&queue->queued, count); } static inline void JobQueueMarkCompleted(JobQueue *queue, u32 count) { + Assert(queue->remaining != 0, "queue remaining is 0 before trying to mark completed"); pu32AtomicFetchSub(&queue->remaining, count); } diff --git a/src/util.h b/src/util.h index d155882..4485f7d 100644 --- a/src/util.h +++ b/src/util.h @@ -16,8 +16,12 @@ typedef struct Arena Arena; #define BitEq(var, bits) (((var) & (bits)) == (bits)) #define AlignPow2(x, b) (((x) + (b) - 1) & (~((b) - 1))) #define IsPow2(x) ((x) != 0 && ((x) &((x) - 1)) == 0) -#define PtrAdd(ptr, add) (((char *)ptr) + add) +#define PtrAdd(ptr, add) (((u8 *)ptr) + add) +#define PtrAddAdjustLen(ptr, len, add) \ +ptr = PtrAdd(ptr, add); \ +len -= add +#define Diff(value, sub) (value - sub) #define MakeArray(arena, type, count) ArenaAlloc(arena, (isize)(sizeof(type)) * (isize)(count)) #define Len(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) @@ -282,6 +286,7 @@ static inline void MutUnlock(Mut *mut); static inline void TicketMutLock(TicketMut *mut); static inline void TicketMutUnlock(TicketMut *mut); static inline u32 JobQueueAdd(JobQueue *queue, u32 count); +static inline u32 JobQueueGetCount(JobQueue *queue); static inline void JobQueueMarkUnqueued(JobQueue *queue, u32 count); static inline void JobQueueMarkCompleted(JobQueue *queue, u32 count); static inline void JobQueueReset(JobQueue *queue);