vulkan: remove dynamic rendering (part 2)

This commit is contained in:
niki
2022-08-20 16:38:13 +02:00
parent 4660466887
commit 3e762c9772
2 changed files with 70 additions and 55 deletions
+50 -51
View File
@@ -46,7 +46,7 @@ constexpr bool enableValidationLayers = true;
constexpr int MAX_FRAMES_IN_FLIGHT = 2; constexpr int MAX_FRAMES_IN_FLIGHT = 2;
constexpr uint32_t vulkanApiVersion = VK_API_VERSION_1_3; constexpr uint32_t vulkanApiVersion = VK_API_VERSION_1_0;
const char* Graphics::getName() const { const char* Graphics::getName() const {
return "love.graphics.vulkan"; return "love.graphics.vulkan";
@@ -821,10 +821,6 @@ void Graphics::createLogicalDevice() {
queueCreateInfos.push_back(queueCreateInfo); queueCreateInfos.push_back(queueCreateInfo);
} }
VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeature{};
dynamicRenderingFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES;
dynamicRenderingFeature.dynamicRendering = VK_FALSE;
VkPhysicalDeviceFeatures deviceFeatures{}; VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.samplerAnisotropy = VK_TRUE; deviceFeatures.samplerAnisotropy = VK_TRUE;
deviceFeatures.fillModeNonSolid = VK_TRUE; deviceFeatures.fillModeNonSolid = VK_TRUE;
@@ -834,7 +830,6 @@ void Graphics::createLogicalDevice() {
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()); createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data(); createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures; createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.pNext = &dynamicRenderingFeature;
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data(); createInfo.ppEnabledExtensionNames = deviceExtensions.data();
@@ -1047,41 +1042,37 @@ void Graphics::createImageViews() {
} }
} }
std::vector<VkFramebuffer> Graphics::createSwapChainFramebuffers(VkRenderPass renderPass) { VkFramebuffer Graphics::createFramebuffer(FramebufferConfiguration configuration) {
std::vector<VkFramebuffer> swapChainFramebuffers; VkImageView attachments[] = {
swapChainFramebuffers.resize(swapChainImageViews.size()); configuration.imageView
};
for (size_t i = 0; i < swapChainImageViews.size(); i++) { VkFramebufferCreateInfo createInfo{};
VkImageView attachments[] = { createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
swapChainImageViews[i] createInfo.renderPass = configuration.renderPass;
}; createInfo.attachmentCount = 1;
createInfo.pAttachments = attachments;
createInfo.width = configuration.width;
createInfo.height = configuration.height;
createInfo.layers = 1; // is this correct?
VkFramebufferCreateInfo createInfo{}; VkFramebuffer frameBuffer;
createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; if (vkCreateFramebuffer(device, &createInfo, nullptr, &frameBuffer) != VK_SUCCESS) {
createInfo.renderPass = renderPass; throw love::Exception("failed to create framebuffer");
createInfo.attachmentCount = 1; }
createInfo.pAttachments = attachments; return frameBuffer;
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) { VkFramebuffer Graphics::getFramebuffer(FramebufferConfiguration configuration) {
auto it = swapChainFramebufferVector.find(renderPass); auto it = framebuffers.find(configuration);
if (it != swapChainFramebufferVector.end()) { if (it != framebuffers.end()) {
return it->second.at(imageIndex); return it->second;
} else { }
auto frameBuffers = createSwapChainFramebuffers(renderPass); else {
swapChainFramebufferVector[renderPass] = frameBuffers; VkFramebuffer framebuffer = createFramebuffer(configuration);
return frameBuffers.at(imageIndex); framebuffers[configuration] = framebuffer;
} return framebuffer;
}
} }
void Graphics::createDefaultShaders() { void Graphics::createDefaultShaders() {
@@ -1258,21 +1249,13 @@ void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
RenderPassConfiguration renderPassConfiguration{}; RenderPassConfiguration renderPassConfiguration{};
if (texture) { if (texture) {
auto vulkanFormat = Vulkan::getTextureFormat(texture->getPixelFormat()); renderPassConfiguration.frameBufferFormat = Vulkan::getTextureFormat(texture->getPixelFormat()).internalFormat;
currentFramebufferOutputFormat = vulkanFormat.internalFormat;
renderPassConfiguration.frameBufferFormat = vulkanFormat.internalFormat;
renderTargetTexture = texture; renderTargetTexture = texture;
} else { } else {
currentFramebufferOutputFormat = swapChainImageFormat;
renderPassConfiguration.frameBufferFormat = swapChainImageFormat; renderPassConfiguration.frameBufferFormat = swapChainImageFormat;
renderTargetTexture = nullptr; renderTargetTexture = nullptr;
} }
currentViewportWidth = (float)w;
currentViewportHeight = (float)h;
VkRenderPass renderPass; VkRenderPass renderPass;
auto it = renderPasses.find(renderPassConfiguration); auto it = renderPasses.find(renderPassConfiguration);
@@ -1283,14 +1266,21 @@ void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
renderPasses[renderPassConfiguration] = renderPass; renderPasses[renderPassConfiguration] = renderPass;
} }
FramebufferConfiguration configuration{};
configuration.renderPass = renderPass;
if (renderTargetTexture == nullptr) {
configuration.imageView = swapChainImageViews.at(imageIndex);
}
else {
configuration.imageView = (VkImageView)texture->getRenderTargetHandle();
}
configuration.width = w;
configuration.height = h;
VkRenderPassBeginInfo renderPassInfo{}; VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass; renderPassInfo.renderPass = renderPass;
if (renderTargetTexture == nullptr) { renderPassInfo.framebuffer = getFramebuffer(configuration);
renderPassInfo.framebuffer = getSwapChainFramebuffer(renderPass);
} else {
renderPassInfo.framebuffer = (VkFramebuffer) texture->getRenderTargetHandle();
}
renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent.width = static_cast<uint32_t>(w); renderPassInfo.renderArea.extent.width = static_cast<uint32_t>(w);
renderPassInfo.renderArea.extent.height = static_cast<uint32_t>(h); renderPassInfo.renderArea.extent.height = static_cast<uint32_t>(h);
@@ -1303,6 +1293,8 @@ void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
currentRenderPass = renderPass; currentRenderPass = renderPass;
currentGraphicsPipeline = VK_NULL_HANDLE; currentGraphicsPipeline = VK_NULL_HANDLE;
currentViewportWidth = (float)w;
currentViewportHeight = (float)h;
} }
void Graphics::endRenderPass() { void Graphics::endRenderPass() {
@@ -1587,6 +1579,10 @@ void Graphics::cleanup() {
} }
samplers.clear(); samplers.clear();
for (const auto& [key, val] : renderPasses) {
vkDestroyRenderPass(device, val, nullptr);
}
// fixme: maybe we should clean up some pipelines if they haven't been used in a while. // fixme: maybe we should clean up some pipelines if they haven't been used in a while.
for (auto const& p : graphicsPipelines) { for (auto const& p : graphicsPipelines) {
vkDestroyPipeline(device, p.second, nullptr); vkDestroyPipeline(device, p.second, nullptr);
@@ -1600,6 +1596,9 @@ void Graphics::cleanup() {
} }
void Graphics::cleanupSwapChain() { void Graphics::cleanupSwapChain() {
for (const auto& [key, val] : framebuffers) {
vkDestroyFramebuffer(device, val, nullptr);
}
for (auto & swapChainImageView : swapChainImageViews) { for (auto & swapChainImageView : swapChainImageViews) {
vkDestroyImageView(device, swapChainImageView, nullptr); vkDestroyImageView(device, swapChainImageView, nullptr);
} }
+20 -4
View File
@@ -38,6 +38,23 @@ struct RenderPassConfigurationHasher {
} }
}; };
struct FramebufferConfiguration {
VkRenderPass renderPass = VK_NULL_HANDLE;
VkImageView imageView = VK_NULL_HANDLE;
uint32_t width = 0;
uint32_t height = 0;
bool operator==(const FramebufferConfiguration& conf) const {
return memcmp(this, &conf, sizeof(FramebufferConfiguration)) == 0;
}
};
struct FramebufferConfigurationHasher {
size_t operator()(const FramebufferConfiguration& configuration) const {
return XXH32(&configuration, sizeof(FramebufferConfiguration), 0);
}
};
struct GraphicsPipelineConfiguration { struct GraphicsPipelineConfiguration {
VkRenderPass renderPass; VkRenderPass renderPass;
VertexAttributes vertexAttributes; VertexAttributes vertexAttributes;
@@ -186,8 +203,8 @@ 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 createFramebuffer(FramebufferConfiguration);
VkFramebuffer getSwapChainFramebuffer(VkRenderPass); VkFramebuffer getFramebuffer(FramebufferConfiguration);
void createDefaultShaders(); void createDefaultShaders();
VkRenderPass createRenderPass(RenderPassConfiguration); VkRenderPass createRenderPass(RenderPassConfiguration);
VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration); VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration);
@@ -224,10 +241,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;
std::unordered_map<VkRenderPass, std::vector<VkFramebuffer>> swapChainFramebufferVector;
VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE; VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE;
VkRenderPass currentRenderPass = VK_NULL_HANDLE; VkRenderPass currentRenderPass = VK_NULL_HANDLE;
std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses; std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
std::unordered_map<FramebufferConfiguration, VkFramebuffer, FramebufferConfigurationHasher> framebuffers;
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;
@@ -252,7 +269,6 @@ private:
graphics::Texture* currentTexture = nullptr; graphics::Texture* currentTexture = nullptr;
// render pass variables. // render pass variables.
VkFormat currentFramebufferOutputFormat = VK_FORMAT_UNDEFINED;
Texture* renderTargetTexture = nullptr; Texture* renderTargetTexture = nullptr;
float currentViewportWidth = 0; float currentViewportWidth = 0;
float currentViewportHeight = 0; float currentViewportHeight = 0;