UI overlay creation via create info structure with additional customization options
This commit is contained in:
parent
a789240567
commit
4e5d95c098
4 changed files with 127 additions and 93 deletions
|
|
@ -10,24 +10,12 @@
|
||||||
|
|
||||||
namespace vks
|
namespace vks
|
||||||
{
|
{
|
||||||
UIOverlay::UIOverlay(vks::VulkanDevice *vulkanDevice, VkQueue copyQueue, std::vector<VkFramebuffer> &framebuffers, VkFormat colorformat, VkFormat depthformat, uint32_t width, uint32_t height, std::vector<VkPipelineShaderStageCreateInfo> shaderstages)
|
UIOverlay::UIOverlay(vks::UIOverlayCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
this->device = vulkanDevice;
|
this->createInfo = createInfo;
|
||||||
this->copyQueue = copyQueue;
|
this->renderPass = createInfo.renderPass;
|
||||||
this->colorFormat = colorformat;
|
|
||||||
this->depthFormat = depthformat;
|
|
||||||
|
|
||||||
this->frameBuffers.resize(framebuffers.size());
|
#if defined(__ANDROID__)
|
||||||
for (uint32_t i = 0; i < framebuffers.size(); i++) {
|
|
||||||
this->frameBuffers[i] = &framebuffers[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
this->shaderStages = shaderstages;
|
|
||||||
|
|
||||||
this->width = width;
|
|
||||||
this->height = height;
|
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
|
||||||
if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_XXHIGH) {
|
if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_XXHIGH) {
|
||||||
scale = 3.5f;
|
scale = 3.5f;
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +25,7 @@ namespace vks
|
||||||
else if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_HIGH) {
|
else if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_HIGH) {
|
||||||
scale = 2.0f;
|
scale = 2.0f;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Init ImGui
|
// Init ImGui
|
||||||
// Color scheme
|
// Color scheme
|
||||||
|
|
@ -52,12 +40,14 @@ namespace vks
|
||||||
style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 0.0f, 0.0f, 0.8f);
|
style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 0.0f, 0.0f, 0.8f);
|
||||||
// Dimensions
|
// Dimensions
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.DisplaySize = ImVec2((float)(width), (float)(height));
|
io.DisplaySize = ImVec2((float)(createInfo.width), (float)(createInfo.height));
|
||||||
io.FontGlobalScale = scale;
|
io.FontGlobalScale = scale;
|
||||||
|
|
||||||
cmdBuffers.resize(framebuffers.size());
|
cmdBuffers.resize(createInfo.framebuffers.size());
|
||||||
prepareResources();
|
prepareResources();
|
||||||
prepareRenderPass();
|
if (createInfo.renderPass == VK_NULL_HANDLE) {
|
||||||
|
prepareRenderPass();
|
||||||
|
}
|
||||||
preparePipeline();
|
preparePipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,19 +56,21 @@ namespace vks
|
||||||
{
|
{
|
||||||
vertexBuffer.destroy();
|
vertexBuffer.destroy();
|
||||||
indexBuffer.destroy();
|
indexBuffer.destroy();
|
||||||
vkDestroyImageView(device->logicalDevice, fontView, nullptr);
|
vkDestroyImageView(createInfo.device->logicalDevice, fontView, nullptr);
|
||||||
vkDestroyImage(device->logicalDevice, fontImage, nullptr);
|
vkDestroyImage(createInfo.device->logicalDevice, fontImage, nullptr);
|
||||||
vkFreeMemory(device->logicalDevice, fontMemory, nullptr);
|
vkFreeMemory(createInfo.device->logicalDevice, fontMemory, nullptr);
|
||||||
vkDestroySampler(device->logicalDevice, sampler, nullptr);
|
vkDestroySampler(createInfo.device->logicalDevice, sampler, nullptr);
|
||||||
vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayout, nullptr);
|
vkDestroyDescriptorSetLayout(createInfo.device->logicalDevice, descriptorSetLayout, nullptr);
|
||||||
vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr);
|
vkDestroyDescriptorPool(createInfo.device->logicalDevice, descriptorPool, nullptr);
|
||||||
vkDestroyPipelineLayout(device->logicalDevice, pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(createInfo.device->logicalDevice, pipelineLayout, nullptr);
|
||||||
vkDestroyPipelineCache(device->logicalDevice, pipelineCache, nullptr);
|
vkDestroyPipelineCache(createInfo.device->logicalDevice, pipelineCache, nullptr);
|
||||||
vkDestroyPipeline(device->logicalDevice, pipeline, nullptr);
|
vkDestroyPipeline(createInfo.device->logicalDevice, pipeline, nullptr);
|
||||||
vkDestroyRenderPass(device->logicalDevice, renderPass, nullptr);
|
if (createInfo.renderPass == VK_NULL_HANDLE) {
|
||||||
vkFreeCommandBuffers(device->logicalDevice, commandPool, static_cast<uint32_t>(cmdBuffers.size()), cmdBuffers.data());
|
vkDestroyRenderPass(createInfo.device->logicalDevice, renderPass, nullptr);
|
||||||
vkDestroyCommandPool(device->logicalDevice, commandPool, nullptr);
|
}
|
||||||
vkDestroyFence(device->logicalDevice, fence, nullptr);
|
vkFreeCommandBuffers(createInfo.device->logicalDevice, commandPool, static_cast<uint32_t>(cmdBuffers.size()), cmdBuffers.data());
|
||||||
|
vkDestroyCommandPool(createInfo.device->logicalDevice, commandPool, nullptr);
|
||||||
|
vkDestroyFence(createInfo.device->logicalDevice, fence, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prepare all vulkan resources required to render the UI overlay */
|
/** Prepare all vulkan resources required to render the UI overlay */
|
||||||
|
|
@ -106,14 +98,14 @@ namespace vks
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageInfo, nullptr, &fontImage));
|
VK_CHECK_RESULT(vkCreateImage(createInfo.device->logicalDevice, &imageInfo, nullptr, &fontImage));
|
||||||
VkMemoryRequirements memReqs;
|
VkMemoryRequirements memReqs;
|
||||||
vkGetImageMemoryRequirements(device->logicalDevice, fontImage, &memReqs);
|
vkGetImageMemoryRequirements(createInfo.device->logicalDevice, fontImage, &memReqs);
|
||||||
VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
|
VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
|
||||||
memAllocInfo.allocationSize = memReqs.size;
|
memAllocInfo.allocationSize = memReqs.size;
|
||||||
memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
memAllocInfo.memoryTypeIndex = createInfo.device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &fontMemory));
|
VK_CHECK_RESULT(vkAllocateMemory(createInfo.device->logicalDevice, &memAllocInfo, nullptr, &fontMemory));
|
||||||
VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, fontImage, fontMemory, 0));
|
VK_CHECK_RESULT(vkBindImageMemory(createInfo.device->logicalDevice, fontImage, fontMemory, 0));
|
||||||
|
|
||||||
// Image view
|
// Image view
|
||||||
VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo();
|
VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo();
|
||||||
|
|
@ -123,12 +115,12 @@ namespace vks
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
viewInfo.subresourceRange.levelCount = 1;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewInfo, nullptr, &fontView));
|
VK_CHECK_RESULT(vkCreateImageView(createInfo.device->logicalDevice, &viewInfo, nullptr, &fontView));
|
||||||
|
|
||||||
// Staging buffers for font data upload
|
// Staging buffers for font data upload
|
||||||
vks::Buffer stagingBuffer;
|
vks::Buffer stagingBuffer;
|
||||||
|
|
||||||
VK_CHECK_RESULT(device->createBuffer(
|
VK_CHECK_RESULT(createInfo.device->createBuffer(
|
||||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
&stagingBuffer,
|
&stagingBuffer,
|
||||||
|
|
@ -139,7 +131,7 @@ namespace vks
|
||||||
stagingBuffer.unmap();
|
stagingBuffer.unmap();
|
||||||
|
|
||||||
// Copy buffer data to font image
|
// Copy buffer data to font image
|
||||||
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
VkCommandBuffer copyCmd = createInfo.device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||||
|
|
||||||
// Prepare for transfer
|
// Prepare for transfer
|
||||||
vks::tools::setImageLayout(
|
vks::tools::setImageLayout(
|
||||||
|
|
@ -178,7 +170,7 @@ namespace vks
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
|
||||||
device->flushCommandBuffer(copyCmd, copyQueue, true);
|
createInfo.device->flushCommandBuffer(copyCmd, createInfo.copyQueue, true);
|
||||||
|
|
||||||
stagingBuffer.destroy();
|
stagingBuffer.destroy();
|
||||||
|
|
||||||
|
|
@ -191,36 +183,36 @@ namespace vks
|
||||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||||
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||||
VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerInfo, nullptr, &sampler));
|
VK_CHECK_RESULT(vkCreateSampler(createInfo.device->logicalDevice, &samplerInfo, nullptr, &sampler));
|
||||||
|
|
||||||
// Command buffer
|
// Command buffer
|
||||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
cmdPoolInfo.queueFamilyIndex = device->queueFamilyIndices.graphics;
|
cmdPoolInfo.queueFamilyIndex = createInfo.device->queueFamilyIndices.graphics;
|
||||||
cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
VK_CHECK_RESULT(vkCreateCommandPool(device->logicalDevice, &cmdPoolInfo, nullptr, &commandPool));
|
VK_CHECK_RESULT(vkCreateCommandPool(createInfo.device->logicalDevice, &cmdPoolInfo, nullptr, &commandPool));
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
|
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
|
||||||
vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(cmdBuffers.size()));
|
vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(cmdBuffers.size()));
|
||||||
VK_CHECK_RESULT(vkAllocateCommandBuffers(device->logicalDevice, &cmdBufAllocateInfo, cmdBuffers.data()));
|
VK_CHECK_RESULT(vkAllocateCommandBuffers(createInfo.device->logicalDevice, &cmdBufAllocateInfo, cmdBuffers.data()));
|
||||||
|
|
||||||
// Descriptor pool
|
// Descriptor pool
|
||||||
std::vector<VkDescriptorPoolSize> poolSizes = {
|
std::vector<VkDescriptorPoolSize> poolSizes = {
|
||||||
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)
|
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)
|
||||||
};
|
};
|
||||||
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2);
|
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2);
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorPool(device->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool));
|
VK_CHECK_RESULT(vkCreateDescriptorPool(createInfo.device->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
// Descriptor set layout
|
// Descriptor set layout
|
||||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
||||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0),
|
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0),
|
||||||
};
|
};
|
||||||
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device->logicalDevice, &descriptorLayout, nullptr, &descriptorSetLayout));
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(createInfo.device->logicalDevice, &descriptorLayout, nullptr, &descriptorSetLayout));
|
||||||
|
|
||||||
// Descriptor set
|
// Descriptor set
|
||||||
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
|
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
|
||||||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &allocInfo, &descriptorSet));
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(createInfo.device->logicalDevice, &allocInfo, &descriptorSet));
|
||||||
VkDescriptorImageInfo fontDescriptor = vks::initializers::descriptorImageInfo(
|
VkDescriptorImageInfo fontDescriptor = vks::initializers::descriptorImageInfo(
|
||||||
sampler,
|
sampler,
|
||||||
fontView,
|
fontView,
|
||||||
|
|
@ -229,12 +221,12 @@ namespace vks
|
||||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
|
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
|
||||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &fontDescriptor)
|
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &fontDescriptor)
|
||||||
};
|
};
|
||||||
vkUpdateDescriptorSets(device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
|
vkUpdateDescriptorSets(createInfo.device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
|
||||||
|
|
||||||
// Pipeline cache
|
// Pipeline cache
|
||||||
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
|
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
|
||||||
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
||||||
VK_CHECK_RESULT(vkCreatePipelineCache(device->logicalDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache));
|
VK_CHECK_RESULT(vkCreatePipelineCache(createInfo.device->logicalDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache));
|
||||||
|
|
||||||
// Pipeline layout
|
// Pipeline layout
|
||||||
// Push constants for UI rendering parameters
|
// Push constants for UI rendering parameters
|
||||||
|
|
@ -242,11 +234,11 @@ namespace vks
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
||||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
||||||
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
VK_CHECK_RESULT(vkCreatePipelineLayout(createInfo.device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
|
|
||||||
// Command buffer execution fence
|
// Command buffer execution fence
|
||||||
VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo();
|
VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo();
|
||||||
VK_CHECK_RESULT(vkCreateFence(device->logicalDevice, &fenceCreateInfo, nullptr, &fence));
|
VK_CHECK_RESULT(vkCreateFence(createInfo.device->logicalDevice, &fenceCreateInfo, nullptr, &fence));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prepare a separate pipeline for the UI overlay rendering decoupled from the main application */
|
/** Prepare a separate pipeline for the UI overlay rendering decoupled from the main application */
|
||||||
|
|
@ -270,8 +262,20 @@ namespace vks
|
||||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
|
||||||
|
std::vector<VkPipelineColorBlendAttachmentState> blendStates(createInfo.attachmentCount);
|
||||||
|
for (uint32_t i = 0; i < createInfo.attachmentCount; i++) {
|
||||||
|
blendStates[i].blendEnable = VK_TRUE;
|
||||||
|
blendStates[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
blendStates[i].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
blendStates[i].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
blendStates[i].colorBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
blendStates[i].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
blendStates[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
|
blendStates[i].alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlendState =
|
VkPipelineColorBlendStateCreateInfo colorBlendState =
|
||||||
vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);
|
vks::initializers::pipelineColorBlendStateCreateInfo(static_cast<uint32_t>(blendStates.size()), blendStates.data());
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencilState =
|
VkPipelineDepthStencilStateCreateInfo depthStencilState =
|
||||||
vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL);
|
vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL);
|
||||||
|
|
@ -280,7 +284,7 @@ namespace vks
|
||||||
vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
|
vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampleState =
|
VkPipelineMultisampleStateCreateInfo multisampleState =
|
||||||
vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT);
|
vks::initializers::pipelineMultisampleStateCreateInfo(createInfo.rasterizationSamples);
|
||||||
|
|
||||||
std::vector<VkDynamicState> dynamicStateEnables = {
|
std::vector<VkDynamicState> dynamicStateEnables = {
|
||||||
VK_DYNAMIC_STATE_VIEWPORT,
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
|
@ -298,8 +302,8 @@ namespace vks
|
||||||
pipelineCreateInfo.pViewportState = &viewportState;
|
pipelineCreateInfo.pViewportState = &viewportState;
|
||||||
pipelineCreateInfo.pDepthStencilState = &depthStencilState;
|
pipelineCreateInfo.pDepthStencilState = &depthStencilState;
|
||||||
pipelineCreateInfo.pDynamicState = &dynamicState;
|
pipelineCreateInfo.pDynamicState = &dynamicState;
|
||||||
pipelineCreateInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
|
pipelineCreateInfo.stageCount = static_cast<uint32_t>(createInfo.shaders.size());
|
||||||
pipelineCreateInfo.pStages = shaderStages.data();
|
pipelineCreateInfo.pStages = createInfo.shaders.data();
|
||||||
|
|
||||||
// Vertex bindings an attributes based on ImGui vertex definition
|
// Vertex bindings an attributes based on ImGui vertex definition
|
||||||
std::vector<VkVertexInputBindingDescription> vertexInputBindings = {
|
std::vector<VkVertexInputBindingDescription> vertexInputBindings = {
|
||||||
|
|
@ -318,18 +322,17 @@ namespace vks
|
||||||
|
|
||||||
pipelineCreateInfo.pVertexInputState = &vertexInputState;
|
pipelineCreateInfo.pVertexInputState = &vertexInputState;
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(createInfo.device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prepare a separate render pass for rendering the text as an overlay */
|
/** Prepare a separate render pass for rendering the UI as an overlay */
|
||||||
void UIOverlay::prepareRenderPass()
|
void UIOverlay::prepareRenderPass()
|
||||||
{
|
{
|
||||||
VkAttachmentDescription attachments[2] = {};
|
VkAttachmentDescription attachments[2] = {};
|
||||||
|
|
||||||
// Color attachment
|
// Color attachment
|
||||||
attachments[0].format = colorFormat;
|
attachments[0].format = createInfo.colorformat;
|
||||||
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
|
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
// Don't clear the framebuffer (like the renderpass from the example does)
|
|
||||||
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
|
@ -338,7 +341,7 @@ namespace vks
|
||||||
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
// Depth attachment
|
// Depth attachment
|
||||||
attachments[1].format = depthFormat;
|
attachments[1].format = createInfo.depthformat;
|
||||||
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
|
@ -397,26 +400,25 @@ namespace vks
|
||||||
renderPassInfo.dependencyCount = 2;
|
renderPassInfo.dependencyCount = 2;
|
||||||
renderPassInfo.pDependencies = subpassDependencies;
|
renderPassInfo.pDependencies = subpassDependencies;
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateRenderPass(device->logicalDevice, &renderPassInfo, nullptr, &renderPass));
|
VK_CHECK_RESULT(vkCreateRenderPass(createInfo.device->logicalDevice, &renderPassInfo, nullptr, &renderPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update the command buffers to reflect text changes */
|
/** Update the command buffers to reflect UI changes */
|
||||||
void UIOverlay::updateCommandBuffers()
|
void UIOverlay::updateCommandBuffers()
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
|
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
|
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
|
||||||
renderPassBeginInfo.renderPass = renderPass;
|
renderPassBeginInfo.renderPass = renderPass;
|
||||||
renderPassBeginInfo.renderArea.extent.width = width;
|
renderPassBeginInfo.renderArea.extent.width = createInfo.width;
|
||||||
renderPassBeginInfo.renderArea.extent.height = height;
|
renderPassBeginInfo.renderArea.extent.height = createInfo.height;
|
||||||
// None of the attachments will be cleared
|
renderPassBeginInfo.clearValueCount = static_cast<uint32_t>(createInfo.clearValues.size());
|
||||||
renderPassBeginInfo.clearValueCount = 0;
|
renderPassBeginInfo.pClearValues = createInfo.clearValues.data();
|
||||||
renderPassBeginInfo.pClearValues = nullptr;
|
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
for (size_t i = 0; i < cmdBuffers.size(); ++i) {
|
for (size_t i = 0; i < cmdBuffers.size(); ++i) {
|
||||||
renderPassBeginInfo.framebuffer = *frameBuffers[i];
|
renderPassBeginInfo.framebuffer = createInfo.framebuffers[i];
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffers[i], &cmdBufInfo));
|
VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffers[i], &cmdBufInfo));
|
||||||
|
|
||||||
|
|
@ -464,6 +466,13 @@ namespace vks
|
||||||
vertexOffset += cmd_list->VtxBuffer.Size;
|
vertexOffset += cmd_list->VtxBuffer.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add empty subpasses if requested
|
||||||
|
if (createInfo.subpassCount > 1) {
|
||||||
|
for (uint32_t j = 1; j < createInfo.subpassCount; j++) {
|
||||||
|
vkCmdNextSubpass(cmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(cmdBuffers[i]);
|
vkCmdEndRenderPass(cmdBuffers[i]);
|
||||||
|
|
||||||
if (vks::debugmarker::active) {
|
if (vks::debugmarker::active) {
|
||||||
|
|
@ -492,7 +501,7 @@ namespace vks
|
||||||
if ((vertexBuffer.buffer == VK_NULL_HANDLE) || (vertexCount != imDrawData->TotalVtxCount)) {
|
if ((vertexBuffer.buffer == VK_NULL_HANDLE) || (vertexCount != imDrawData->TotalVtxCount)) {
|
||||||
vertexBuffer.unmap();
|
vertexBuffer.unmap();
|
||||||
vertexBuffer.destroy();
|
vertexBuffer.destroy();
|
||||||
VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &vertexBuffer, vertexBufferSize));
|
VK_CHECK_RESULT(createInfo.device->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &vertexBuffer, vertexBufferSize));
|
||||||
vertexCount = imDrawData->TotalVtxCount;
|
vertexCount = imDrawData->TotalVtxCount;
|
||||||
vertexBuffer.unmap();
|
vertexBuffer.unmap();
|
||||||
vertexBuffer.map();
|
vertexBuffer.map();
|
||||||
|
|
@ -504,7 +513,7 @@ namespace vks
|
||||||
if ((indexBuffer.buffer == VK_NULL_HANDLE) || (indexCount < imDrawData->TotalIdxCount)) {
|
if ((indexBuffer.buffer == VK_NULL_HANDLE) || (indexCount < imDrawData->TotalIdxCount)) {
|
||||||
indexBuffer.unmap();
|
indexBuffer.unmap();
|
||||||
indexBuffer.destroy();
|
indexBuffer.destroy();
|
||||||
VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &indexBuffer, indexBufferSize));
|
VK_CHECK_RESULT(createInfo.device->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &indexBuffer, indexBufferSize));
|
||||||
indexCount = imDrawData->TotalIdxCount;
|
indexCount = imDrawData->TotalIdxCount;
|
||||||
indexBuffer.map();
|
indexBuffer.map();
|
||||||
updateCmdBuffers = true;
|
updateCmdBuffers = true;
|
||||||
|
|
@ -535,8 +544,8 @@ namespace vks
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.DisplaySize = ImVec2((float)(width), (float)(height));
|
io.DisplaySize = ImVec2((float)(width), (float)(height));
|
||||||
this->width = width;
|
createInfo.width = width;
|
||||||
this->height = height;
|
createInfo.height = height;
|
||||||
updateCommandBuffers();
|
updateCommandBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -552,8 +561,8 @@ namespace vks
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence));
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence));
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkWaitForFences(device->logicalDevice, 1, &fence, VK_TRUE, UINT64_MAX));
|
VK_CHECK_RESULT(vkWaitForFences(createInfo.device->logicalDevice, 1, &fence, VK_TRUE, UINT64_MAX));
|
||||||
VK_CHECK_RESULT(vkResetFences(device->logicalDevice, 1, &fence));
|
VK_CHECK_RESULT(vkResetFences(createInfo.device->logicalDevice, 1, &fence));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIOverlay::header(const char *caption)
|
bool UIOverlay::header(const char *caption)
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,26 @@
|
||||||
|
|
||||||
namespace vks
|
namespace vks
|
||||||
{
|
{
|
||||||
|
struct UIOverlayCreateInfo
|
||||||
|
{
|
||||||
|
vks::VulkanDevice *device;
|
||||||
|
VkQueue copyQueue;
|
||||||
|
VkRenderPass renderPass;
|
||||||
|
std::vector<VkFramebuffer> framebuffers;
|
||||||
|
VkFormat colorformat;
|
||||||
|
VkFormat depthformat;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
std::vector<VkPipelineShaderStageCreateInfo> shaders;
|
||||||
|
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
uint32_t subpassCount = 1;
|
||||||
|
std::vector<VkClearValue> clearValues = {};
|
||||||
|
uint32_t attachmentCount = 1;
|
||||||
|
};
|
||||||
|
|
||||||
class UIOverlay
|
class UIOverlay
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
vks::VulkanDevice *device;
|
|
||||||
|
|
||||||
VkQueue copyQueue;
|
|
||||||
VkFormat colorFormat;
|
|
||||||
VkFormat depthFormat;
|
|
||||||
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
|
|
||||||
vks::Buffer vertexBuffer;
|
vks::Buffer vertexBuffer;
|
||||||
vks::Buffer indexBuffer;
|
vks::Buffer indexBuffer;
|
||||||
int32_t vertexCount = 0;
|
int32_t vertexCount = 0;
|
||||||
|
|
@ -55,8 +63,6 @@ namespace vks
|
||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VkCommandPool commandPool;
|
VkCommandPool commandPool;
|
||||||
std::vector<VkFramebuffer*> frameBuffers;
|
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
|
||||||
VkFence fence;
|
VkFence fence;
|
||||||
|
|
||||||
VkDeviceMemory fontMemory = VK_NULL_HANDLE;
|
VkDeviceMemory fontMemory = VK_NULL_HANDLE;
|
||||||
|
|
@ -69,6 +75,8 @@ namespace vks
|
||||||
glm::vec2 translate;
|
glm::vec2 translate;
|
||||||
} pushConstBlock;
|
} pushConstBlock;
|
||||||
|
|
||||||
|
UIOverlayCreateInfo createInfo = {};
|
||||||
|
|
||||||
void prepareResources();
|
void prepareResources();
|
||||||
void preparePipeline();
|
void preparePipeline();
|
||||||
void prepareRenderPass();
|
void prepareRenderPass();
|
||||||
|
|
@ -79,7 +87,7 @@ namespace vks
|
||||||
|
|
||||||
std::vector<VkCommandBuffer> cmdBuffers;
|
std::vector<VkCommandBuffer> cmdBuffers;
|
||||||
|
|
||||||
UIOverlay(vks::VulkanDevice *vulkanDevice, VkQueue copyQueue, std::vector<VkFramebuffer> &framebuffers, VkFormat colorformat, VkFormat depthformat, uint32_t width, uint32_t height, std::vector<VkPipelineShaderStageCreateInfo> shaderstages);
|
UIOverlay(vks::UIOverlayCreateInfo createInfo);
|
||||||
~UIOverlay();
|
~UIOverlay();
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
|
||||||
|
|
@ -188,11 +188,25 @@ void VulkanExampleBase::prepare()
|
||||||
setupFrameBuffer();
|
setupFrameBuffer();
|
||||||
settings.overlay = settings.overlay && (!benchmark.active);
|
settings.overlay = settings.overlay && (!benchmark.active);
|
||||||
if (settings.overlay) {
|
if (settings.overlay) {
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages = {
|
vks::UIOverlayCreateInfo overlayCreateInfo = {};
|
||||||
loadShader(getAssetPath() + "shaders/base/uioverlay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
|
// Setup default overlay creation info
|
||||||
loadShader(getAssetPath() + "shaders/base/uioverlay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT),
|
overlayCreateInfo.device = vulkanDevice;
|
||||||
};
|
overlayCreateInfo.copyQueue = queue;
|
||||||
UIOverlay = new vks::UIOverlay(vulkanDevice, queue, frameBuffers, swapChain.colorFormat, depthFormat, width, height, shaderStages);
|
overlayCreateInfo.framebuffers = frameBuffers;
|
||||||
|
overlayCreateInfo.colorformat = swapChain.colorFormat;
|
||||||
|
overlayCreateInfo.depthformat = depthFormat;
|
||||||
|
overlayCreateInfo.width = width;
|
||||||
|
overlayCreateInfo.height = height;
|
||||||
|
// Virtual function call for example to customize overlay creation
|
||||||
|
OnSetupUIOverlay(overlayCreateInfo);
|
||||||
|
// Load default shaders if not specified by example
|
||||||
|
if (overlayCreateInfo.shaders.size() == 0) {
|
||||||
|
overlayCreateInfo.shaders = {
|
||||||
|
loadShader(getAssetPath() + "shaders/base/uioverlay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
|
||||||
|
loadShader(getAssetPath() + "shaders/base/uioverlay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
UIOverlay = new vks::UIOverlay(overlayCreateInfo);
|
||||||
updateOverlay();
|
updateOverlay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2141,4 +2155,5 @@ void VulkanExampleBase::setupSwapChain()
|
||||||
swapChain.create(&width, &height, settings.vsync);
|
swapChain.create(&width, &height, settings.vsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanExampleBase::OnSetupUIOverlay(vks::UIOverlayCreateInfo &createInfo) {}
|
||||||
void VulkanExampleBase::OnUpdateUIOverlay(vks::UIOverlay *overlay) {}
|
void VulkanExampleBase::OnUpdateUIOverlay(vks::UIOverlay *overlay) {}
|
||||||
|
|
@ -392,6 +392,8 @@ public:
|
||||||
// Submit the frames' workload
|
// Submit the frames' workload
|
||||||
void submitFrame();
|
void submitFrame();
|
||||||
|
|
||||||
|
/** @brief (Virtual) Called before the UI overlay is created, can be used to do a custom setup e.g. with different renderpass */
|
||||||
|
virtual void OnSetupUIOverlay(vks::UIOverlayCreateInfo &createInfo);
|
||||||
/** @brief (Virtual) Called when the UI overlay is updating, can be used to add custom elements to the overlay */
|
/** @brief (Virtual) Called when the UI overlay is updating, can be used to add custom elements to the overlay */
|
||||||
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay);
|
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue