summaryrefslogtreecommitdiff
path: root/src/window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.cpp')
-rw-r--r--src/window.cpp427
1 files changed, 388 insertions, 39 deletions
diff --git a/src/window.cpp b/src/window.cpp
index 0c7f281..773c767 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -76,8 +76,11 @@ VkSampleCountFlagBits global_sample_count;
struct pkvk_queued_actions {
struct pkvk_queued_actions_delete {
+ pk_arr_t<VkImageView> image_view{};
+ pk_arr_t<VkImage> image{};
pk_arr_t<VkBuffer> buffers{};
pk_arr_t<VkDeviceMemory> memory{};
+ pk_arr_t<VkDescriptorPool> descriptor_pool{};
} destroy;
} pkvk_actn_queue;
@@ -465,6 +468,7 @@ void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_dat
VkDeviceSize offsets[PKVK_TEXTURE_UPLOAD_ARR_MAX_LENGTH];
VkDeviceSize size = 0;
VkDeviceSize offset = 0;
+ VkDeviceSize padding = 0;
memset(&offsets, 0, sizeof(offsets));
@@ -551,7 +555,10 @@ void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_dat
*/
for (i = 0; i < data->n_textures; ++i) {
- assert(data->texture_assets[i]->type == PKE_ASSET_TYPE_TEXTURE);
+ if(data->texture_assets[i]->type != PKE_ASSET_TYPE_TEXTURE) {
+ fprintf(stderr, "[pkvk_texture_upload] Expected all passed assets to be textures, got: %hhu for idx#%i.", static_cast<AssetType_T>(data->texture_assets[i]->type), i);
+ return;
+ }
imageCreateInfo.extent.width = data->texture_assets[i]->details.texture.width;
imageCreateInfo.extent.height = data->texture_assets[i]->details.texture.height;
@@ -626,7 +633,8 @@ void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_dat
vkImageMemoryBarriers[i].image = out->images[i];
offset += size;
- offset += (combined_mem_reqs.alignment - (size % combined_mem_reqs.alignment)) % combined_mem_reqs.alignment;
+ padding = (combined_mem_reqs.alignment - (size % combined_mem_reqs.alignment)) % combined_mem_reqs.alignment;
+ offset += padding;
}
/*
@@ -712,6 +720,276 @@ void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_dat
PKVK_EndBuffer(tmpBufferDetails);
}
+void pkvk_texture_upload_array(pkvk_texture_upload_data *data, pkvk_texture_upload_data_out *out) {
+ uint8_t i;
+ int txtr_x, txtr_y, txtr_chan;
+ VkResult vkResult{};
+ VkImage tmpImage{};
+ PKVK_TmpBufferDetails tmpBufferDetails{};
+ VkImageViewCreateInfo vkImageViewCreateInfo{};
+ VkImageCreateInfo imageCreateInfo{};
+ VkMemoryRequirements combined_mem_reqs{};
+
+ VkBufferImageCopy2 vkBufferImageCopies[PKVK_TEXTURE_UPLOAD_ARR_MAX_LENGTH];
+ VkCopyBufferToImageInfo2 copy_buffer_to_image_2{};
+ VkImageMemoryBarrier vkImageMemoryBarrier{};
+ VkDeviceSize size = 0;
+ VkDeviceSize offset = 0;
+
+ vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ vkImageViewCreateInfo.pNext = VK_NULL_HANDLE;
+ vkImageViewCreateInfo.flags = 0;
+ vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkImageViewCreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
+ vkImageViewCreateInfo.components = VkComponentMapping {
+ .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+ };
+ vkImageViewCreateInfo.subresourceRange = VkImageSubresourceRange {
+ .aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0u,
+ // TODO MipMap
+ .levelCount = 1u,
+ .baseArrayLayer = 0u,
+ .layerCount = (uint32_t)data->n_textures,
+ };
+
+ imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageCreateInfo.pNext = VK_NULL_HANDLE;
+ imageCreateInfo.flags = 0;
+ imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageCreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
+ imageCreateInfo.extent.width = data->texture_assets[0]->details.texture.width;
+ imageCreateInfo.extent.height = data->texture_assets[0]->details.texture.height;
+ imageCreateInfo.extent.depth = 1;
+ imageCreateInfo.mipLevels = 1;
+ imageCreateInfo.arrayLayers = data->n_textures;
+ imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ imageCreateInfo.queueFamilyIndexCount = 0;
+ imageCreateInfo.pQueueFamilyIndices = VK_NULL_HANDLE;
+ imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ imageCreateInfo.extent = {
+ .width = data->texture_assets[0]->details.texture.width,
+ .height = data->texture_assets[0]->details.texture.height,
+ .depth = 1,
+ };
+
+ vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ vkImageMemoryBarrier.pNext = VK_NULL_HANDLE;
+ vkImageMemoryBarrier.srcAccessMask = {};
+ vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.subresourceRange = vkImageViewCreateInfo.subresourceRange;
+
+ for (i = 0; i < data->n_textures; ++i) {
+ vkBufferImageCopies[i].sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2;
+ vkBufferImageCopies[i].pNext = VK_NULL_HANDLE;
+ vkBufferImageCopies[i].bufferOffset = 0;
+ vkBufferImageCopies[i].bufferRowLength = data->texture_assets[0]->details.texture.width;
+ vkBufferImageCopies[i].bufferImageHeight = data->texture_assets[0]->details.texture.width;
+ vkBufferImageCopies[i].bufferRowLength = 0;
+ vkBufferImageCopies[i].bufferImageHeight = 0;
+ vkBufferImageCopies[i].imageSubresource = VkImageSubresourceLayers {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = i,
+ .layerCount = 1,
+ };
+ vkBufferImageCopies[i].imageOffset = VkOffset3D {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ };
+ vkBufferImageCopies[i].imageExtent = VkExtent3D {
+ .width = data->texture_assets[0]->details.texture.width,
+ .height = data->texture_assets[0]->details.texture.height,
+ .depth = 1,
+ };
+ }
+
+ copy_buffer_to_image_2.sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2;
+ copy_buffer_to_image_2.pNext = VK_NULL_HANDLE;
+ copy_buffer_to_image_2.srcBuffer = VK_NULL_HANDLE;
+ copy_buffer_to_image_2.dstImage = VK_NULL_HANDLE;
+ copy_buffer_to_image_2.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ copy_buffer_to_image_2.regionCount = (uint32_t)data->n_textures;
+ copy_buffer_to_image_2.pRegions = vkBufferImageCopies;
+
+ /*
+ * get memory requirements
+ */
+ for (i = 0; i < data->n_textures; ++i) {
+ if(data->texture_assets[i]->type != PKE_ASSET_TYPE_TEXTURE) {
+ fprintf(stderr, "[pkvk_texture_upload] Expected all passed assets to be textures, got: %hhu for idx#%i.", static_cast<AssetType_T>(data->texture_assets[i]->type), i);
+ return;
+ }
+ if (data->texture_assets[i]->details.texture.width != data->texture_assets[0]->details.texture.width
+ || data->texture_assets[i]->details.texture.height != data->texture_assets[0]->details.texture.height) {
+ fprintf(stderr, "[pkvk_texture_upload] Requested array but the dimensions of texture (idx %i) did not match.", i);
+ return;
+ }
+ }
+
+ vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &tmpImage);
+ assert(vkResult == VK_SUCCESS);
+ vkGetImageMemoryRequirements(vkDevice, tmpImage, &combined_mem_reqs);
+ vkDestroyImage(vkDevice, tmpImage, vkAllocator);
+
+ /*
+ * memory allocation
+ */
+
+ VkMemoryAllocateInfo vkMemoryAllocateInfo;
+ vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ vkMemoryAllocateInfo.pNext = nullptr;
+ vkMemoryAllocateInfo.allocationSize = combined_mem_reqs.size;
+ vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_mem_reqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
+ if (vkMemoryAllocateInfo.memoryTypeIndex == 0) {
+ vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_mem_reqs.memoryTypeBits, 0);
+ }
+ vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &out->device_memory);
+
+ /*
+ * buffer setup
+ */
+
+ char *temp_buffer = (char *)malloc(combined_mem_reqs.size);
+
+ // copy data to temp buffer
+ // 2025-08-06 - JCB - PERF TODO actually test performance
+ // It's possible that copying these to a temporary buffer is a performance loss.
+ // The idea here is to separate this number-crunching from the buffer recording.
+ // If this texture upload function ends up being a bottleneck here's a few suggestions:
+ // - split stbi work to separate threads (likely biggest impact)
+ // - reduce # of data-copies (copy straight to the vulkan buffer instead of intermediary)
+ for (i = 0; i < data->n_textures; ++i) {
+
+ vkBufferImageCopies[i].bufferOffset = offset;
+
+ /* run texture data through stbi, putting it in the VkFormat we desire, & copy */
+ stbi_uc *txtr_bytes = stbi_load_from_memory((unsigned char*)data->texture_assets[i]->ptr, data->texture_assets[i]->size, &txtr_x, &txtr_y, &txtr_chan, 4);
+ assert(txtr_bytes != nullptr);
+ assert(txtr_chan == 4);
+
+ size = sizeof(uint8_t) * txtr_x * txtr_y * txtr_chan;
+ memcpy(temp_buffer + offset, txtr_bytes, size);
+
+ free(txtr_bytes);
+
+ offset += size;
+ }
+
+ // create image
+
+ vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &out->images[0]);
+ assert(vkResult == VK_SUCCESS);
+ vkResult = vkBindImageMemory(vkDevice, out->images[0], out->device_memory, 0);
+ assert(vkResult == VK_SUCCESS);
+
+ // create image view
+
+ vkImageViewCreateInfo.image = out->images[0];
+ vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &out->image_views[0]);
+ assert(vkResult == VK_SUCCESS);
+
+ // set up image copy parameters
+ vkImageMemoryBarrier.image = out->images[0];
+
+ /*
+ * transition layout & copy to buffer
+ */
+
+ PKVK_BeginBuffer(transferFamilyIndex, combined_mem_reqs.size, tmpBufferDetails);
+
+ // copy data to vulkan buffer
+ memcpy(tmpBufferDetails.deviceData, temp_buffer, combined_mem_reqs.size);
+ free(temp_buffer);
+
+ VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
+ vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ vkCommandBufferBeginInfo.pNext = nullptr;
+ vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
+ vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo);
+
+ vkCmdPipelineBarrier(tmpBufferDetails.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier);
+
+ copy_buffer_to_image_2.dstImage = out->images[0];
+ copy_buffer_to_image_2.srcBuffer = tmpBufferDetails.buffer;
+ vkCmdCopyBufferToImage2(tmpBufferDetails.cmdBuffer, &copy_buffer_to_image_2);
+
+ vkEndCommandBuffer(tmpBufferDetails.cmdBuffer);
+
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr);
+ vkQueueWaitIdle(tmpBufferDetails.queue);
+ vkResetCommandBuffer(tmpBufferDetails.cmdBuffer, 0);
+
+ PKVK_EndBuffer(tmpBufferDetails);
+
+ // update command buffer data
+ vkImageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ tmpBufferDetails = {};
+ PKVK_BeginBuffer(graphicsFamilyIndex, 0, tmpBufferDetails);
+ {
+
+ VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
+ vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ vkCommandBufferBeginInfo.pNext = nullptr;
+ vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
+
+ vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo);
+
+ vkCmdPipelineBarrier(tmpBufferDetails.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier);
+
+ vkEndCommandBuffer(tmpBufferDetails.cmdBuffer);
+
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr);
+ vkQueueWaitIdle(tmpBufferDetails.queue);
+ }
+ PKVK_EndBuffer(tmpBufferDetails);
+}
+
+void pkvk_queue_vk_image_view_destroy(VkImageView image_view) {
+ pk_arr_append_t(&pkvk_actn_queue.destroy.image_view, image_view);
+}
+
+void pkvk_queue_vk_image_destroy(VkImage image) {
+ pk_arr_append_t(&pkvk_actn_queue.destroy.image, image);
+}
+
void pkvk_queue_vk_buffer_destroy(VkBuffer buffer) {
pk_arr_append_t(&pkvk_actn_queue.destroy.buffers, buffer);
}
@@ -720,6 +998,10 @@ void pkvk_queue_vk_memory_free(VkDeviceMemory memory) {
pk_arr_append_t(&pkvk_actn_queue.destroy.memory, memory);
}
+void pkvk_queue_vk_descriptor_pool_destroy(VkDescriptorPool descriptor_pool) {
+ pk_arr_append_t(&pkvk_actn_queue.destroy.descriptor_pool, descriptor_pool);
+}
+
unsigned int FindQueueFamilyIndex(VkPhysicalDevice device, char hasPresentSupport = -1, VkQueueFlagBits includeBits = (VkQueueFlagBits)0U, VkQueueFlagBits excludeBits = (VkQueueFlagBits)0U) {
if (hasPresentSupport == -1 && includeBits == 0 && excludeBits == 0) {
@@ -1954,8 +2236,7 @@ void CreateGraphicsPipelines() {
vkDescriptorSetLayoutCreateInfo.pBindings = VK_NULL_HANDLE;
vkResult = vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &pkePipelines.descr_layouts.named.base);
assert(vkResult == VK_SUCCESS);
- assert(pkePipelines.descr_layouts.named.txtr != VK_NULL_HANDLE);
-
+ assert(pkePipelines.descr_layouts.named.base != VK_NULL_HANDLE);
VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
@@ -1987,6 +2268,7 @@ void CreateGraphicsPipelines() {
AssetHandle fragGlyphAssetHandle { AM_GetHandle(AssetKey{"pke_glyph_frg\0\0"})};
AssetHandle asset_handle_vert_ui_base { AM_GetHandle(AssetKey{"pke_ui_bs_vrt\0\0"})};
AssetHandle asset_handle_frag_ui_base { AM_GetHandle(AssetKey{"pke_ui_bs_frg\0\0"})};
+ AssetHandle asset_handle_frag_ui_txtr { AM_GetHandle(AssetKey{"pke_ui_txt_frg\0"})};
const long vertexBindingCount = 4;
long index = 0;
@@ -2189,7 +2471,7 @@ void CreateGraphicsPipelines() {
offset = 0;
const long vertexBindingCount_ui_base = 3;
VkVertexInputBindingDescription vertInputBD_ui_base[vertexBindingCount_ui_base];
- const long vertexAttrDescCount_ui_base = 10;
+ const long vertexAttrDescCount_ui_base = 11;
VkVertexInputAttributeDescription vertAttrDesc_ui_base[vertexAttrDescCount_ui_base];
VkPipelineVertexInputStateCreateInfo vkPipelineVertexInputStateCreateInfo_ui_base{vkPipelineVertexInputStateCreateInfo_txtr};
{
@@ -2213,7 +2495,7 @@ void CreateGraphicsPipelines() {
+ sizeof(glm::vec4) // in_background_color
+ sizeof(glm::vec2) // px_scale
+ sizeof(float) // depth
- + (sizeof(float) * 1) // padding
+ + sizeof(float) // texture_layer
+ 0;
vertInputBD_ui_base[index].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
// index += 1;
@@ -2258,18 +2540,25 @@ void CreateGraphicsPipelines() {
offset += sizeof(glm::vec4);
index += 1;
- // instance - in_sprite_region_min
+ // instance - px_scale
vertAttrDesc_ui_base[index].binding = 2;
vertAttrDesc_ui_base[index].format = VK_FORMAT_R32G32_SFLOAT;
vertAttrDesc_ui_base[index].offset = offset;
offset += sizeof(glm::vec2);
index += 1;
- // instance - in_sprite_region_min
+ // instance - depth
vertAttrDesc_ui_base[index].binding = 2;
vertAttrDesc_ui_base[index].format = VK_FORMAT_R32_SFLOAT;
vertAttrDesc_ui_base[index].offset = offset;
- // offset += sizeof(glm::vec2);
+ offset += sizeof(float);
+ index += 1;
+
+ // instance - texture_layer
+ vertAttrDesc_ui_base[index].binding = 2;
+ vertAttrDesc_ui_base[index].format = VK_FORMAT_R32_SFLOAT;
+ vertAttrDesc_ui_base[index].offset = offset;
+ // offset += sizeof(float);
// index += 1;
vkPipelineVertexInputStateCreateInfo_ui_base.vertexBindingDescriptionCount = vertexBindingCount_ui_base;
@@ -2408,8 +2697,15 @@ void CreateGraphicsPipelines() {
vkPipelineShaderStageCreateInfo_ui_base[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
vkPipelineShaderStageCreateInfo_ui_base[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
- VkGraphicsPipelineCreateInfo vkGraphicsPipelineCreateInfo[4];
- for (long i = 0; i < 4; ++i) {
+ /* pipelines
+ * 0: entity_standard
+ * 1: entity_wireframe
+ * 2: glyph
+ * 3: ui_base
+ * 4: ui_txtr
+ */
+ std::array<VkGraphicsPipelineCreateInfo, 5> vkGraphicsPipelineCreateInfo;
+ for (size_t i = 0; i < vkGraphicsPipelineCreateInfo.size(); ++i) {
vkGraphicsPipelineCreateInfo[i].sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
vkGraphicsPipelineCreateInfo[i].pNext = nullptr;
vkGraphicsPipelineCreateInfo[i].flags = {};
@@ -2417,6 +2713,7 @@ void CreateGraphicsPipelines() {
vkGraphicsPipelineCreateInfo[i].pInputAssemblyState = &vkPipelineInputAssemblyStateCreateInfo;
vkGraphicsPipelineCreateInfo[i].pTessellationState = nullptr;
vkGraphicsPipelineCreateInfo[i].pViewportState = &vkPipelineViewportStateCreateInfo;
+ vkGraphicsPipelineCreateInfo[i].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill;
vkGraphicsPipelineCreateInfo[i].pMultisampleState = &vkPipelineMultisampleStateCreateInfo;
vkGraphicsPipelineCreateInfo[i].pDepthStencilState = &vkPipelineDepthStencilStateCreateInfo;
vkGraphicsPipelineCreateInfo[i].pColorBlendState = &vkPipelineColorBlendStateCreateInfo;
@@ -2424,46 +2721,50 @@ void CreateGraphicsPipelines() {
vkGraphicsPipelineCreateInfo[i].subpass = 0;
vkGraphicsPipelineCreateInfo[i].basePipelineHandle = VK_NULL_HANDLE;
vkGraphicsPipelineCreateInfo[i].basePipelineIndex = {};
+ vkGraphicsPipelineCreateInfo[i].renderPass = VK_NULL_HANDLE; // dynamic rendering
}
vkGraphicsPipelineCreateInfo[0].layout = pkePipelines.pipe_layouts.named.ubo_txtr;
vkGraphicsPipelineCreateInfo[1].layout = pkePipelines.pipe_layouts.named.ubo_txtr;
vkGraphicsPipelineCreateInfo[2].layout = pkePipelines.pipe_layouts.named.txtr;
vkGraphicsPipelineCreateInfo[3].layout = pkePipelines.pipe_layouts.named.base;
-
- vkGraphicsPipelineCreateInfo[0].renderPass = VK_NULL_HANDLE; // dynamic rendering
- vkGraphicsPipelineCreateInfo[1].renderPass = VK_NULL_HANDLE; // dynamic rendering
- vkGraphicsPipelineCreateInfo[2].renderPass = VK_NULL_HANDLE; // dynamic rendering
- vkGraphicsPipelineCreateInfo[3].renderPass = VK_NULL_HANDLE; // dynamic rendering
+ vkGraphicsPipelineCreateInfo[4].layout = pkePipelines.pipe_layouts.named.txtr;
vkGraphicsPipelineCreateInfo[0].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr;
vkGraphicsPipelineCreateInfo[1].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr;
vkGraphicsPipelineCreateInfo[2].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_glyph;
vkGraphicsPipelineCreateInfo[3].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_ui_base;
+ vkGraphicsPipelineCreateInfo[4].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_ui_base;
- vkGraphicsPipelineCreateInfo[0].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill;
vkGraphicsPipelineCreateInfo[1].pRasterizationState = &vkPipelineRasterizationStateCreateInfoLine;
- vkGraphicsPipelineCreateInfo[2].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill;
- vkGraphicsPipelineCreateInfo[3].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill;
vkGraphicsPipelineCreateInfo[0].pStages = vkPipelineShaderStageCreateInfo_txtr;
vkGraphicsPipelineCreateInfo[1].pStages = vkPipelineShaderStageCreateInfo_txtr;
vkGraphicsPipelineCreateInfo[2].pStages = vkPipelineShaderStageCreateInfo_glyph;
vkGraphicsPipelineCreateInfo[3].pStages = vkPipelineShaderStageCreateInfo_ui_base;
+ vkGraphicsPipelineCreateInfo[4].pStages = vkPipelineShaderStageCreateInfo_ui_base;
// deffered shader creation
- vkPipelineShaderStageCreateInfo_txtr[0].module = UploadShader(vertShaderAssetHandle);
- vkPipelineShaderStageCreateInfo_txtr[1].module = UploadShader(textureFragShaderAssetHandle);
- vkPipelineShaderStageCreateInfo_glyph[0].module = UploadShader(vertGlyphAssetHandle);
- vkPipelineShaderStageCreateInfo_glyph[1].module = UploadShader(fragGlyphAssetHandle);
- vkPipelineShaderStageCreateInfo_ui_base[0].module = UploadShader(asset_handle_vert_ui_base);
- vkPipelineShaderStageCreateInfo_ui_base[1].module = UploadShader(asset_handle_frag_ui_base);
+ auto shader_module_3d_vert = UploadShader(vertShaderAssetHandle);
+ auto shader_module_3d_frag = UploadShader(textureFragShaderAssetHandle);
+ auto shader_module_glyph_vert = UploadShader(vertGlyphAssetHandle);
+ auto shader_module_glyph_frag = UploadShader(fragGlyphAssetHandle);
+ auto shader_module_ui_base_vert = UploadShader(asset_handle_vert_ui_base);
+ auto shader_module_ui_clr_frag = UploadShader(asset_handle_frag_ui_base);
+ auto shader_module_ui_txtr_frag = UploadShader(asset_handle_frag_ui_txtr);
+ vkPipelineShaderStageCreateInfo_txtr[0].module = shader_module_3d_vert;
+ vkPipelineShaderStageCreateInfo_txtr[1].module = shader_module_3d_frag;
+ vkPipelineShaderStageCreateInfo_glyph[0].module = shader_module_glyph_vert;
+ vkPipelineShaderStageCreateInfo_glyph[1].module = shader_module_glyph_frag;
+ vkPipelineShaderStageCreateInfo_ui_base[0].module = shader_module_ui_base_vert;
+ vkPipelineShaderStageCreateInfo_ui_base[1].module = shader_module_ui_clr_frag;
VkPipelineRenderingCreateInfo renderingInfo{};
vkGraphicsPipelineCreateInfo[0].pNext = &renderingInfo;
vkGraphicsPipelineCreateInfo[1].pNext = &renderingInfo;
vkGraphicsPipelineCreateInfo[2].pNext = &renderingInfo;
vkGraphicsPipelineCreateInfo[3].pNext = &renderingInfo;
+ vkGraphicsPipelineCreateInfo[4].pNext = &renderingInfo;
renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
std::array<VkFormat, 3> color_formats;
@@ -2489,16 +2790,25 @@ void CreateGraphicsPipelines() {
vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[3], vkAllocator, &pkePipelines.pipelines.named.ui_base);
assert(vkResult == VK_SUCCESS);
+
+ vkPipelineShaderStageCreateInfo_ui_base[1].module = shader_module_ui_txtr_frag;
+ vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[4], vkAllocator, &pkePipelines.pipelines.named.ui_txtr);
+ assert(vkResult == VK_SUCCESS);
+
assert(pkePipelines.pipelines.named.entity_standard != VK_NULL_HANDLE);
assert(pkePipelines.pipelines.named.entity_wireframe != VK_NULL_HANDLE);
assert(pkePipelines.pipelines.named.font_glyph != VK_NULL_HANDLE);
assert(pkePipelines.pipelines.named.ui_base != VK_NULL_HANDLE);
+ assert(pkePipelines.pipelines.named.ui_txtr != VK_NULL_HANDLE);
+
+ vkDestroyShaderModule(vkDevice, shader_module_ui_txtr_frag, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_ui_clr_frag, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_ui_base_vert, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_glyph_frag, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_glyph_vert, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_3d_frag, vkAllocator);
+ vkDestroyShaderModule(vkDevice, shader_module_3d_vert, vkAllocator);
- for (long i = 0; i < 2; ++i) {
- vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo_txtr[i].module, vkAllocator);
- vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo_glyph[i].module, vkAllocator);
- vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo_ui_base[i].module, vkAllocator);
- }
}
// debug texture
@@ -3107,6 +3417,7 @@ void pkvk_transition_image_layout(VkCommandBuffer command_buffer,
}
void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
+ uint32_t i, counter;
vkResetCommandBuffer(commandBuffer, 0);
VkCommandBufferBeginInfo beginInfo;
@@ -3336,15 +3647,30 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
// 2d overlay grbinds
- pke_ui_graphics_bindings *ui_gr = pke_ui_get_graphics_bindings();
- if (ui_gr != nullptr && ui_gr->instance_counter > 0)
+ const pke_ui_graphics_bindings &ui_gr = pke_ui_get_graphics_bindings();
+ pk_arr_t<pke_ui_graphics_bindings_texture> ui_gr_texture;
+ pke_ui_get_graphics_bindings_texture(&ui_gr_texture);
+ if (ui_gr.instance_counter > 0)
{
+ counter = 0;
+ for (i = 0; i < ui_gr_texture.next; ++i) {
+ counter += ui_gr_texture[i].instance_count;
+ }
+
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.ui_base);
- vkCmdBindIndexBuffer(commandBuffer, ui_gr->bd_index.buffer, ui_gr->bd_index.offsets[0], VK_INDEX_TYPE_UINT16);
- vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_vertex.firstBinding, ui_gr->bd_vertex.bindingCount, &ui_gr->bd_vertex.buffer, ui_gr->bd_vertex.offsets);
- vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_uv.firstBinding, ui_gr->bd_uv.bindingCount, &ui_gr->bd_uv.buffer, ui_gr->bd_uv.offsets);
- vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_instance.firstBinding, ui_gr->bd_instance.bindingCount, &ui_gr->bd_instance.buffer, ui_gr->bd_instance.offsets);
- vkCmdDrawIndexed(commandBuffer, ui_gr->index_count, ui_gr->instance_counter, 0, 0, 0);
+ vkCmdBindIndexBuffer(commandBuffer, ui_gr.bd_index.buffer, ui_gr.bd_index.offsets[0], VK_INDEX_TYPE_UINT16);
+ vkCmdBindVertexBuffers(commandBuffer, ui_gr.bd_vertex.firstBinding, ui_gr.bd_vertex.bindingCount, &ui_gr.bd_vertex.buffer, ui_gr.bd_vertex.offsets);
+ vkCmdBindVertexBuffers(commandBuffer, ui_gr.bd_uv.firstBinding, ui_gr.bd_uv.bindingCount, &ui_gr.bd_uv.buffer, ui_gr.bd_uv.offsets);
+ vkCmdBindVertexBuffers(commandBuffer, ui_gr.bd_instance.firstBinding, ui_gr.bd_instance.bindingCount, &ui_gr.bd_instance.buffer, ui_gr.bd_instance.offsets);
+ vkCmdDrawIndexed(commandBuffer, ui_gr.index_count, ui_gr.instance_counter - counter, 0, 0, 0);
+
+ if (counter > 0) {
+ vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.ui_txtr);
+ for (i = 0; i < ui_gr_texture.next; ++i) {
+ vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.txtr, 0, 1, &ui_gr_texture[i].descriptor_sets[imageIndex], 0, {});
+ vkCmdDrawIndexed(commandBuffer, ui_gr.index_count, ui_gr_texture[i].instance_count, 0, 0, ui_gr_texture[i].instance_offset);
+ }
+ }
}
vkCmdEndRendering(commandBuffer);
@@ -3790,6 +4116,7 @@ void CreateWindow(PKEWindowProperties wp) {
void DestroyWindow() {
if (vkInstance == nullptr) return;
+ window_tick_late(0.0);
if (pke_window_did_init_imgui == true) {
ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown();
@@ -3817,6 +4144,8 @@ void DestroyWindow() {
vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.font_glyph, vkAllocator);
if (pkePipelines.pipelines.named.ui_base != VK_NULL_HANDLE)
vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.ui_base, vkAllocator);
+ if (pkePipelines.pipelines.named.ui_txtr != VK_NULL_HANDLE)
+ vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.ui_txtr, vkAllocator);
if (pkePipelines.pipe_layouts.named.ubo_txtr != VK_NULL_HANDLE)
vkDestroyPipelineLayout(vkDevice, pkePipelines.pipe_layouts.named.ubo_txtr, vkAllocator);
@@ -3860,8 +4189,11 @@ void DestroyWindow() {
fprintf(stderr, "VkAllocator has '%u' outstanding allocations!", vulkanAllocs.next);
}
pk_arr_reset(&vulkanAllocs);
+ pk_arr_reset(&pkvk_actn_queue.destroy.image_view);
+ pk_arr_reset(&pkvk_actn_queue.destroy.image);
pk_arr_reset(&pkvk_actn_queue.destroy.buffers);
pk_arr_reset(&pkvk_actn_queue.destroy.memory);
+ pk_arr_reset(&pkvk_actn_queue.destroy.descriptor_pool);
// TODO there's un-freed vulkan stuff in the bucket
// comment this out to see it in the debug printout
pk_mem_bucket_destroy(MemBkt_Vulkan);
@@ -3932,6 +4264,7 @@ void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memRe
* Vulkan was emitting an error that the buffer was in use by a command buffer.
* Processing these actions after the graphics queue is idle solved that specific issue.
* This is a stop-gap measure so I can keep working and is not intended to be permanent.
+ * This might be okay for switching levels (maybe?)
* PERF
* This will block the main thread until all in-flight renders are no longer using any of the resources needed to render a scene.
* Move this to a fire-and-forget background thread that uses a memory barrier and a semaphore specifically for the target resource.
@@ -3939,18 +4272,34 @@ void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memRe
void window_tick_late(double delta) {
(void)delta;
uint32_t i;
- if (pkvk_actn_queue.destroy.buffers.next > 0
- || pkvk_actn_queue.destroy.memory.next > 0) {
+ if (pkvk_actn_queue.destroy.image_view.next > 0
+ || pkvk_actn_queue.destroy.image.next > 0
+ || pkvk_actn_queue.destroy.buffers.next > 0
+ || pkvk_actn_queue.destroy.memory.next > 0
+ || pkvk_actn_queue.destroy.descriptor_pool.next > 0
+ ) {
vkQueueWaitIdle(pkvk_shared.queue.graphics);
}
+ for (i = 0; i < pkvk_actn_queue.destroy.image_view.next; ++i) {
+ vkDestroyImageView(vkDevice, pkvk_actn_queue.destroy.image_view[i], vkAllocator);
+ }
+ for (i = 0; i < pkvk_actn_queue.destroy.image.next; ++i) {
+ vkDestroyImage(vkDevice, pkvk_actn_queue.destroy.image[i], vkAllocator);
+ }
for (i = 0; i < pkvk_actn_queue.destroy.buffers.next; ++i) {
vkDestroyBuffer(vkDevice, pkvk_actn_queue.destroy.buffers[i], vkAllocator);
}
for (i = 0; i < pkvk_actn_queue.destroy.memory.next; ++i) {
vkFreeMemory(vkDevice, pkvk_actn_queue.destroy.memory[i], vkAllocator);
}
+ for (i = 0; i < pkvk_actn_queue.destroy.descriptor_pool.next; ++i) {
+ vkDestroyDescriptorPool(vkDevice, pkvk_actn_queue.destroy.descriptor_pool[i], vkAllocator);
+ }
+ pk_arr_clear(&pkvk_actn_queue.destroy.image_view);
+ pk_arr_clear(&pkvk_actn_queue.destroy.image);
pk_arr_clear(&pkvk_actn_queue.destroy.buffers);
pk_arr_clear(&pkvk_actn_queue.destroy.memory);
+ pk_arr_clear(&pkvk_actn_queue.destroy.descriptor_pool);
}
void Render() {