diff --git a/NothinFancy/src/client/render/RenderEngine.cpp b/NothinFancy/src/client/render/RenderEngine.cpp index 8e2b961..0fd0f3e 100644 --- a/NothinFancy/src/client/render/RenderEngine.cpp +++ b/NothinFancy/src/client/render/RenderEngine.cpp @@ -50,9 +50,10 @@ namespace nf::client::render { createOutputRenderPass(); createSwapchainFramebuffers(); createOutputPipeline(); - createVertexBuffer(); createFrameExecutors(); + createVertexBuffer(); + m_window->show(); } @@ -413,50 +414,6 @@ namespace nf::client::render { NFError("Could not create graphics pipeline."); } - void RenderEngine::createVertexBuffer() { - std::vector triangleData = { - {{0.0, -0.5}, {1.0, 0.0, 0.0}}, - {{0.5, 0.5}, {0.0, 1.0, 0.0}}, - {{-0.5, 0.5}, {0.0, 0.0, 1.0}} - }; - - VkBufferCreateInfo bufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - bufferCI.size = sizeof(triangleData[0]) * triangleData.size(); - bufferCI.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - - if (vkCreateBuffer(m_device, &bufferCI, nullptr, &m_bufferVertex) != VK_SUCCESS) - NFError("Could not create vertex buffer."); - - VkMemoryRequirements memoryRequirements = {}; - vkGetBufferMemoryRequirements(m_device, m_bufferVertex, &memoryRequirements); - - VkPhysicalDeviceMemoryProperties memoryProperties = {}; - vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memoryProperties); - - VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - std::optional memoryTypeIndex; - for (int i = 0; i < memoryProperties.memoryTypeCount; i++) - if (memoryRequirements.memoryTypeBits & (1 << i) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) - memoryTypeIndex = i; - - if (!memoryTypeIndex.has_value()) - NFError("Could not find suitable memory type."); - - VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - allocateInfo.allocationSize = memoryRequirements.size; - allocateInfo.memoryTypeIndex = memoryTypeIndex.value(); - - if (vkAllocateMemory(m_device, &allocateInfo, nullptr, &m_memoryVertexBuffer) != VK_SUCCESS) - NFError("Could not allocate video memory."); - - vkBindBufferMemory(m_device, m_bufferVertex, m_memoryVertexBuffer, 0); - - void* bufferPointer = nullptr; - vkMapMemory(m_device, m_memoryVertexBuffer, 0, bufferCI.size, 0, &bufferPointer); - std::memcpy(bufferPointer, triangleData.data(), bufferCI.size); - vkUnmapMemory(m_device, m_memoryVertexBuffer); - } - void RenderEngine::createFrameExecutors() { VkCommandPoolCreateInfo commandPoolCI = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; @@ -486,6 +443,109 @@ namespace nf::client::render { } } + void RenderEngine::createVertexBuffer() { + std::vector triangleData = { + {{0.0, -0.5}, {1.0, 0.0, 0.0}}, + {{0.5, 0.5}, {0.0, 1.0, 0.0}}, + {{-0.5, 0.5}, {0.0, 0.0, 1.0}} + }; + + VkBuffer stagingBuffer = nullptr; + VkBufferCreateInfo bufferCI = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + bufferCI.size = sizeof(triangleData[0]) * triangleData.size(); + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + if (vkCreateBuffer(m_device, &bufferCI, nullptr, &stagingBuffer) != VK_SUCCESS) + NFError("Could not create vertex buffer."); + + VkMemoryRequirements memoryRequirements = {}; + vkGetBufferMemoryRequirements(m_device, stagingBuffer, &memoryRequirements); + + VkPhysicalDeviceMemoryProperties memoryProperties = {}; + vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memoryProperties); + + VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + std::optional memoryTypeIndex; + for (int i = 0; i < memoryProperties.memoryTypeCount; i++) + if (memoryRequirements.memoryTypeBits & (1 << i) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + memoryTypeIndex = i; + + if (!memoryTypeIndex.has_value()) + NFError("Could not find suitable memory type."); + + VkDeviceMemory stagingBufferMemory = nullptr; + VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + allocateInfo.allocationSize = memoryRequirements.size; + allocateInfo.memoryTypeIndex = memoryTypeIndex.value(); + + if (vkAllocateMemory(m_device, &allocateInfo, nullptr, &stagingBufferMemory) != VK_SUCCESS) + NFError("Could not allocate video memory."); + + vkBindBufferMemory(m_device, stagingBuffer, stagingBufferMemory, 0); + + void* bufferPointer = nullptr; + vkMapMemory(m_device, stagingBufferMemory, 0, bufferCI.size, 0, &bufferPointer); + std::memcpy(bufferPointer, triangleData.data(), bufferCI.size); + vkUnmapMemory(m_device, stagingBufferMemory); + + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + if (vkCreateBuffer(m_device, &bufferCI, nullptr, &m_bufferVertex) != VK_SUCCESS) + NFError("Could not create vertex buffer."); + + vkGetBufferMemoryRequirements(m_device, m_bufferVertex, &memoryRequirements); + + properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + memoryTypeIndex.reset(); + for (int i = 0; i < memoryProperties.memoryTypeCount; i++) + if (memoryRequirements.memoryTypeBits & (1 << i) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + memoryTypeIndex = i; + + if (!memoryTypeIndex.has_value()) + NFError("Could not find suitable memory type."); + + allocateInfo.allocationSize = memoryRequirements.size; + allocateInfo.memoryTypeIndex = memoryTypeIndex.value(); + + if (vkAllocateMemory(m_device, &allocateInfo, nullptr, &m_memoryVertexBuffer) != VK_SUCCESS) + NFError("Could not allocate video memory."); + + vkBindBufferMemory(m_device, m_bufferVertex, m_memoryVertexBuffer, 0); + + VkCommandBuffer commandBuffer = nullptr; + VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + commandBufferAI.commandPool = m_commandPool; + commandBufferAI.commandBufferCount = 1; + + if (vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer) != VK_SUCCESS) + NFError("Could not create command buffer."); + + VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + if (vkBeginCommandBuffer(commandBuffer, &commandBufferBI) != VK_SUCCESS) + NFError("Could not begin recording command buffer."); + + VkBufferCopy bufferCopyRegion = {}; + bufferCopyRegion.size = bufferCI.size; + vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_bufferVertex, 1, &bufferCopyRegion); + + if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) + NFError("Could not end command buffer."); + + VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + if (vkQueueSubmit(m_queueGraphics, 1, &submitInfo, nullptr) != VK_SUCCESS) + NFError("Could not submit to Vulkan queue."); + + vkQueueWaitIdle(m_queueGraphics); + + vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer); + vkFreeMemory(m_device, stagingBufferMemory, nullptr); + vkDestroyBuffer(m_device, stagingBuffer, nullptr); + } + void RenderEngine::doFrame() { // Get current frame executor auto& [commandBuffer, semaphoreImageAvailable, semaphoreRenderFinished, fenceFrameInFlight] = m_frameExecutors[m_currentFrameExecutor]; diff --git a/NothinFancy/src/client/render/RenderEngine.h b/NothinFancy/src/client/render/RenderEngine.h index ee89fac..42e2e0a 100644 --- a/NothinFancy/src/client/render/RenderEngine.h +++ b/NothinFancy/src/client/render/RenderEngine.h @@ -28,9 +28,10 @@ namespace nf::client::render { void createOutputRenderPass(); void createSwapchainFramebuffers(); void createOutputPipeline(); - void createVertexBuffer(); void createFrameExecutors(); + void createVertexBuffer(); + void recreateSwapchain(); void destroySwapchain();