mirror of
https://github.com/love2d/love.git
synced 2026-08-20 20:49:54 +02:00
vulkan: remove dynamic rendering (part 2)
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user