4#include <vulkan/vulkan.h>
28namespace Vulkan {
class Drawer; }
58 std::vector<Pipeline*> pipelines,
59 const std::vector<std::reference_wrapper<StaticSet>>& globalSets,
60 const std::vector<std::reference_wrapper<DynamicSet>>& perObjectSets,
61 unsigned int framesInFlight = 2)
63 framesInFlight{ framesInFlight },
65 virtualGpu{ virtualGpu },
68 windowSurface{ windowSurface },
69 depthBuffer{ depthBuffer },
70 renderPass{ renderPass },
71 pipelines{ pipelines },
72 globalDescriptorSets{},
73 perObjectDescriptorSets{},
74 swapchain{ swapchain },
75 commandBufferPool{ commandBufferPool } ,
76 descriptorSetPool{ virtualGpu, framesInFlight*10, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER }{
80 for (
unsigned int i = 0; i < framesInFlight; ++i) {
81 fences.emplace_back(virtualGpu);
82 imageAvailableSemaphores.emplace_back(virtualGpu);
83 renderFinishedSemaphores.emplace_back(virtualGpu);
84 commandBuffers.emplace_back(virtualGpu, commandBufferPool);
85 globalDescriptorSets.emplace_back();
86 perObjectDescriptorSets.emplace_back();
90 for (
unsigned int j = 0; j < globalSets.size(); ++j) {
91 globalDescriptorSets[i].emplace_back(virtualGpu, descriptorSetPool, globalSets[j]);
92 perObjectDescriptorSets[i].emplace_back(virtualGpu, descriptorSetPool, perObjectSets[j]);
174 template<
template<
typename,
typename>
class... P>
requires (std::same_as<P<int, int>, std::pair<int, int>> && ...)
175 void draw(
const P<std::reference_wrapper<Buffers::VertexBuffer>, std::reference_wrapper<Buffers::IndexBuffer>>&... buffers) {
176 uint32_t obtainedSwapchainImageIndex{};
177 vkWaitForFences(+virtualGpu, 1, &+fences[currentFrame], VK_TRUE, UINT64_MAX);
179 if (VkResult result = vkAcquireNextImageKHR(+virtualGpu, +swapchain, UINT64_MAX, +imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &obtainedSwapchainImageIndex); result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
183 else if (result != VK_SUCCESS) {
186 vkResetFences(+virtualGpu, 1, &+fences[currentFrame]);
188 commandBuffers[currentFrame].reset(renderPass, framebuffers[obtainedSwapchainImageIndex]);
190 unsigned int counter = 0;
192 VkDeviceSize offsets[] = { 0 };
193 commandBuffers[currentFrame].addCommand(vkCmdBindPipeline, VK_PIPELINE_BIND_POINT_GRAPHICS, +*pipelines[counter]);
194 commandBuffers[currentFrame].addCommand(vkCmdBindVertexBuffers, 0, 1, &+vertexBuffer, offsets);
195 commandBuffers[currentFrame].addCommand(vkCmdBindIndexBuffer, +indexBuffer, 0, VK_INDEX_TYPE_UINT32);
196 commandBuffers[currentFrame].addCommand(vkCmdBindDescriptorSets, VK_PIPELINE_BIND_POINT_GRAPHICS, +pipelines[counter]->getLayout(), 0, 1, &+globalDescriptorSets[currentFrame][counter], 0,
nullptr);
197 for (
int i = 0; i < indexBuffer.getModelsCount(); ++i) {
198 commandBuffers[currentFrame].addCommand(vkCmdBindDescriptorSets, VK_PIPELINE_BIND_POINT_GRAPHICS, +pipelines[counter]->getLayout(), 1, 1, &+perObjectDescriptorSets[currentFrame][counter], perObjectDescriptorSets[currentFrame][counter].getSet().getAmountOfBindings(), perObjectDescriptorSets[currentFrame][counter].getSet().getDynamicDistances(i).data());
199 commandBuffers[currentFrame].addCommand(vkCmdDrawIndexed, indexBuffer.getModelIndexesCount(i), 1, indexBuffer.getModelOffset(i), 0, 0);
202 }(buffers.first, buffers.second), ...);
204 commandBuffers[currentFrame].addCommand(vkCmdEndRenderPass);
205 commandBuffers[currentFrame].endCommand();
208 std::vector<VkSemaphore> waitSemaphores = { +imageAvailableSemaphores[currentFrame] };
209 std::vector<VkSemaphore> signalSemaphores = { +renderFinishedSemaphores[currentFrame] };
210 std::vector<VkPipelineStageFlags> waitStages = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
211 commandBuffers[currentFrame].sendCommand(virtualGpu[
QueueFamily::GRAPHICS], waitSemaphores, signalSemaphores, waitStages, fences[currentFrame]);
214 std::vector<VkSwapchainKHR> swapchains = { +swapchain };
215 VkPresentInfoKHR presentInfo{};
216 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
217 presentInfo.waitSemaphoreCount = signalSemaphores.size();
218 presentInfo.pWaitSemaphores = signalSemaphores.data();
219 presentInfo.swapchainCount = swapchains.size();
220 presentInfo.pSwapchains = swapchains.data();
221 presentInfo.pImageIndices = &obtainedSwapchainImageIndex;
223 if (VkResult result = vkQueuePresentKHR(+virtualGpu[
QueueFamily::PRESENTATION], &presentInfo); result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
226 else if (result != VK_SUCCESS) {
230 increaseCurrentFrame();
238 void increaseCurrentFrame() {
239 currentFrame = (currentFrame + 1) % framesInFlight;
243 void recreateSwapchain() {
245 int width = 0, height = 0;
247 glfwGetFramebufferSize(+window, &width, &height);
249 }
while (width == 0 || height == 0);
251 vkDeviceWaitIdle(+virtualGpu);
254 swapchain = Swapchain(realGpu, virtualGpu, windowSurface, window, swapchain);
255 depthBuffer = DepthImage{ virtualGpu, realGpu, swapchain.
getResolution() };
257 commandBuffers = std::vector<CommandBuffer>{};
259 for (
unsigned int i = 0; i < framesInFlight; ++i) {
260 commandBuffers.emplace_back(virtualGpu, commandBufferPool);
269 unsigned int currentFrame;
270 unsigned int framesInFlight;
272 const LogicalDevice& virtualGpu;
273 const PhysicalDevice& realGpu;
274 const Window& window;
275 const WindowSurface& windowSurface;
276 const PipelineOptions::RenderPass& renderPass;
277 std::vector<Pipeline*> pipelines;
278 const CommandBufferPool& commandBufferPool;
280 Swapchain& swapchain;
281 DepthImage& depthBuffer;
282 std::vector<Framebuffer> framebuffers;
283 DescriptorSetPool descriptorSetPool;
285 std::vector<SynchronizationPrimitives::Fence> fences;
286 std::vector<SynchronizationPrimitives::Semaphore> imageAvailableSemaphores;
287 std::vector<SynchronizationPrimitives::Semaphore> renderFinishedSemaphores;
288 std::vector<CommandBuffer> commandBuffers;
289 std::vector<std::vector<DescriptorSet<StaticSet>>> globalDescriptorSets;
290 std::vector<std::vector<DescriptorSet<DynamicSet>>> perObjectDescriptorSets;
Definition: IndexBuffer.h:15
Definition: VertexBuffer.h:16
A CommandBufferPool is an object which is used to allocate CommandBuffers.
Definition: CommandBufferPool.h:14
Definition: DepthImage.h:13
A Drawer is a class which holds all of the resources to draw frames on screen, such as the synchroniz...
Definition: Drawer.h:34
Drawer(const LogicalDevice &virtualGpu, const PhysicalDevice &realGpu, const Window &window, const WindowSurface &windowSurface, Swapchain &swapchain, DepthImage &depthBuffer, const CommandBufferPool &commandBufferPool, const PipelineOptions::RenderPass &renderPass, std::vector< Pipeline * > pipelines, const std::vector< std::reference_wrapper< StaticSet > > &globalSets, const std::vector< std::reference_wrapper< DynamicSet > > &perObjectSets, unsigned int framesInFlight=2)
Creates all the resources needed to draw something on screen.
Definition: Drawer.h:50
void draw(const P< std::reference_wrapper< Buffers::VertexBuffer >, std::reference_wrapper< Buffers::IndexBuffer > > &... buffers)
Draws the vertexBuffer by running the specified commands.
Definition: Drawer.h:175
static std::vector< Framebuffer > generateFramebufferForEachSwapchainImageView(const LogicalDevice &virtualGpu, const PipelineOptions::RenderPass &renderPass, const Swapchain &swapchain, const IV &... otherAttachments)
Creates a framebuffer for each image view in the specified swapchain. It also attaches the specified ...
Definition: Framebuffer.h:88
A logical device is an abstraction of the physical GPU which we can mainly use to send commands.
Definition: LogicalDevice.h:15
Represents the GPU (or any other device) that will be used with Vulkan to perform computer graphics.
Definition: PhysicalDevice.h:17
A RenderPass is the set of attachments, the way they are used, and the rendering work that is perform...
Definition: RenderPass.h:20
Object which holds images to be presented to the WindowSurface.
Definition: Swapchain.h:19
std::pair< unsigned int, unsigned int > getResolution() const
Returns the width and height of the images in this swapchain.
Definition: Swapchain.cpp:95
Generic runtime exception thrown by Vulkan-related functions.
Definition: VulkanException.h:13
Manages the creation and lifetime of an OS window.
Definition: Window.h:15
A window surface is the connection between Vulkan and the OS windows environment.
Definition: WindowSurface.h:13
Types of queue families.
Definition: Animations.h:17