vulkan: don't use dynamic rendering

This commit is contained in:
niki
2022-08-20 15:49:09 +02:00
parent 51e3cf2a9c
commit 4660466887
2 changed files with 147 additions and 50 deletions
+110 -32
View File
@@ -146,7 +146,7 @@ void Graphics::present(void* screenshotCallbackdata) {
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores.at(currentFrame) }; VkSemaphore waitSemaphores[] = { imageAvailableSemaphores.at(currentFrame) };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages; submitInfo.pWaitDstStageMask = waitStages;
@@ -823,7 +823,7 @@ void Graphics::createLogicalDevice() {
VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeature{}; VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeature{};
dynamicRenderingFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; dynamicRenderingFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES;
dynamicRenderingFeature.dynamicRendering = VK_TRUE; dynamicRenderingFeature.dynamicRendering = VK_FALSE;
VkPhysicalDeviceFeatures deviceFeatures{}; VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.samplerAnisotropy = VK_TRUE; deviceFeatures.samplerAnisotropy = VK_TRUE;
@@ -1047,6 +1047,43 @@ void Graphics::createImageViews() {
} }
} }
std::vector<VkFramebuffer> Graphics::createSwapChainFramebuffers(VkRenderPass renderPass) {
std::vector<VkFramebuffer> swapChainFramebuffers;
swapChainFramebuffers.resize(swapChainImageViews.size());
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
VkImageView attachments[] = {
swapChainImageViews[i]
};
VkFramebufferCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
createInfo.renderPass = renderPass;
createInfo.attachmentCount = 1;
createInfo.pAttachments = attachments;
createInfo.width = swapChainExtent.width;
createInfo.height = swapChainExtent.height;
createInfo.layers = 1;
if (vkCreateFramebuffer(device, &createInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
throw love::Exception("failed to create framebuffer");
}
}
return swapChainFramebuffers;
}
VkFramebuffer Graphics::getSwapChainFramebuffer(VkRenderPass renderPass) {
auto it = swapChainFramebufferVector.find(renderPass);
if (it != swapChainFramebufferVector.end()) {
return it->second.at(imageIndex);
} else {
auto frameBuffers = createSwapChainFramebuffers(renderPass);
swapChainFramebufferVector[renderPass] = frameBuffers;
return frameBuffers.at(imageIndex);
}
}
void Graphics::createDefaultShaders() { void Graphics::createDefaultShaders() {
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) { for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) {
auto stype = (Shader::StandardShader)i; auto stype = (Shader::StandardShader)i;
@@ -1060,6 +1097,41 @@ void Graphics::createDefaultShaders() {
} }
} }
VkRenderPass Graphics::createRenderPass(RenderPassConfiguration configuration) {
VkAttachmentDescription colorDescription{};
colorDescription.format = configuration.frameBufferFormat;
colorDescription.samples = VK_SAMPLE_COUNT_1_BIT;
colorDescription.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorDescription.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subPass{};
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subPass.colorAttachmentCount = 1;
subPass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.attachmentCount = 1;
createInfo.pAttachments = &colorDescription;
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subPass;
VkRenderPass renderPass;
if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS) {
throw love::Exception("failed to create render pass");
}
return renderPass;
}
bool Graphics::usesConstantVertexColor(const VertexAttributes& vertexAttributes) { bool Graphics::usesConstantVertexColor(const VertexAttributes& vertexAttributes) {
return !!(vertexAttributes.enableBits & (1u << ATTRIB_COLOR)); return !!(vertexAttributes.enableBits & (1u << ATTRIB_COLOR));
} }
@@ -1135,6 +1207,7 @@ void Graphics::createVulkanVertexFormat(
void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType, CullMode cullmode) { void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType, CullMode cullmode) {
GraphicsPipelineConfiguration configuration; GraphicsPipelineConfiguration configuration;
configuration.renderPass = currentRenderPass;
configuration.vertexAttributes = attributes; configuration.vertexAttributes = attributes;
configuration.shader = (Shader*)Shader::current; configuration.shader = (Shader*)Shader::current;
configuration.primitiveType = primitiveType; configuration.primitiveType = primitiveType;
@@ -1143,7 +1216,6 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi
configuration.colorChannelMask = states.back().colorMask; configuration.colorChannelMask = states.back().colorMask;
configuration.winding = states.back().winding; configuration.winding = states.back().winding;
configuration.cullmode = cullmode; configuration.cullmode = cullmode;
configuration.framebufferFormat = currentFramebufferOutputFormat;
configuration.viewportWidth = currentViewportWidth; configuration.viewportWidth = currentViewportWidth;
configuration.viewportHeight = currentViewportHeight; configuration.viewportHeight = currentViewportHeight;
if (states.back().scissor) { if (states.back().scissor) {
@@ -1183,46 +1255,59 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi
} }
void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) { void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
VkRenderingAttachmentInfo colorAttachmentInfo{}; RenderPassConfiguration renderPassConfiguration{};
colorAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorAttachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
if (texture) { if (texture) {
colorAttachmentInfo.imageView = (VkImageView)texture->getRenderTargetHandle();
auto vulkanFormat = Vulkan::getTextureFormat(texture->getPixelFormat()); auto vulkanFormat = Vulkan::getTextureFormat(texture->getPixelFormat());
currentFramebufferOutputFormat = vulkanFormat.internalFormat; currentFramebufferOutputFormat = vulkanFormat.internalFormat;
renderPassConfiguration.frameBufferFormat = vulkanFormat.internalFormat;
renderTargetTexture = texture; renderTargetTexture = texture;
} else { } else {
colorAttachmentInfo.imageView = swapChainImageViews[imageIndex];
currentFramebufferOutputFormat = swapChainImageFormat; currentFramebufferOutputFormat = swapChainImageFormat;
renderPassConfiguration.frameBufferFormat = swapChainImageFormat;
renderTargetTexture = nullptr; renderTargetTexture = nullptr;
} }
colorAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
VkRenderingInfo renderingInfo{};
renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
renderingInfo.renderArea.extent.width = w;
renderingInfo.renderArea.extent.height = h;
renderingInfo.layerCount = 1;
renderingInfo.colorAttachmentCount = 1;
renderingInfo.pColorAttachments = &colorAttachmentInfo;
currentViewportWidth = (float)w; currentViewportWidth = (float)w;
currentViewportHeight = (float)h; currentViewportHeight = (float)h;
if (renderTargetTexture) { VkRenderPass renderPass;
auto it = renderPasses.find(renderPassConfiguration);
if (it != renderPasses.end()) {
renderPass = it->second;
} else {
renderPass = createRenderPass(renderPassConfiguration);
renderPasses[renderPassConfiguration] = renderPass;
}
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
if (renderTargetTexture == nullptr) {
renderPassInfo.framebuffer = getSwapChainFramebuffer(renderPass);
} else {
renderPassInfo.framebuffer = (VkFramebuffer) texture->getRenderTargetHandle();
}
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent.width = static_cast<uint32_t>(w);
renderPassInfo.renderArea.extent.height = static_cast<uint32_t>(h);
if (renderTargetTexture) {
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)texture->getHandle(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)texture->getHandle(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
} }
vkCmdBeginRendering(commandBuffers.at(currentFrame), &renderingInfo); vkCmdBeginRenderPass(commandBuffers.at(currentFrame), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
currentRenderPass = renderPass;
currentGraphicsPipeline = VK_NULL_HANDLE; currentGraphicsPipeline = VK_NULL_HANDLE;
} }
void Graphics::endRenderPass() { void Graphics::endRenderPass() {
vkCmdEndRendering(commandBuffers.at(currentFrame)); vkCmdEndRenderPass(commandBuffers.at(currentFrame));
currentRenderPass = VK_NULL_HANDLE;
if (renderTargetTexture) { if (renderTargetTexture) {
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)renderTargetTexture->getHandle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)renderTargetTexture->getHandle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@@ -1366,13 +1451,6 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
colorBlending.blendConstants[2] = 0.0f; colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f; colorBlending.blendConstants[3] = 0.0f;
VkFormat framebufferOutputFormat = configuration.framebufferFormat;
VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{};
pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
pipelineRenderingCreateInfo.colorAttachmentCount = 1;
pipelineRenderingCreateInfo.pColorAttachmentFormats = &framebufferOutputFormat;
VkGraphicsPipelineCreateInfo pipelineInfo{}; VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size()); pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
@@ -1389,7 +1467,7 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
pipelineInfo.subpass = 0; pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1; pipelineInfo.basePipelineIndex = -1;
pipelineInfo.pNext = &pipelineRenderingCreateInfo; pipelineInfo.renderPass = configuration.renderPass;
VkPipeline graphicsPipeline; VkPipeline graphicsPipeline;
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
@@ -1522,9 +1600,9 @@ void Graphics::cleanup() {
} }
void Graphics::cleanupSwapChain() { void Graphics::cleanupSwapChain() {
for (size_t i = 0; i < swapChainImageViews.size(); i++) { for (auto & swapChainImageView : swapChainImageViews) {
vkDestroyImageView(device, swapChainImageViews[i], nullptr); vkDestroyImageView(device, swapChainImageView, nullptr);
} }
vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroySwapchainKHR(device, swapChain, nullptr);
} }
+21 -2
View File
@@ -24,7 +24,22 @@
namespace love { namespace love {
namespace graphics { namespace graphics {
namespace vulkan { namespace vulkan {
struct RenderPassConfiguration {
VkFormat frameBufferFormat;
bool operator==(const RenderPassConfiguration& conf) const {
return memcmp(this, &conf, sizeof(RenderPassConfiguration)) == 0;
}
};
struct RenderPassConfigurationHasher {
size_t operator()(const RenderPassConfiguration &configuration) const {
return XXH32(&configuration, sizeof(RenderPassConfiguration), 0);
}
};
struct GraphicsPipelineConfiguration { struct GraphicsPipelineConfiguration {
VkRenderPass renderPass;
VertexAttributes vertexAttributes; VertexAttributes vertexAttributes;
Shader* shader = nullptr; Shader* shader = nullptr;
PrimitiveType primitiveType = PRIMITIVE_MAX_ENUM; PrimitiveType primitiveType = PRIMITIVE_MAX_ENUM;
@@ -33,7 +48,6 @@ struct GraphicsPipelineConfiguration {
ColorChannelMask colorChannelMask; ColorChannelMask colorChannelMask;
Winding winding; Winding winding;
CullMode cullmode; CullMode cullmode;
VkFormat framebufferFormat;
float viewportWidth; float viewportWidth;
float viewportHeight; float viewportHeight;
std::optional<Rect> scissorRect; std::optional<Rect> scissorRect;
@@ -172,7 +186,10 @@ private:
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
void createSwapChain(); void createSwapChain();
void createImageViews(); void createImageViews();
std::vector<VkFramebuffer> createSwapChainFramebuffers(VkRenderPass);
VkFramebuffer getSwapChainFramebuffer(VkRenderPass);
void createDefaultShaders(); void createDefaultShaders();
VkRenderPass createRenderPass(RenderPassConfiguration);
VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration); VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration);
void createCommandPool(); void createCommandPool();
void createCommandBuffers(); void createCommandBuffers();
@@ -207,8 +224,10 @@ private:
VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED; VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
VkExtent2D swapChainExtent = VkExtent2D(); VkExtent2D swapChainExtent = VkExtent2D();
std::vector<VkImageView> swapChainImageViews; std::vector<VkImageView> swapChainImageViews;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; std::unordered_map<VkRenderPass, std::vector<VkFramebuffer>> swapChainFramebufferVector;
VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE; VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE;
VkRenderPass currentRenderPass = VK_NULL_HANDLE;
std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines; std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines;
std::unordered_map<SamplerState, VkSampler, SamplerStateHasher> samplers; std::unordered_map<SamplerState, VkSampler, SamplerStateHasher> samplers;
VkCommandPool commandPool = VK_NULL_HANDLE; VkCommandPool commandPool = VK_NULL_HANDLE;