Streamlined UI overlay, code cleanup

Refs #496
This commit is contained in:
saschawillems 2018-08-31 21:15:43 +02:00
parent c1c4f06a23
commit 69c3f62b9a
7 changed files with 75 additions and 131 deletions

View file

@ -10,10 +10,8 @@
namespace vks namespace vks
{ {
UIOverlay::UIOverlay(vks::UIOverlayCreateInfo createInfo) UIOverlay::UIOverlay()
{ {
this->createInfo = createInfo;
#if defined(__ANDROID__) #if defined(__ANDROID__)
if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_XXHIGH) { if (vks::android::screenDensity >= ACONFIGURATION_DENSITY_XXHIGH) {
scale = 3.5f; scale = 3.5f;
@ -40,27 +38,10 @@ 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)(createInfo.width), (float)(createInfo.height));
io.FontGlobalScale = scale; io.FontGlobalScale = scale;
prepareResources();
} }
/** Free up all Vulkan resources acquired by the UI overlay */ UIOverlay::~UIOverlay() { }
UIOverlay::~UIOverlay()
{
ImGui::DestroyContext();
vertexBuffer.destroy();
indexBuffer.destroy();
vkDestroyImageView(createInfo.device->logicalDevice, fontView, nullptr);
vkDestroyImage(createInfo.device->logicalDevice, fontImage, nullptr);
vkFreeMemory(createInfo.device->logicalDevice, fontMemory, nullptr);
vkDestroySampler(createInfo.device->logicalDevice, sampler, nullptr);
vkDestroyDescriptorSetLayout(createInfo.device->logicalDevice, descriptorSetLayout, nullptr);
vkDestroyDescriptorPool(createInfo.device->logicalDevice, descriptorPool, nullptr);
vkDestroyPipelineLayout(createInfo.device->logicalDevice, pipelineLayout, nullptr);
vkDestroyPipeline(createInfo.device->logicalDevice, pipeline, nullptr);
}
/** Prepare all vulkan resources required to render the UI overlay */ /** Prepare all vulkan resources required to render the UI overlay */
void UIOverlay::prepareResources() void UIOverlay::prepareResources()
@ -87,14 +68,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(createInfo.device->logicalDevice, &imageInfo, nullptr, &fontImage)); VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageInfo, nullptr, &fontImage));
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(createInfo.device->logicalDevice, fontImage, &memReqs); vkGetImageMemoryRequirements(device->logicalDevice, fontImage, &memReqs);
VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
memAllocInfo.allocationSize = memReqs.size; memAllocInfo.allocationSize = memReqs.size;
memAllocInfo.memoryTypeIndex = createInfo.device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(createInfo.device->logicalDevice, &memAllocInfo, nullptr, &fontMemory)); VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &fontMemory));
VK_CHECK_RESULT(vkBindImageMemory(createInfo.device->logicalDevice, fontImage, fontMemory, 0)); VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, fontImage, fontMemory, 0));
// Image view // Image view
VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo(); VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo();
@ -104,12 +85,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(createInfo.device->logicalDevice, &viewInfo, nullptr, &fontView)); VK_CHECK_RESULT(vkCreateImageView(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(createInfo.device->createBuffer( VK_CHECK_RESULT(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,
@ -120,7 +101,7 @@ namespace vks
stagingBuffer.unmap(); stagingBuffer.unmap();
// Copy buffer data to font image // Copy buffer data to font image
VkCommandBuffer copyCmd = createInfo.device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
// Prepare for transfer // Prepare for transfer
vks::tools::setImageLayout( vks::tools::setImageLayout(
@ -159,7 +140,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);
createInfo.device->flushCommandBuffer(copyCmd, createInfo.copyQueue, true); device->flushCommandBuffer(copyCmd, queue, true);
stagingBuffer.destroy(); stagingBuffer.destroy();
@ -172,25 +153,25 @@ 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(createInfo.device->logicalDevice, &samplerInfo, nullptr, &sampler)); VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerInfo, nullptr, &sampler));
// 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(createInfo.device->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(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(createInfo.device->logicalDevice, &descriptorLayout, nullptr, &descriptorSetLayout)); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(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(createInfo.device->logicalDevice, &allocInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &allocInfo, &descriptorSet));
VkDescriptorImageInfo fontDescriptor = vks::initializers::descriptorImageInfo( VkDescriptorImageInfo fontDescriptor = vks::initializers::descriptorImageInfo(
sampler, sampler,
fontView, fontView,
@ -199,7 +180,7 @@ 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(createInfo.device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); vkUpdateDescriptorSets(device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
} }
/** 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 */
@ -211,7 +192,7 @@ 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(createInfo.device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); VK_CHECK_RESULT(vkCreatePipelineLayout(device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
// Setup graphics pipeline for UI rendering // Setup graphics pipeline for UI rendering
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
@ -231,20 +212,8 @@ 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(static_cast<uint32_t>(blendStates.size()), blendStates.data()); vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);
VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo depthStencilState =
vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_ALWAYS); vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_ALWAYS);
@ -253,7 +222,7 @@ namespace vks
vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo multisampleState =
vks::initializers::pipelineMultisampleStateCreateInfo(createInfo.rasterizationSamples); vks::initializers::pipelineMultisampleStateCreateInfo(rasterizationSamples);
std::vector<VkDynamicState> dynamicStateEnables = { std::vector<VkDynamicState> dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_VIEWPORT,
@ -271,9 +240,9 @@ 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>(createInfo.shaders.size()); pipelineCreateInfo.stageCount = static_cast<uint32_t>(shaders.size());
pipelineCreateInfo.pStages = createInfo.shaders.data(); pipelineCreateInfo.pStages = shaders.data();
pipelineCreateInfo.subpass = createInfo.targetSubpass; pipelineCreateInfo.subpass = subpass;
// 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 = {
@ -292,7 +261,7 @@ namespace vks
pipelineCreateInfo.pVertexInputState = &vertexInputState; pipelineCreateInfo.pVertexInputState = &vertexInputState;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(createInfo.device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
} }
/** Update vertex and index buffer containing the imGui elements when required */ /** Update vertex and index buffer containing the imGui elements when required */
@ -316,7 +285,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(createInfo.device->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &vertexBuffer, vertexBufferSize)); VK_CHECK_RESULT(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();
@ -328,7 +297,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(createInfo.device->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &indexBuffer, indexBufferSize)); VK_CHECK_RESULT(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;
@ -401,6 +370,21 @@ namespace vks
io.DisplaySize = ImVec2((float)(width), (float)(height)); io.DisplaySize = ImVec2((float)(width), (float)(height));
} }
void UIOverlay::freeResources()
{
ImGui::DestroyContext();
vertexBuffer.destroy();
indexBuffer.destroy();
vkDestroyImageView(device->logicalDevice, fontView, nullptr);
vkDestroyImage(device->logicalDevice, fontImage, nullptr);
vkFreeMemory(device->logicalDevice, fontMemory, nullptr);
vkDestroySampler(device->logicalDevice, sampler, nullptr);
vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayout, nullptr);
vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr);
vkDestroyPipelineLayout(device->logicalDevice, pipelineLayout, nullptr);
vkDestroyPipeline(device->logicalDevice, pipeline, nullptr);
}
bool UIOverlay::header(const char *caption) bool UIOverlay::header(const char *caption)
{ {
return ImGui::CollapsingHeader(caption, ImGuiTreeNodeFlags_DefaultOpen); return ImGui::CollapsingHeader(caption, ImGuiTreeNodeFlags_DefaultOpen);

View file

@ -30,28 +30,22 @@
namespace vks namespace vks
{ {
struct UIOverlayCreateInfo
{
vks::VulkanDevice *device;
VkQueue copyQueue;
uint32_t width;
uint32_t height;
std::vector<VkPipelineShaderStageCreateInfo> shaders;
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
uint32_t targetSubpass = 0;
uint32_t subpassCount = 1;
std::vector<VkClearValue> clearValues = {};
uint32_t attachmentCount = 1;
};
class UIOverlay class UIOverlay
{ {
public: public:
vks::VulkanDevice *device;
VkQueue queue;
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
uint32_t subpass = 0;
vks::Buffer vertexBuffer; vks::Buffer vertexBuffer;
vks::Buffer indexBuffer; vks::Buffer indexBuffer;
int32_t vertexCount = 0; int32_t vertexCount = 0;
int32_t indexCount = 0; int32_t indexCount = 0;
std::vector<VkPipelineShaderStageCreateInfo> shaders;
VkDescriptorPool descriptorPool; VkDescriptorPool descriptorPool;
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout descriptorSetLayout;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
@ -68,22 +62,21 @@ namespace vks
glm::vec2 translate; glm::vec2 translate;
} pushConstBlock; } pushConstBlock;
UIOverlayCreateInfo createInfo = {};
void prepareResources();
public:
bool visible = true; bool visible = true;
float scale = 1.0f; float scale = 1.0f;
UIOverlay(vks::UIOverlayCreateInfo createInfo); UIOverlay();
~UIOverlay(); ~UIOverlay();
void preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass); void preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass);
void prepareResources();
bool update(); bool update();
void draw(const VkCommandBuffer commandBuffer); void draw(const VkCommandBuffer commandBuffer);
void resize(uint32_t width, uint32_t height); void resize(uint32_t width, uint32_t height);
void freeResources();
bool header(const char* caption); bool header(const char* caption);
bool checkBox(const char* caption, bool* value); bool checkBox(const char* caption, bool* value);
bool checkBox(const char* caption, int32_t* value); bool checkBox(const char* caption, int32_t* value);

View file

@ -195,23 +195,14 @@ void VulkanExampleBase::prepare()
setupFrameBuffer(); setupFrameBuffer();
settings.overlay = settings.overlay && (!benchmark.active); settings.overlay = settings.overlay && (!benchmark.active);
if (settings.overlay) { if (settings.overlay) {
vks::UIOverlayCreateInfo overlayCreateInfo = {}; UIOverlay.device = vulkanDevice;
// Setup default overlay creation info UIOverlay.queue = queue;
overlayCreateInfo.device = vulkanDevice; UIOverlay.shaders = {
overlayCreateInfo.copyQueue = queue; loadShader(getAssetPath() + "shaders/base/uioverlay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
overlayCreateInfo.width = width; loadShader(getAssetPath() + "shaders/base/uioverlay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT),
overlayCreateInfo.height = height; };
// Virtual function call for example to customize overlay creation UIOverlay.prepareResources();
OnSetupUIOverlay(overlayCreateInfo); UIOverlay.preparePipeline(pipelineCache, renderPass);
// 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);
UIOverlay->preparePipeline(pipelineCache, renderPass);
updateOverlay(); updateOverlay();
} }
} }
@ -588,10 +579,10 @@ void VulkanExampleBase::updateOverlay()
ImGui::Text("%.2f ms/frame (%.1d fps)", (1000.0f / lastFPS), lastFPS); ImGui::Text("%.2f ms/frame (%.1d fps)", (1000.0f / lastFPS), lastFPS);
#if defined(VK_USE_PLATFORM_ANDROID_KHR) #if defined(VK_USE_PLATFORM_ANDROID_KHR)
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 5.0f * UIOverlay->scale)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 5.0f * UIOverlay.scale));
#endif #endif
ImGui::PushItemWidth(110.0f * UIOverlay->scale); ImGui::PushItemWidth(110.0f * UIOverlay.scale);
OnUpdateUIOverlay(UIOverlay); OnUpdateUIOverlay(&UIOverlay);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
#if defined(VK_USE_PLATFORM_ANDROID_KHR) #if defined(VK_USE_PLATFORM_ANDROID_KHR)
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -601,7 +592,7 @@ void VulkanExampleBase::updateOverlay()
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::Render(); ImGui::Render();
if (UIOverlay->update()) { if (UIOverlay.update()) {
buildCommandBuffers(); buildCommandBuffers();
} }
@ -621,7 +612,7 @@ void VulkanExampleBase::drawUI(const VkCommandBuffer commandBuffer)
vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
UIOverlay->draw(commandBuffer); UIOverlay.draw(commandBuffer);
} }
} }
@ -794,8 +785,8 @@ VulkanExampleBase::~VulkanExampleBase()
vkDestroyFence(device, fence, nullptr); vkDestroyFence(device, fence, nullptr);
} }
if (UIOverlay) { if (settings.overlay) {
delete UIOverlay; UIOverlay.freeResources();
} }
delete vulkanDevice; delete vulkanDevice;
@ -1156,7 +1147,7 @@ void VulkanExampleBase::handleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break; break;
case KEY_F1: case KEY_F1:
if (settings.overlay) { if (settings.overlay) {
UIOverlay->visible = !UIOverlay->visible; UIOverlay.visible = !UIOverlay.visible;
} }
break; break;
case KEY_ESCAPE: case KEY_ESCAPE:
@ -2144,7 +2135,7 @@ void VulkanExampleBase::windowResize()
if ((width > 0.0f) && (height > 0.0f)) { if ((width > 0.0f) && (height > 0.0f)) {
if (settings.overlay) { if (settings.overlay) {
UIOverlay->resize(width, height); UIOverlay.resize(width, height);
} }
} }
@ -2232,5 +2223,4 @@ 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) {}

View file

@ -66,7 +66,6 @@ private:
uint32_t destWidth; uint32_t destWidth;
uint32_t destHeight; uint32_t destHeight;
bool resizing = false; bool resizing = false;
vks::UIOverlay *UIOverlay = nullptr;
// Called if the window is resized and some resources have to be recreatesd // Called if the window is resized and some resources have to be recreatesd
void windowResize(); void windowResize();
void handleMouseMove(int32_t x, int32_t y); void handleMouseMove(int32_t x, int32_t y);
@ -135,6 +134,8 @@ public:
uint32_t width = 1280; uint32_t width = 1280;
uint32_t height = 720; uint32_t height = 720;
vks::UIOverlay UIOverlay;
/** @brief Last frame time measured using a high performance timer (if available) */ /** @brief Last frame time measured using a high performance timer (if available) */
float frameTimer = 1.0f; float frameTimer = 1.0f;
/** @brief Returns os specific base asset path (for shaders, models, textures) */ /** @brief Returns os specific base asset path (for shaders, models, textures) */
@ -399,8 +400,6 @@ 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);
}; };

View file

@ -97,6 +97,7 @@ public:
camera.setRotation(glm::vec3(-12.75f, 380.0f, 0.0f)); camera.setRotation(glm::vec3(-12.75f, 380.0f, 0.0f));
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
settings.overlay = true; settings.overlay = true;
UIOverlay.subpass = 1;
} }
~VulkanExample() ~VulkanExample()
@ -608,19 +609,6 @@ public:
} }
} }
// UI overlay configuration needs to be adjusted for this example (renderpass setup, attachment count, etc.)
virtual void OnSetupUIOverlay(vks::UIOverlayCreateInfo &createInfo)
{
createInfo.targetSubpass = 1;
createInfo.subpassCount = 2;
createInfo.attachmentCount = 1;
createInfo.clearValues = {
{ { 0.0f, 0.0f, 0.0f, 0.0f } },
{ { 0.0f, 0.0f, 0.0f, 0.0f } },
{ { 1.0f, 0 } },
};
}
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
{ {
if (overlay->header("Settings")) { if (overlay->header("Settings")) {

View file

@ -87,11 +87,12 @@ public:
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
title = "Multisampling"; title = "Multisampling";
settings.overlay = true;
camera.type = Camera::CameraType::lookat; camera.type = Camera::CameraType::lookat;
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f));
camera.setTranslation(glm::vec3(2.5f, 2.5f, -7.5f)); camera.setTranslation(glm::vec3(2.5f, 2.5f, -7.5f));
settings.overlay = true;
UIOverlay.rasterizationSamples = sampleCount;
} }
~VulkanExample() ~VulkanExample()
@ -729,12 +730,6 @@ public:
return VK_SAMPLE_COUNT_1_BIT; return VK_SAMPLE_COUNT_1_BIT;
} }
// UI overlay configuration needs to be adjusted for this example (renderpass setup, attachment count, etc.)
virtual void OnSetupUIOverlay(vks::UIOverlayCreateInfo &createInfo)
{
createInfo.rasterizationSamples = sampleCount;
}
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
{ {
if (vulkanDevice->features.sampleRateShading) { if (vulkanDevice->features.sampleRateShading) {

View file

@ -133,6 +133,7 @@ public:
camera.setRotation(glm::vec3(0.5f, 210.05f, 0.0f)); camera.setRotation(glm::vec3(0.5f, 210.05f, 0.0f));
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
settings.overlay = true; settings.overlay = true;
UIOverlay.subpass = 2;
} }
~VulkanExample() ~VulkanExample()
@ -1069,12 +1070,6 @@ public:
updateUniformBufferDeferredLights(); updateUniformBufferDeferredLights();
} }
// UI overlay configuration needs to be adjusted for this example (renderpass setup, attachment count, etc.)
virtual void OnSetupUIOverlay(vks::UIOverlayCreateInfo &createInfo)
{
createInfo.targetSubpass = 2;
}
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
{ {
if (overlay->header("Subpasses")) { if (overlay->header("Subpasses")) {