I have set up viewport and scissor as dynamic states for my pipelines and I am updating them if the window is resized (or first draw call):
void VulkanRenderer::setViewportAndScissor(VkCommandBuffer commandBuffer) {
if (!sizeChanged)
return;
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swapchain.getExtent().width;
viewport.height = (float)swapchain.getExtent().height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = {0, 0};
scissor.extent = swapchain.getExtent();
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
sizeChanged = true;
}
My renderer creates one command buffer per swapchain and when I acquire a swapchain image, I use the respective command buffer for all the draw related commands:
void VulkanRenderer::draw(Scene *scene) {
uint32_t imageIdx = swapchain.acquireNextImage(imageAvailableSemaphore);
vkWaitForFences(context.getDevice(), 1, &renderFence, true,
std::numeric_limits<uint32_t>::max());
vkResetFences(context.getDevice(), 1, &renderFence);
vkResetCommandBuffer(commandBuffers[imageIdx], 0);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr;
if (vkBeginCommandBuffer(commandBuffers[imageIdx], &beginInfo) !=
VK_SUCCESS) {
throw VulkanError("Failed to begin recording command buffer for frame");
}
setViewportAndScissor(commandBuffers[imageIdx]);
VkClearValue clearValue;
clearValue.color = {{0.0f, 0.0f, 0.0f, 1.0f}};
VkClearValue depthClear;
depthClear.depthStencil.depth = 1.0f;
VkClearValue clearValues[] = {clearValue, depthClear};
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
renderPassInfo.framebuffer = framebuffers[imageIdx];
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapchain.getExtent();
renderPassInfo.clearValueCount = 2;
renderPassInfo.pClearValues = clearValues;
// rest of the call
}
Do I need to write the viewport and scissor for every outputted framebuffer?