682 lines
17 KiB
C
682 lines
17 KiB
C
// ::Vulkan::Renderer::Initialization::Functions::Start::
|
|
|
|
b32 rInit()
|
|
{
|
|
rThreadCountSet(pCPUCountGet());
|
|
vInitArenas();
|
|
vCustomizePipelines();
|
|
|
|
Assert(vInitInstance(), "Unable to initialize instance");
|
|
Assert(vInstanceFunctionsInit(), "Unable to initialize instance functions");
|
|
|
|
#ifdef BUILD_DEBUG
|
|
{
|
|
vEnableDebug();
|
|
}
|
|
#endif
|
|
|
|
Assert(vSurfaceInit(), "Unable to create surface");
|
|
Assert(vDeviceInit(), "Unable to create device");
|
|
Assert(vVmaAllocatorInit(), "Unable to create VMA allocator");
|
|
Assert(vSwapchainInit(), "Unable to initialize swapchain and draw images");
|
|
Assert(vDrawImagesInit(), "Unable to create draw images");
|
|
Assert(vFrameStructuresInit(), "Unable to create frame structures");
|
|
Assert(vImmediateStructuresInit(), "Unable to create immediate structures");
|
|
Assert(vDescriptorsInit(), "Unable to initialize descriptors.");
|
|
Assert(vPipelinesInit(), "Unable to initialize pipelines.");
|
|
Assert(vInitBuffers(), "Unable to initialize buffers.");
|
|
|
|
vUploadQueuesInit();
|
|
vLoaderStartThreads();
|
|
|
|
ArenaFree(vFrameArena());
|
|
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
vImmHandlesArray imm = v_Renderer.imm_handles;
|
|
VmaAllocator vma_alloc = v_Renderer.handles.vma_alloc;
|
|
VkSwapchainKHR swapchain = v_Renderer.handles.swapchain;
|
|
VkPipeline *pipelines = v_Renderer.handles.pipelines;
|
|
VkPipelineLayout pipeline_layout = v_Renderer.handles.pipeline_layout;
|
|
VkDescriptorSetLayout *desc_layouts = v_Renderer.handles.desc_layouts;
|
|
VkDescriptorPool desc_pool = v_Renderer.handles.desc_pool;
|
|
vAsync async = v_Renderer.async;
|
|
|
|
vkDeviceWaitIdle(device);
|
|
|
|
for (u32 i = R_PIPELINE_CUBE; i < R_PIPELINE_MAX; i++)
|
|
vkDestroyPipeline(device, pipelines[i], NULL);
|
|
|
|
vkDestroyPipelineLayout(device, pipeline_layout, NULL);
|
|
|
|
for (u32 i = vDT_SHARED; i < vDT_MAX; i++)
|
|
vkDestroyDescriptorSetLayout(device, desc_layouts[i], NULL);
|
|
|
|
vkDestroyDescriptorPool(device, desc_pool, NULL);
|
|
|
|
vDrawImagesDestroy();
|
|
|
|
vSwapchainDestroy();
|
|
|
|
for (u32 i = 0; i < async.count; i++)
|
|
{
|
|
vImmHandles ih = imm.data[i];
|
|
|
|
vkDestroyFence(device, ih.fence, NULL);
|
|
vkFreeCommandBuffers(device, ih.pool, 1, &ih.buffer);
|
|
vkDestroyCommandPool(device, ih.pool, NULL);
|
|
}
|
|
|
|
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
|
{
|
|
vFrameHandles fh = v_Renderer.frame_handles[i];
|
|
|
|
vkDestroySemaphore(device, fh.r_sem, NULL);
|
|
vkDestroySemaphore(device, fh.sc_sem, NULL);
|
|
vkDestroyFence(device, fh.r_fence, NULL);
|
|
vkFreeCommandBuffers(device, fh.pool, 1, &fh.buffer);
|
|
vkDestroyCommandPool(device, fh.pool, NULL);
|
|
|
|
for (u32 j = 0; j < frame_buffers[i].length; j++)
|
|
vmaDestroyBuffer(vma_alloc, frame_buffers[i].data[j]->buffer, frame_buffers[i].data[j]->alloc);
|
|
}
|
|
|
|
vmaUnmapMemory(vma_alloc, v_Renderer.buffers.transfer.alloc.alloc);
|
|
vmaUnmapMemory(vma_alloc, v_Renderer.buffers.gui_vert.alloc.alloc);
|
|
vmaUnmapMemory(vma_alloc, v_Renderer.buffers.gui_idx.alloc.alloc);
|
|
|
|
vmaDestroyBuffer(vma_alloc, v_Renderer.buffers.transfer.alloc.buffer, v_Renderer.buffers.transfer.alloc.alloc);
|
|
vmaDestroyBuffer(vma_alloc, v_Renderer.buffers.gui_vert.alloc.buffer, v_Renderer.buffers.gui_vert.alloc.alloc);
|
|
vmaDestroyBuffer(vma_alloc, v_Renderer.buffers.gui_idx.alloc.buffer, v_Renderer.buffers.gui_idx.alloc.alloc);
|
|
|
|
vmaDestroyAllocator(v_Renderer.handles.vma_alloc);
|
|
vkDestroyDevice(v_Renderer.handles.device, NULL);
|
|
vkDestroySurfaceKHR(v_Renderer.handles.inst, v_Renderer.handles.surface, NULL);
|
|
|
|
#ifdef BUILD_DEBUG
|
|
{
|
|
vkDestroyDebugUtilsMessengerEXT(v_Renderer.handles.inst, v_Renderer.handles.debug, NULL);
|
|
}
|
|
#endif
|
|
|
|
vkDestroyInstance(v_Renderer.handles.inst, NULL);
|
|
|
|
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
|
{
|
|
ArenaFree(v_Renderer.mem.frame_arenas[i]);
|
|
}
|
|
|
|
ArenaFree(v_Renderer.mem.perm_arena);
|
|
}
|
|
|
|
// ::Vulkan::Renderer::Initialization::Functions::End::
|
|
|
|
|
|
|
|
// ::Vulkan::Renderer::Buffers::Functions::Start::
|
|
|
|
static rBuffer rBufferCreate(rRenderBufferType type, u64 size)
|
|
{
|
|
rBuffer buffer = NULL;
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static b32 rBufferCreateOLD(rRenderBufferType type, u64 size)
|
|
{
|
|
Assert(type != rRBT_NONE, "rBufferCreate: rRenderBuffer type must not be rRBT_NONE");
|
|
|
|
b32 success = true;
|
|
|
|
VkResult result;
|
|
|
|
u32 gfx_queue = v_Renderer.state.vk.gfx_queue_idx;
|
|
u32 tfer_queue = v_Renderer.state.vk.tfer_queue_idx;
|
|
VmaAllocator alloc = v_Renderer.handles.vma_alloc;
|
|
|
|
VkBufferCreateInfo buffer_info = {
|
|
.sType = STYPE(BUFFER_CREATE_INFO),
|
|
//.size = (VkDeviceSize)buffer->size,
|
|
};
|
|
|
|
VmaAllocationCreateInfo alloc_info = {
|
|
.usage = VMA_MEMORY_USAGE_UNKNOWN,
|
|
.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
};
|
|
|
|
switch (type)
|
|
{
|
|
case rRBT_VERTEX:
|
|
{
|
|
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
|
} break;
|
|
case rRBT_INDEX:
|
|
{
|
|
buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
|
} break;
|
|
case rRBT_UNIFORM:
|
|
{
|
|
buffer_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
|
} break;
|
|
case rRBT_STAGING:
|
|
{
|
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
} break;
|
|
case rRBT_STORAGE:
|
|
{
|
|
buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((type & rRBT_HOST) == rRBT_HOST || type == rRBT_STAGING)
|
|
{
|
|
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
alloc_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
|
}
|
|
else
|
|
{
|
|
buffer_info.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
|
}
|
|
|
|
if (tfer_queue != gfx_queue)
|
|
{
|
|
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
buffer_info.queueFamilyIndexCount = 2;
|
|
buffer_info.pQueueFamilyIndices = (u32[]){gfx_queue, tfer_queue};
|
|
}
|
|
|
|
//result = vmaCreateBuffer(alloc, &buffer_info, &alloc_info, &buffer->buffer, &buffer->alloc, &buffer->info);
|
|
//if (result != VK_SUCCESS)
|
|
//{
|
|
//Printfln("vmaCreateBuffer failure: %s", vVkResultStr(result));
|
|
//}
|
|
|
|
return success;
|
|
}
|
|
|
|
static b32 rBufferUpload(rRenderBuffer **buffers, rawptr *ptrs, u32 count, u32 thr_ix)
|
|
{
|
|
// TODO: replace
|
|
/*
|
|
Assert(buffers, "rBufferUpload: buffer must not be null");
|
|
Assert(ptrs, "rBufferUpload: ptr must not be null");
|
|
|
|
b32 success = true;
|
|
|
|
VkCommandBuffer cmd = renderer.vk.imm.cmds[thr_ix];
|
|
VkFence fence = renderer.vk.imm.fences[thr_ix];
|
|
VkDevice device = v_Renderer.handles.device;
|
|
VkQueue queue = renderer.vk.queues.transfer_queue;
|
|
VmaAllocator alloc = v_Renderer.handles.vma_alloc;
|
|
rawptr mapped_buffers[16] = {0};
|
|
rRenderBuffer staging_buffers[16] = {0};
|
|
|
|
u32 copy_count = 0;
|
|
|
|
b32 imm_started = success = vImmSubmitBegin(device, fence, cmd);
|
|
for (u32 i = 0; i < count && success; i++)
|
|
{
|
|
b32 host_visible = buffers[i]->type & HOST_VISIBLE_BUFFERS;
|
|
if (host_visible)
|
|
{
|
|
vmaMapMemory(alloc, buffers[i]->alloc, &mapped_buffers[i]);
|
|
MemCpy(mapped_buffers[i], ptrs[i], buffers[i]->size);
|
|
}
|
|
else
|
|
{
|
|
staging_buffers[copy_count].type = rRBT_STAGING;
|
|
staging_buffers[copy_count].size = buffers[i]->size;
|
|
|
|
//success = rBufferCreate(&staging_buffers[i]);
|
|
|
|
if (success)
|
|
{
|
|
vmaMapMemory(alloc, staging_buffers[i].alloc, &mapped_buffers[i]);
|
|
MemCpy(mapped_buffers[i], ptrs[i], staging_buffers[i].size);
|
|
|
|
VkBufferCopy buffer_copy = { .size = (VkDeviceSize)buffers[i]->size };
|
|
vkCmdCopyBuffer(cmd, staging_buffers[i].buffer, buffers[i]->buffer, 1, &buffer_copy);
|
|
|
|
copy_count += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
vImmSubmitFinish(device, fence, cmd, queue);
|
|
vkWaitForFences(device, 1, &fence, VK_TRUE, 999999999);
|
|
|
|
for (u32 i = 0; i < copy_count; i++)
|
|
{
|
|
vmaUnmapMemory(alloc, staging_buffers[i].alloc);
|
|
vmaDestroyBuffer(alloc, staging_buffers[i].buffer, staging_buffers[i].alloc);
|
|
}
|
|
*/
|
|
|
|
return false;
|
|
}
|
|
|
|
static void rBufferCreateAndUpload(rRenderBuffer *buffer, rawptr ptr)
|
|
{
|
|
|
|
// TODO: replace
|
|
/*
|
|
TicketMutLock(&renderer.upload_queues[vDT_MATERIAL].ticket_mut);
|
|
|
|
u32 job_idx = JobQueueAdd(&renderer.upload_queues[vDT_MATERIAL].job_queue, 1);
|
|
renderer.upload_queues[vDT_MATERIAL].queued_buffers[job_idx] = buffer;
|
|
renderer.upload_queues[vDT_MATERIAL].data[job_idx] = ptr;
|
|
|
|
TicketMutUnlock(&renderer.upload_queues[vDT_MATERIAL].ticket_mut);
|
|
*/
|
|
|
|
vLoaderWake();
|
|
}
|
|
|
|
static rDescHandle rTextureCreateAndUpload(TextureAsset asset_id)
|
|
{
|
|
rDescHandle handle = 0;
|
|
|
|
// TODO: replace it
|
|
/*
|
|
vAssetInfo *info = vDescHandleSearch(vDT_SAMPLED_IMAGE, asset_id);
|
|
if (info == NULL)
|
|
{
|
|
Asset asset = apLoadTexture(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;
|
|
|
|
TicketMutLock(&renderer.upload_queues[vDT_SAMPLED_IMAGE].ticket_mut);
|
|
|
|
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;
|
|
|
|
handle = vDescHandlePop(vDT_SAMPLED_IMAGE);
|
|
|
|
TicketMutUnlock(&renderer.upload_queues[vDT_SAMPLED_IMAGE].ticket_mut);
|
|
|
|
vLoaderWake();
|
|
}
|
|
else
|
|
{
|
|
handle = info->handle;
|
|
}
|
|
*/
|
|
|
|
return handle;
|
|
}
|
|
|
|
static void rBufferFree(rRenderBuffer *buffers, u32 buffer_count)
|
|
{
|
|
VkDevice device = v_Renderer.handles.device;
|
|
VmaAllocator alloc = v_Renderer.handles.vma_alloc;
|
|
u32 frame_index = vFrameIndex();
|
|
|
|
|
|
// TODO: replace it
|
|
//for (u32 i = 0; i < buffer_count; i++)
|
|
//{
|
|
// *buf_count += 1;
|
|
//}
|
|
}
|
|
|
|
static void rBufferBindVertex(rRenderBuffer *buffer)
|
|
{
|
|
Assert(buffer && buffer->type == rRBT_VERTEX, "rBufferBindVertex: invalid buffer provided");
|
|
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
VkDeviceSize offsets = 0;
|
|
|
|
vkCmdBindVertexBuffers(cmd, 0, 1, &buffer->buffer, &offsets);
|
|
}
|
|
|
|
static void rBufferBindIndex(rRenderBuffer *buffer)
|
|
{
|
|
Assert(buffer && buffer->type == rRBT_INDEX, "rBufferBindIndex: invalid buffer provided");
|
|
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
|
|
vkCmdBindIndexBuffer(cmd, buffer->buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
}
|
|
|
|
static rAssetHandle rTextureLoad(TextureAsset asset_id)
|
|
{
|
|
rAssetHandle handle = 0;
|
|
|
|
return handle;
|
|
}
|
|
|
|
static void WaitForBufferQueue()
|
|
{
|
|
for (u32 i = 0; i < vDT_MAX; i++)
|
|
{
|
|
// TODO: replace
|
|
/*
|
|
while (!JobQueueCompleted(&renderer.upload_queues[vDT_MATERIAL].job_queue))
|
|
{
|
|
if (v_Renderer.state.renderer.height > 0)
|
|
vLoaderWake();
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
static void rBufferQueueReset()
|
|
{
|
|
for (u32 i = 0; i < vDT_MAX; i++)
|
|
{
|
|
// TODO: replace
|
|
//JobQueueReset(&renderer.upload_queues[i].job_queue);
|
|
}
|
|
}
|
|
|
|
static rawptr rBufferGUIVertMapping()
|
|
{
|
|
return v_Renderer.buffers.gui_vert.ptr;
|
|
}
|
|
|
|
static rawptr rBufferGUIIdxMapping()
|
|
{
|
|
return v_Renderer.buffers.gui_idx.ptr;
|
|
}
|
|
|
|
static void rBufferBindGUIVertex()
|
|
{
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
VkDeviceSize offsets = 0;
|
|
VkBuffer buffer = v_Renderer.buffers.gui_vert.alloc.buffer;
|
|
|
|
vkCmdBindVertexBuffers(cmd, 0, 1, &buffer, &offsets);
|
|
}
|
|
|
|
static void rBufferBindGUIIndex()
|
|
{
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
VkBuffer buffer = v_Renderer.buffers.gui_idx.alloc.buffer;
|
|
|
|
vkCmdBindIndexBuffer(cmd, buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
}
|
|
|
|
// ::Vulkan::Renderer::Buffers::Functions::End::
|
|
|
|
|
|
|
|
// ::Vulkan::Renderer::Uniforms::Functions::Start::
|
|
// ::Vulkan::Renderer::PushConstants::Functions::Start::
|
|
|
|
static void rViewportSize(Vec2 *size)
|
|
{
|
|
size->x = (f32)v_Renderer.state.swapchain.extent.width;
|
|
size->y = (f32)v_Renderer.state.swapchain.extent.height;
|
|
}
|
|
|
|
static void rGlobalUniformSet(rShaderGlobals *globals)
|
|
{
|
|
|
|
}
|
|
|
|
static void rPushConstantsSet(rPushConst *pc)
|
|
{
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
|
|
vkCmdPushConstants(cmd,
|
|
v_Renderer.handles.pipeline_layout,
|
|
VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT|VK_SHADER_STAGE_COMPUTE_BIT,
|
|
0,
|
|
sizeof(rPushConst),
|
|
pc);
|
|
}
|
|
|
|
// ::Vulkan::Renderer::Uniforms::Functions::End::
|
|
// ::Vulkan::Renderer::PushConstants::Functions::End::
|
|
|
|
|
|
|
|
// ::Vulkan::Renderer::Config::Functions::Start::
|
|
|
|
static void rResolutionSet(u32 x, u32 y)
|
|
{
|
|
v_Renderer.state.renderer.width = x;
|
|
v_Renderer.state.renderer.height = y;
|
|
}
|
|
|
|
static void rThreadCountSet(u32 n)
|
|
{
|
|
v_Renderer.async.count = n;
|
|
}
|
|
|
|
// ::Vulkan::Renderer::Config::Functions::End::
|
|
|
|
|
|
|
|
// ::Vulkan::Renderer::Rendering::Functions::Start::
|
|
|
|
b32 rFrameBegin()
|
|
{
|
|
b32 success = true;
|
|
VkResult result;
|
|
|
|
VkDevice device = v_Renderer.handles.device;
|
|
VkSwapchainKHR swapchain = v_Renderer.handles.swapchain;
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
VkFence fence = vFrameRenderFence();
|
|
VkSemaphore sc_sem = vFrameSwapSem();
|
|
VkSemaphore rndr_sem = vFrameRenderSem();
|
|
|
|
// TODO(MA): make this work with VK_PRESENT_MODE_MAILBOX_KHR and remove assignment of present mode to FIFO
|
|
result = vkWaitForFences(device, 1, &fence, VK_TRUE, 1000000000);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkWaitForFences failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
// TODO: replace
|
|
/*
|
|
u32 *buf_count = vFrameBufferCount();
|
|
if (*buf_count > 0)
|
|
{
|
|
rRenderBuffer *buffers = vFrameRenderBuffers();
|
|
for (u32 i = 0; i < *buf_count; i++)
|
|
vmaDestroyBuffer(v_Renderer.handles.vma_alloc, buffers[i].buffer, buffers[i].alloc);
|
|
*buf_count = 0;
|
|
}
|
|
*/
|
|
|
|
result = vkResetFences(device, 1, &fence);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkResetFences failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
result = vkAcquireNextImageKHR(device, swapchain, 1000000000, sc_sem, 0, &v_Renderer.state.vk.image_idx);
|
|
if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
|
vSwapchainResize();
|
|
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
|
{
|
|
Printf("vkAcquireNextImageKHR failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
result = vkResetCommandBuffer(cmd, 0);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkResetCommandBuffer failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (success)
|
|
{
|
|
VkCommandBufferBeginInfo cmd_info = {
|
|
.sType = STYPE(COMMAND_BUFFER_BEGIN_INFO),
|
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
|
};
|
|
|
|
result = vkBeginCommandBuffer(cmd, &cmd_info);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkBeginCommandBuffer failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
|
|
if (success)
|
|
vRenderingBegin();
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
b32 rFrameFinish()
|
|
{
|
|
b32 success = true;
|
|
VkResult result;
|
|
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
VkSemaphore sc_sem = vFrameSwapSem();
|
|
VkSemaphore rndr_sem = vFrameRenderSem();
|
|
VkFence fence = vFrameRenderFence();
|
|
VkImage curr_img = vFrameImage();
|
|
|
|
vkCmdEndRendering(cmd);
|
|
|
|
vImageTransition(cmd, &v_Renderer.images.draw.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
|
|
|
VkExtent2D extent = {
|
|
.width = v_Renderer.state.swapchain.extent.width,
|
|
.height = v_Renderer.state.swapchain.extent.height,
|
|
};
|
|
|
|
vImageCopyToImage(cmd, v_Renderer.images.draw.image.image, curr_img, extent, extent);
|
|
|
|
vImageTransitionLayout(cmd, curr_img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
|
|
|
result = vkEndCommandBuffer(cmd);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkEndCommandBuffer failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
VkCommandBufferSubmitInfo cmd_info = {
|
|
.sType = STYPE(COMMAND_BUFFER_SUBMIT_INFO),
|
|
.commandBuffer = cmd,
|
|
};
|
|
|
|
VkSemaphoreSubmitInfo wait_info = {
|
|
.sType = STYPE(SEMAPHORE_SUBMIT_INFO),
|
|
.semaphore = sc_sem,
|
|
.stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
.value = 1,
|
|
};
|
|
|
|
VkSemaphoreSubmitInfo signal_info = {
|
|
.sType = STYPE(SEMAPHORE_SUBMIT_INFO),
|
|
.semaphore = rndr_sem,
|
|
.stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
|
|
.value = 1,
|
|
};
|
|
|
|
VkSubmitInfo2 submit_info = {
|
|
.sType = STYPE(SUBMIT_INFO_2),
|
|
.waitSemaphoreInfoCount = 1,
|
|
.pWaitSemaphoreInfos = &wait_info,
|
|
.signalSemaphoreInfoCount = 1,
|
|
.pSignalSemaphoreInfos = &signal_info,
|
|
.commandBufferInfoCount = 1,
|
|
.pCommandBufferInfos = &cmd_info,
|
|
};
|
|
|
|
result = vkQueueSubmit2(v_Renderer.handles.gfx_queue, 1, &submit_info, fence);
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkQueueSubmit2 failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
VkPresentInfoKHR present_info = {
|
|
.sType = STYPE(PRESENT_INFO_KHR),
|
|
.pSwapchains = &v_Renderer.handles.swapchain,
|
|
.swapchainCount = 1,
|
|
.pWaitSemaphores = &rndr_sem,
|
|
.waitSemaphoreCount = 1,
|
|
.pImageIndices = &v_Renderer.state.vk.image_idx,
|
|
};
|
|
|
|
result = vkQueuePresentKHR(v_Renderer.handles.gfx_queue, &present_info);
|
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
|
|
vSwapchainResize();
|
|
else if (result != VK_SUCCESS)
|
|
{
|
|
Printf("vkQueuePresentKHR failure: %s", vVkResultStr(result));
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
v_Renderer.state.renderer.frame_count += 1;
|
|
|
|
return success;
|
|
}
|
|
|
|
static void rDrawIndexed(u32 index_count, u32 instance_count)
|
|
{
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
|
|
vkCmdDrawIndexed(cmd, index_count, instance_count, 0, 0, 0);
|
|
}
|
|
|
|
static void rPipelineBind(rPipelineHandle handle, rPipelineType type)
|
|
{
|
|
VkCommandBuffer cmd = vFrameCmdBuf();
|
|
|
|
vkCmdBindPipeline(cmd, (VkPipelineBindPoint)type, v_Renderer.handles.pipelines[handle]);
|
|
|
|
VkViewport viewport = {
|
|
.width = (f32)v_Renderer.state.swapchain.extent.width,
|
|
.height = (f32)v_Renderer.state.swapchain.extent.height,
|
|
.maxDepth = 1.0,
|
|
};
|
|
|
|
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
|
|
|
VkRect2D scissor = {
|
|
.extent = {
|
|
.width = v_Renderer.state.swapchain.extent.width,
|
|
.height = v_Renderer.state.swapchain.extent.height,
|
|
},
|
|
};
|
|
|
|
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
|
}
|
|
|
|
// ::Vulkan::Renderer::Rendering::Functions::End::
|