Permalink
Browse files

VulkanRenderManager: Split out BeginFrame and EndFrame from Run

  • Loading branch information...
hrydgard committed Oct 28, 2017
1 parent 872b030 commit 717ec2387b39293063324cfa7b025819af19104f
@@ -509,7 +509,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
return fb->color.imageView;
}
void VulkanRenderManager::Flush() {
void VulkanRenderManager::Finish() {
curRenderStep_ = nullptr;
int curFrame = vulkan_->GetCurFrame();
FrameData &frameData = frameData_[curFrame];
@@ -529,46 +529,42 @@ void VulkanRenderManager::Flush() {
vulkan_->EndFrame();
}
void VulkanRenderManager::Run(int frame) {
// Can be called multiple times with no bad side effects. This is so that we can either begin a frame the normal way,
void VulkanRenderManager::BeginFrame(int frame) {
FrameData &frameData = frameData_[frame];
auto &stepsOnThread = frameData_[frame].steps;
VkDevice device = vulkan_->GetDevice();
uint32_t curSwapchainImage = 0;
// Get the index of the next available swapchain image, and a semaphore to block command buffer execution on.
// Now, I wonder if we should do this early in the frame or late? Right now we do it early, which should be fine.
VkResult res = vkAcquireNextImageKHR(device, vulkan_->GetSwapchain(), UINT64_MAX, acquireSemaphore_, (VkFence)VK_NULL_HANDLE, &curSwapchainImage);
assert(res == VK_SUCCESS);
if (!frameData.hasBegun) {
// Get the index of the next available swapchain image, and a semaphore to block command buffer execution on.
// Now, I wonder if we should do this early in the frame or late? Right now we do it early, which should be fine.
VkResult res = vkAcquireNextImageKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), UINT64_MAX, acquireSemaphore_, (VkFence)VK_NULL_HANDLE, &frameData.curSwapchainImage);
assert(res == VK_SUCCESS);
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
VkCommandBuffer cmd = frameData.mainCmd;
VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
res = vkBeginCommandBuffer(frameData.mainCmd, &begin);
VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
res = vkBeginCommandBuffer(cmd, &begin);
assert(res == VK_SUCCESS);
assert(res == VK_SUCCESS);
// TODO: Is it best to do this here, or combine with some other transition, or just do it right before the backbuffer bind-for-render?
TransitionFromPresent(frameData.mainCmd, swapchainImages_[frameData.curSwapchainImage].image);
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
// TODO: Is it best to do this here, or combine with some other transition, or just do it right before the backbuffer bind-for-render?
assert(res == VK_SUCCESS);
TransitionFromPresent(cmd, swapchainImages_[curSwapchainImage].image);
queueRunner_.SetBackbuffer(framebuffers_[frameData.curSwapchainImage]);
queueRunner_.SetBackbuffer(framebuffers_[curSwapchainImage]);
queueRunner_.RunSteps(cmd, stepsOnThread);
stepsOnThread.clear();
frameData.hasBegun = true;
}
}
void VulkanRenderManager::EndFrame(int frame) {
FrameData &frameData = frameData_[frame];
frameData.hasBegun = false;
insideFrame_ = false;
TransitionToPresent(frameData.mainCmd, swapchainImages_[curSwapchainImage].image);
TransitionToPresent(frameData.mainCmd, swapchainImages_[frameData.curSwapchainImage].image);
res = vkEndCommandBuffer(frameData.mainCmd);
VkResult res = vkEndCommandBuffer(frameData.mainCmd);
assert(res == VK_SUCCESS);
// So the sequence will be, cmdInit, [cmdQueue_], frame->cmdBuf.
// This way we bunch up all the initialization needed for the frame, we render to
// other buffers before the back buffer, and then last we render to the backbuffer.
int numCmdBufs = 0;
std::vector<VkCommandBuffer> cmdBufs;
if (frameData.hasInitCommands) {
@@ -602,7 +598,7 @@ void VulkanRenderManager::Run(int frame) {
VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
present.swapchainCount = 1;
present.pSwapchains = &swapchain;
present.pImageIndices = &curSwapchainImage;
present.pImageIndices = &frameData.curSwapchainImage;
present.pWaitSemaphores = &renderingCompleteSemaphore_;
present.waitSemaphoreCount = 1;
present.pResults = nullptr;
@@ -614,6 +610,21 @@ void VulkanRenderManager::Run(int frame) {
} else {
assert(res == VK_SUCCESS);
}
}
void VulkanRenderManager::Run(int frame) {
VkDevice device = vulkan_->GetDevice();
BeginFrame(frame);
FrameData &frameData = frameData_[frame];
auto &stepsOnThread = frameData_[frame].steps;
VkCommandBuffer cmd = frameData.mainCmd;
queueRunner_.RunSteps(cmd, stepsOnThread);
stepsOnThread.clear();
EndFrame(frame);
VLOG("PULL: Finished running frame %d", frame);
}
@@ -78,12 +78,13 @@ class VulkanRenderManager {
// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
void BeginFrame();
void EndFrame();
// Can run on a different thread! Just make sure to use BeginFrameWrites.
void Flush();
void Finish();
void Run(int frame);
// Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot).
void Sync();
void RunSteps(VkCommandBuffer cmd, const std::vector<VKRStep *> &steps, int curSwapChainImage);
void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, int aspectBit, int attachment);
@@ -186,6 +187,9 @@ class VulkanRenderManager {
private:
void InitBackbufferFramebuffers(int width, int height);
void InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
void BeginFrame(int frame);
void EndFrame(int frame);
// Permanent objects
VkSemaphore acquireSemaphore_;
VkSemaphore renderingCompleteSemaphore_;
@@ -209,6 +213,10 @@ class VulkanRenderManager {
VkCommandBuffer mainCmd;
bool hasInitCommands = false;
std::vector<VKRStep *> steps;
// Swapchain.
bool hasBegun = false;
uint32_t curSwapchainImage;
};
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES];
@@ -757,7 +757,7 @@ void VKContext::EndFrame() {
// Stop collecting data in the frame's data pushbuffer.
push_->End();
renderManager_.Flush();
renderManager_.Finish();
frameNum_++;
if (frameNum_ >= vulkan_->GetInflightFrames())

0 comments on commit 717ec23

Please sign in to comment.