Add doFrame function
This commit is contained in:
parent
ebe78cb4ca
commit
c5e1a66e36
@ -19,8 +19,7 @@ namespace nf::client {
|
|||||||
m_renderEngine = std::make_unique<render::RenderEngine>(std::move(windowFuture.get()), m_config.display);
|
m_renderEngine = std::make_unique<render::RenderEngine>(std::move(windowFuture.get()), m_config.display);
|
||||||
|
|
||||||
while (m_running) {
|
while (m_running) {
|
||||||
NFLog("Client running...");
|
m_renderEngine->doFrame();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputThread.join();
|
inputThread.join();
|
||||||
|
@ -107,11 +107,6 @@ namespace nf::client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
DestroyWindow(hWnd);
|
|
||||||
NFLog("Window destroyed");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -127,4 +122,9 @@ namespace nf::client {
|
|||||||
int width = cli.right - cli.left, height = cli.bottom - cli.top;
|
int width = cli.right - cli.left, height = cli.bottom - cli.top;
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window::~Window() {
|
||||||
|
DestroyWindow(m_handle);
|
||||||
|
NFLog("Window destroyed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ namespace nf::client {
|
|||||||
void setDisplay(DisplayConfig config);
|
void setDisplay(DisplayConfig config);
|
||||||
void runLoop();
|
void runLoop();
|
||||||
void show(bool show = true);
|
void show(bool show = true);
|
||||||
|
|
||||||
|
~Window();
|
||||||
private:
|
private:
|
||||||
void registerWindowClass();
|
void registerWindowClass();
|
||||||
static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
@ -281,11 +281,19 @@ namespace nf::client::render {
|
|||||||
subpassDescription.colorAttachmentCount = 1;
|
subpassDescription.colorAttachmentCount = 1;
|
||||||
subpassDescription.pColorAttachments = &outputColorAttachmentReference;
|
subpassDescription.pColorAttachments = &outputColorAttachmentReference;
|
||||||
|
|
||||||
|
VkSubpassDependency dependency = {};
|
||||||
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassCI = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
|
VkRenderPassCreateInfo renderPassCI = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
|
||||||
renderPassCI.attachmentCount = 1;
|
renderPassCI.attachmentCount = 1;
|
||||||
renderPassCI.pAttachments = &outputColorAttachment;
|
renderPassCI.pAttachments = &outputColorAttachment;
|
||||||
renderPassCI.subpassCount = 1;
|
renderPassCI.subpassCount = 1;
|
||||||
renderPassCI.pSubpasses = &subpassDescription;
|
renderPassCI.pSubpasses = &subpassDescription;
|
||||||
|
renderPassCI.dependencyCount = 1;
|
||||||
|
renderPassCI.pDependencies = &dependency;
|
||||||
|
|
||||||
if (vkCreateRenderPass(m_device, &renderPassCI, nullptr, &m_renderPassOutput) != VK_SUCCESS)
|
if (vkCreateRenderPass(m_device, &renderPassCI, nullptr, &m_renderPassOutput) != VK_SUCCESS)
|
||||||
NFError("Could not create Vulkan output render pass.");
|
NFError("Could not create Vulkan output render pass.");
|
||||||
@ -375,8 +383,7 @@ namespace nf::client::render {
|
|||||||
framebufferCI.renderPass = m_renderPassOutput;
|
framebufferCI.renderPass = m_renderPassOutput;
|
||||||
framebufferCI.attachmentCount = 1;
|
framebufferCI.attachmentCount = 1;
|
||||||
framebufferCI.pAttachments = &m_swapchainImageViews[i];
|
framebufferCI.pAttachments = &m_swapchainImageViews[i];
|
||||||
framebufferCI.width = m_display.width;
|
framebufferCI.width = m_display.width, framebufferCI.height = m_display.height;
|
||||||
framebufferCI.height = m_display.height;
|
|
||||||
framebufferCI.layers = 1;
|
framebufferCI.layers = 1;
|
||||||
|
|
||||||
if (vkCreateFramebuffer(m_device, &framebufferCI, nullptr, &m_swapchainFramebuffers[i]) != VK_SUCCESS)
|
if (vkCreateFramebuffer(m_device, &framebufferCI, nullptr, &m_swapchainFramebuffers[i]) != VK_SUCCESS)
|
||||||
@ -407,11 +414,84 @@ namespace nf::client::render {
|
|||||||
NFError("Could not create semaphore.");
|
NFError("Could not create semaphore.");
|
||||||
|
|
||||||
VkFenceCreateInfo fenceCI = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
|
VkFenceCreateInfo fenceCI = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
|
||||||
|
fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
if (vkCreateFence(m_device, &fenceCI, nullptr, &m_fenceInFlight) != VK_SUCCESS)
|
if (vkCreateFence(m_device, &fenceCI, nullptr, &m_fenceInFlight) != VK_SUCCESS)
|
||||||
NFError("Could not create fence.");
|
NFError("Could not create fence.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderEngine::doFrame() {
|
||||||
|
// First, wait for previous frame to complete
|
||||||
|
vkWaitForFences(m_device, 1, &m_fenceInFlight, VK_TRUE, UINT64_MAX);
|
||||||
|
vkResetFences(m_device, 1, &m_fenceInFlight);
|
||||||
|
|
||||||
|
// Get next swapchain image
|
||||||
|
uint32_t nextImageIndex = 0;
|
||||||
|
vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_semaphoreImageAvailable, nullptr, &nextImageIndex);
|
||||||
|
|
||||||
|
// Begin recording
|
||||||
|
VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||||
|
|
||||||
|
if (vkBeginCommandBuffer(m_commandBuffer, &commandBufferBI) != VK_SUCCESS)
|
||||||
|
NFError("Could not begin recording command buffer.");
|
||||||
|
|
||||||
|
// Start the render pass
|
||||||
|
VkClearValue black = { {{0.0, 0.0, 0.0, 1.0}} };
|
||||||
|
VkRenderPassBeginInfo renderPassBI = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||||
|
renderPassBI.renderPass = m_renderPassOutput;
|
||||||
|
renderPassBI.framebuffer = m_swapchainFramebuffers[nextImageIndex];
|
||||||
|
renderPassBI.renderArea.extent = { m_display.width, m_display.height };
|
||||||
|
renderPassBI.clearValueCount = 1;
|
||||||
|
renderPassBI.pClearValues = &black;
|
||||||
|
vkCmdBeginRenderPass(m_commandBuffer, &renderPassBI, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
// Bind output pipeline
|
||||||
|
vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineOutput);
|
||||||
|
|
||||||
|
// Set viewport
|
||||||
|
VkViewport viewport = {};
|
||||||
|
viewport.width = static_cast<float>(m_display.width), viewport.height = static_cast<float>(m_display.height);
|
||||||
|
viewport.maxDepth = 1.0;
|
||||||
|
vkCmdSetViewport(m_commandBuffer, 0, 1, &viewport);
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
vkCmdDraw(m_commandBuffer, 3, 1, 0, 0);
|
||||||
|
|
||||||
|
// End the render pass
|
||||||
|
vkCmdEndRenderPass(m_commandBuffer);
|
||||||
|
|
||||||
|
// Finish recording
|
||||||
|
if (vkEndCommandBuffer(m_commandBuffer) != VK_SUCCESS)
|
||||||
|
NFError("Could not end command buffer.");
|
||||||
|
|
||||||
|
// Submit to graphics queue
|
||||||
|
VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||||
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
|
submitInfo.pWaitSemaphores = &m_semaphoreImageAvailable;
|
||||||
|
submitInfo.pWaitDstStageMask = &waitStage;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &m_commandBuffer;
|
||||||
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
|
submitInfo.pSignalSemaphores = &m_semaphoreRenderFinished;
|
||||||
|
|
||||||
|
if (vkQueueSubmit(m_queueGraphics, 1, &submitInfo, m_fenceInFlight) != VK_SUCCESS)
|
||||||
|
NFError("Could not submit to Vulkan queue.");
|
||||||
|
|
||||||
|
// And present!
|
||||||
|
VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
|
||||||
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
|
presentInfo.pWaitSemaphores = &m_semaphoreRenderFinished;
|
||||||
|
presentInfo.swapchainCount = 1;
|
||||||
|
presentInfo.pSwapchains = &m_swapchain;
|
||||||
|
presentInfo.pImageIndices = &nextImageIndex;
|
||||||
|
|
||||||
|
vkQueuePresentKHR(m_queuePresent, &presentInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderEngine::~RenderEngine() {
|
RenderEngine::~RenderEngine() {
|
||||||
|
vkDeviceWaitIdle(m_device);
|
||||||
|
|
||||||
vkDestroyFence(m_device, m_fenceInFlight, nullptr);
|
vkDestroyFence(m_device, m_fenceInFlight, nullptr);
|
||||||
vkDestroySemaphore(m_device, m_semaphoreRenderFinished, nullptr);
|
vkDestroySemaphore(m_device, m_semaphoreRenderFinished, nullptr);
|
||||||
vkDestroySemaphore(m_device, m_semaphoreImageAvailable, nullptr);
|
vkDestroySemaphore(m_device, m_semaphoreImageAvailable, nullptr);
|
||||||
|
@ -9,6 +9,8 @@ namespace nf::client::render {
|
|||||||
public:
|
public:
|
||||||
RenderEngine(std::shared_ptr<Window> window, DisplayConfig display);
|
RenderEngine(std::shared_ptr<Window> window, DisplayConfig display);
|
||||||
|
|
||||||
|
void doFrame();
|
||||||
|
|
||||||
~RenderEngine();
|
~RenderEngine();
|
||||||
private:
|
private:
|
||||||
void createInstance();
|
void createInstance();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user