mirror of
https://github.com/love2d/love.git
synced 2026-08-20 12:40:20 +02:00
vulkan: don't use dynamic rendering
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user