For some reason, the window in which Vulkan controls the graphics only clears, but does not render a triangle, but there are no Vulkan validation errors/warnings. I write that the code is from methods because it is code from class methods.
Vertex shader code:
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}
Fragment shader code:
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}
A method code that initializes important variables for window:
device = gd->getDevice();
Assert(!SDL_Vulkan_CreateSurface(window, gd->getVkInstance(), NULL, &vkSurface) != SDL_TRUE);
LoadVkFunc(vkGetPhysicalDeviceSurfaceSupportKHR);
LoadVkFunc(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
LoadVkFunc(vkGetPhysicalDeviceSurfaceFormatsKHR);
LoadVkFunc(vkCreateSwapchainKHR);
LoadVkFunc(vkGetSwapchainImagesKHR);
LoadVkFunc(vkCreateImageView);
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->vkPhysDevice, vkSurface, &capabilities);
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device->vkPhysDevice, vkSurface, &formatCount, nullptr);
if (formatCount != 0) {
formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device->vkPhysDevice, vkSurface, &formatCount, formats.data());
}
AssertMessage(!(formats.empty() && presentModes.empty()), "Failed to detect format and present mode!");
for (const auto& availableFormat : formats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
vkSurfaceFormat = availableFormat;
}
}
if (!(vkSurfaceFormat.format == VK_FORMAT_B8G8R8A8_UNORM && vkSurfaceFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)) vkSurfaceFormat = formats[0];
for (const auto& availablePresentMode : presentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
vkPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
}
}
if (vkPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) vkPresentMode = VK_PRESENT_MODE_FIFO_KHR;
if (capabilities.currentExtent.width != UINT32_MAX) {
vkExtent2D = capabilities.currentExtent;
}
else {
int width, height;
SDL_GetWindowSizeInPixels(window, &width, &height);
VkExtent2D actualExtent = {
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
};
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
vkExtent2D = actualExtent;
}
formats.clear();
presentModes.clear();
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = vkSurface;
maxFrames = capabilities.maxImageCount > 0 && (capabilities.minImageCount + 1) > capabilities.maxImageCount ? capabilities.maxImageCount : capabilities.minImageCount + 1;
createInfo.minImageCount = maxFrames;
createInfo.imageFormat = vkSurfaceFormat.format;
createInfo.imageColorSpace = vkSurfaceFormat.colorSpace;
createInfo.imageExtent = vkExtent2D;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
createInfo.preTransform = capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = vkPresentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
uint32_t queueFamilyIndices[] = { device->vkGraphicsFamily.value(), vkPresentMode };
if (device->vkGraphicsFamily.value() != vkPresentMode) {
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else {
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
}
vkCreateSwapchainKHR(device->vkDevice, &createInfo, nullptr, &vkSwapchain);
vkGetSwapchainImagesKHR(device->vkDevice, vkSwapchain, &maxFrames, nullptr);
vkFrames.resize(maxFrames);
vkGetSwapchainImagesKHR(device->vkDevice, vkSwapchain, &maxFrames, vkFrames.data());
vkFrameViews.resize(vkFrames.size());
for (size_t i = 0; i < vkFrames.size(); i++) {
VkImageViewCreateInfo IVcreateInfo{};
IVcreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
IVcreateInfo.image = vkFrames[i];
IVcreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
IVcreateInfo.format = vkSurfaceFormat.format;
IVcreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
IVcreateInfo.subresourceRange.baseArrayLayer = 0;
IVcreateInfo.subresourceRange.baseMipLevel = 0;
IVcreateInfo.subresourceRange.layerCount = 1;
IVcreateInfo.subresourceRange.levelCount = 1;
IVcreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
IVcreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
IVcreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
IVcreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
Assert(!vkCreateImageView(device->vkDevice, &IVcreateInfo, nullptr, &vkFrameViews[i]) != VK_SUCCESS);
}
vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)vkExtent2D.width;
viewport.height = (float)vkExtent2D.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
VkRect2D scissor;
scissor.offset = { 0, 0 };
scissor.extent = vkExtent2D;
viewportState.pScissors = &scissor;
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0; // Optional
pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
LoadVkFunc(vkCreatePipelineLayout);
Assert(!vkCreatePipelineLayout(device->vkDevice, &pipelineLayoutInfo, nullptr, &vkPipelineLayout));
VkAttachmentDescription colorAttachment{};
colorAttachment.format = vkSurfaceFormat.format;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
renderPassInfo.pDependencies = &dependency;
LoadVkFunc(vkCreateRenderPass);
Assert(!vkCreateRenderPass(device->vkDevice, &renderPassInfo, nullptr, &vkRenderPass));
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = shaders.size();
vector<VkPipelineShaderStageCreateInfo> shadersCI;
for (uint16 i = 0; i < shaders.size(); i++)
{
std::ifstream file(shaders[i].vertex, std::ios::ate | std::ios::binary);
Assert(file.is_open());
size_t fileSize = static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
VkShaderModuleCreateInfo vkVertCreateInfo{};
vkVertCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vkVertCreateInfo.codeSize = buffer.size();
vkVertCreateInfo.pCode = reinterpret_cast<const uint32_t*>(buffer.data());
VkShaderModule vertexShaderModule;
VkShaderModule fragmentShaderModule;
LoadVkFunc(vkCreateShaderModule);
Assert(!vkCreateShaderModule(device->vkDevice, &vkVertCreateInfo, nullptr, &vertexShaderModule) != VK_SUCCESS);
file.open(shaders[i].fragment, std::ios::ate | std::ios::binary);
Assert(file.is_open());
fileSize = static_cast<size_t>(file.tellg());
buffer.clear();
buffer.resize(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
VkShaderModuleCreateInfo vkFragCreateInfo{};
vkFragCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vkFragCreateInfo.codeSize = buffer.size();
vkFragCreateInfo.pCode = reinterpret_cast<const uint32_t*>(buffer.data());
Assert(!vkCreateShaderModule(device->vkDevice, &vkFragCreateInfo, nullptr, &fragmentShaderModule) != VK_SUCCESS);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertexShaderModule;
vertShaderStageInfo.pName = "main";
vertShaderStageInfo.pSpecializationInfo = nullptr;
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragmentShaderModule;
fragShaderStageInfo.pName = "main";
fragShaderStageInfo.pSpecializationInfo = nullptr;
shadersCI.push_back(vertShaderStageInfo);
i++;
shadersCI.push_back(fragShaderStageInfo);
}
pipelineInfo.pStages = shadersCI.data();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexBindingDescriptions = nullptr;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.renderPass = vkRenderPass;
pipelineInfo.layout = vkPipelineLayout;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
LoadVkFunc(vkCreateGraphicsPipelines);
Assert(!vkCreateGraphicsPipelines(device->vkDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &vkPipeline));
vkFrameBuffers.resize(vkFrameViews.size());
LoadVkFunc(vkCreateFramebuffer);
for (size_t i = 0; i < vkFrameBuffers.size(); i++) {
VkImageView attachments[] = {
vkFrameViews[i]
};
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = vkRenderPass;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = vkExtent2D.width;
framebufferInfo.height = vkExtent2D.height;
framebufferInfo.layers = 1;
Assert(!vkCreateFramebuffer(device->vkDevice, &framebufferInfo, nullptr, &vkFrameBuffers[i]));
}
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = device->vkGraphicsFamily.value();
LoadVkFunc(vkCreateCommandPool);
Assert(!vkCreateCommandPool(device->vkDevice, &poolInfo, nullptr, &vkCommandPool));
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = vkCommandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = maxFrames;
vkCommandBuffers.resize(maxFrames);
LoadVkFunc(vkAllocateCommandBuffers);
Assert(!vkAllocateCommandBuffers(device->vkDevice, &allocInfo, vkCommandBuffers.data()));
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkFences.resize(maxFrames);
vkAvailableSems.resize(maxFrames);
vkFinishedSems.resize(maxFrames);
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
LoadVkFunc(vkCreateFence);
LoadVkFunc(vkCreateSemaphore);
for (uint32 i = 0; i < maxFrames; i++) {
Assert(vkCreateFence(device->vkDevice, &fenceInfo, nullptr, &vkFences[i]) == VK_SUCCESS);
Assert(vkCreateSemaphore(device->vkDevice, &semaphoreInfo, nullptr, &vkAvailableSems[i]) == VK_SUCCESS);
Assert(vkCreateSemaphore(device->vkDevice, &semaphoreInfo, nullptr, &vkFinishedSems[i]) == VK_SUCCESS);
}
The method code that renders to vkSurface:
LoadVkFunc(vkWaitForFences);
vkWaitForFences(device->vkDevice, 1, &vkFences[currentFrameID], VK_TRUE, UINT64_MAX);
LoadVkFunc(vkResetFences);
vkResetFences(device->vkDevice, 1, &vkFences[currentFrameID]);
uint32 imageID;
LoadVkFunc(vkAcquireNextImageKHR);
vkAcquireNextImageKHR(device->vkDevice, vkSwapchain, UINT64_MAX, vkAvailableSems[currentFrameID], VK_NULL_HANDLE, &imageID);
LoadVkFunc(vkResetCommandBuffer);
vkResetCommandBuffer(vkCommandBuffers[currentFrameID], 0);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
LoadVkFunc(vkBeginCommandBuffer);
Assert(!vkBeginCommandBuffer(vkCommandBuffers[currentFrameID], &beginInfo));
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = vkRenderPass;
renderPassInfo.framebuffer = vkFrameBuffers[imageID];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = vkExtent2D;
VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
LoadVkFunc(vkCmdBindPipeline);
vkCmdBindPipeline(vkCommandBuffers[currentFrameID], VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline);
LoadVkFunc(vkCmdBeginRenderPass);
vkCmdBeginRenderPass(vkCommandBuffers[currentFrameID], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(vkExtent2D.width);
viewport.height = static_cast<float>(vkExtent2D.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
LoadVkFunc(vkCmdSetViewport);
vkCmdSetViewport(vkCommandBuffers[currentFrameID], 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = vkExtent2D;
LoadVkFunc(vkCmdSetScissor);
vkCmdSetScissor(vkCommandBuffers[currentFrameID], 0, 1, &scissor);
LoadVkFunc(vkCmdDraw);
vkCmdDraw(vkCommandBuffers[currentFrameID], 3, 1, 0, 0);
LoadVkFunc(vkCmdEndRenderPass);
vkCmdEndRenderPass(vkCommandBuffers[currentFrameID]);
LoadVkFunc(vkEndCommandBuffer);
vkEndCommandBuffer(vkCommandBuffers[currentFrameID]);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &vkCommandBuffers[currentFrameID];
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &vkFinishedSems[currentFrameID];
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &vkAvailableSems[currentFrameID];
submitInfo.pWaitDstStageMask = waitStages;
LoadVkFunc(vkQueueSubmit);
Assert(vkQueueSubmit(device->vkGraphicsQueue, 1, &submitInfo, vkFences[currentFrameID]) == VK_SUCCESS);
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &vkFinishedSems[currentFrameID];
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &vkSwapchain;
presentInfo.pImageIndices = &imageID;
presentInfo.pResults = nullptr; // Optional
LoadVkFunc(vkQueuePresentKHR);
vkQueuePresentKHR(device->vkPresentQueue, &presentInfo);
currentFrameID = currentFrameID < maxFrames - 1 ? currentFrameID + 1 : 0;
New contributor
Katadron Katadron is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.