1
0
Fork 0
Univerxel/src/client/render/vk/CommandCenter.cpp

140 lines
5.4 KiB
C++

#include "CommandCenter.hpp"
#include "PhysicalDeviceInfo.hpp"
#include "../Renderer.hpp"
#include "buffer/VertexData.hpp"
using namespace render::vk;
CommandCenter::CommandCenter(VkDevice device, const std::vector<VkImageView> &views, PipelineRef pipe,
std::pair<VkBuffer, VkBuffer> buffer, const PhysicalDeviceInfo &info, const renderOptions &opt) : device(device) {
{
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
poolInfo.flags = 0;
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
FATAL("Failed to create graphics pool!");
}
}
allocate(views, pipe, buffer, info.swapDetails.capabilities.currentExtent, opt);
}
CommandCenter::~CommandCenter() {
if(!freed)
free();
vkDestroyCommandPool(device, graphicsPool, ALLOC);
}
void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, std::pair<VkBuffer, VkBuffer> buffer, VkExtent2D extent,
const renderOptions& opt)
{
assert(freed);
framebuffers.resize(views.size());
for (size_t i = 0; i < views.size(); i++) {
VkImageView attachments[] = { views[i] };
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = pipe.first;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = extent.width;
framebufferInfo.height = extent.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(device, &framebufferInfo, ALLOC, &framebuffers[i]) != VK_SUCCESS) {
FATAL("Failed to create framebuffer!");
}
}
{
graphicsBuffers.resize(framebuffers.size());
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = graphicsPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = (uint32_t) graphicsBuffers.size();
if (vkAllocateCommandBuffers(device, &allocInfo, graphicsBuffers.data()) != VK_SUCCESS) {
FATAL("Failed to allocate graphics buffers!");
}
}
for (size_t i = 0; i < graphicsBuffers.size(); i++) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr;
if (vkBeginCommandBuffer(graphicsBuffers[i], &beginInfo) != VK_SUCCESS) {
FATAL("Failed to begin recording command buffer!");
}
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = pipe.first;
renderPassInfo.framebuffer = framebuffers[i];
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = extent;
VkClearValue clearColor = {opt.clear_color.x, opt.clear_color.y, opt.clear_color.z, opt.clear_color.a};
renderPassInfo.clearValueCount = 1; //TODO: clear depth
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
VkBuffer vertexBuffers[] = {buffer.first};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(graphicsBuffers[i], buffer.second, 0, VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(graphicsBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(graphicsBuffers[i]);
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
FATAL("Failed to record graphics buffer!");
}
}
freed = false;
}
void CommandCenter::free() {
assert(!freed);
for (size_t i = 0; i < framebuffers.size(); i++) {
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
}
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
freed = true;
}
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
assert(!freed);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {waitSemaphore};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &graphicsBuffers[idx];
VkSemaphore signalSemaphores[] = {signalSemaphore};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &submittedFence);
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, submittedFence) != VK_SUCCESS) {
FATAL("Failed to submit draw command buffer!");
}
}