Merge pull request #1885 from nikeinikei/12.0-development

Vulkan fixes
This commit is contained in:
Sasha Szpakowski
2022-12-27 13:32:08 -04:00
committed by GitHub
8 changed files with 185 additions and 185 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ class Buffer final
, public Volatile
{
public:
Buffer(love::graphics::Graphics *gfx, const Settings& settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength);
Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength);
virtual ~Buffer();
virtual bool loadVolatile() override;
+103 -121
View File
@@ -81,8 +81,6 @@ Graphics::Graphics()
throw love::Exception("could not find vulkan");
volkInitializeCustom((PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr());
instanceVersion = volkGetInstanceVersion();
}
Graphics::~Graphics()
@@ -360,7 +358,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
}
}
endRecordingGraphicsCommands(present);
endRecordingGraphicsCommands();
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
@@ -412,7 +410,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
callbacks.clear();
}
startRecordingGraphicsCommands(false);
startRecordingGraphicsCommands();
}
}
@@ -438,9 +436,9 @@ void Graphics::present(void *screenshotCallbackdata)
VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized)
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested)
{
framebufferResized = false;
swapChainRecreationRequested = false;
recreateSwapChain();
}
else if (result != VK_SUCCESS)
@@ -465,6 +463,9 @@ void Graphics::present(void *screenshotCallbackdata)
void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight)
{
if (swapChain != VK_NULL_HANDLE && (pixelWidth != this->pixelWidth || pixelHeight != this->pixelHeight || width != this->width || height != this->height))
requestSwapchainRecreation();
this->width = width;
this->height = height;
this->pixelWidth = pixelwidth;
@@ -601,7 +602,7 @@ void Graphics::unSetMode()
renderPassUsages.clear();
framebufferUsages.clear();
pipelineUsages.clear();
created = false;
vkDeviceWaitIdle(device);
Volatile::unloadAll();
@@ -675,34 +676,7 @@ Graphics::RendererInfo Graphics::getRendererInfo() const
Graphics::RendererInfo info;
if (isDebugEnabled())
{
std::stringstream ss;
ss << "Vulkan( ";
ss << renderPasses.size() << " ";
ss << framebuffers.size() << " ";
ss << graphicsPipelines.size() << " ";
if (optionalDeviceFeatures.extendedDynamicState)
ss << "eds ";
if (optionalDeviceFeatures.memoryRequirements2)
ss << "mr2 ";
if (optionalDeviceFeatures.dedicatedAllocation)
ss << "da ";
if (optionalDeviceFeatures.bufferDeviceAddress)
ss << "bda ";
if (optionalDeviceFeatures.memoryBudget)
ss << "mb ";
if (optionalDeviceFeatures.shaderFloatControls)
ss << "sfc ";
if (optionalDeviceFeatures.spirv14)
ss << "spv14 ";
ss << ")";
info.name = ss.str();
}
else
info.name = "Vulkan";
info.name = "Vulkan";
info.device = deviceProperties.deviceName;
info.vendor = Vulkan::getVendorName(deviceProperties.vendorID);
info.version = Vulkan::getVulkanApiVersion(deviceProperties.apiVersion);
@@ -832,11 +806,7 @@ void Graphics::setScissor(const Rect &rect)
{
flushBatchedDraws();
VkRect2D scissor = computeScissor(rect,
static_cast<double>(swapChainExtent.width),
static_cast<double>(swapChainExtent.height),
getCurrentDPIScale(),
preTransform);
VkRect2D scissor = computeScissor(rect, static_cast<double>(swapChainExtent.width), static_cast<double>(swapChainExtent.height), getCurrentDPIScale(), preTransform);
vkCmdSetScissor(commandBuffers.at(currentFrame), 0, 1, &scissor);
states.back().scissor = true;
@@ -1133,7 +1103,7 @@ void Graphics::beginFrame()
cleanUpFn();
cleanUpFunctions.at(currentFrame).clear();
startRecordingGraphicsCommands(true);
startRecordingGraphicsCommands();
Vulkan::cmdTransitionImageLayout(
commandBuffers.at(currentFrame),
@@ -1164,7 +1134,7 @@ void Graphics::beginFrame()
usedShadersInFrame.clear();
}
void Graphics::startRecordingGraphicsCommands(bool newFrame)
void Graphics::startRecordingGraphicsCommands()
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -1179,7 +1149,7 @@ void Graphics::startRecordingGraphicsCommands(bool newFrame)
setDefaultRenderPass();
}
void Graphics::endRecordingGraphicsCommands(bool present) {
void Graphics::endRecordingGraphicsCommands() {
if (renderPassState.active)
endRenderPass();
@@ -1187,16 +1157,6 @@ void Graphics::endRecordingGraphicsCommands(bool present) {
throw love::Exception("failed to record command buffer");
}
uint32_t Graphics::getNumImagesInFlight() const
{
return MAX_FRAMES_IN_FLIGHT;
}
uint32_t Graphics::getFrameIndex() const
{
return static_cast<uint32_t>(currentFrame);
}
const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const
{
return minUniformBufferOffsetAlignment;
@@ -1297,7 +1257,7 @@ void Graphics::createVulkanInstance()
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
appInfo.pEngineName = "LOVE Game Framework";
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
appInfo.apiVersion = instanceVersion;
appInfo.apiVersion = VK_API_VERSION_1_3;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@@ -1351,7 +1311,7 @@ bool Graphics::checkValidationSupport()
{
bool layerFound = false;
for (const auto& layerProperties : availableLayers)
for (const auto &layerProperties : availableLayers)
{
if (strcmp(layerName, layerProperties.layerName) == 0)
{
@@ -1546,8 +1506,8 @@ void Graphics::createLogicalDevice()
// sanity check for dependencies.
if (optionalDeviceFeatures.extendedDynamicState && !optionalInstanceExtensions.physicalDeviceProperties2)
optionalDeviceFeatures.extendedDynamicState = false;
if (optionalDeviceFeatures.extendedDynamicState && !optionalInstanceExtensions.physicalDeviceProperties2)
optionalDeviceFeatures.extendedDynamicState = false;
if (optionalDeviceFeatures.dedicatedAllocation && !optionalDeviceFeatures.memoryRequirements2)
optionalDeviceFeatures.dedicatedAllocation = false;
if (optionalDeviceFeatures.bufferDeviceAddress && !optionalInstanceExtensions.physicalDeviceProperties2)
@@ -1606,7 +1566,7 @@ void Graphics::createLogicalDevice()
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS)
throw love::Exception("failed to create logical device");
volkLoadDevice(device);
volkLoadDevice(device);
vkGetDeviceQueue(device, indices.graphicsFamily.value, 0, &graphicsQueue);
vkGetDeviceQueue(device, indices.presentFamily.value, 0, &presentQueue);
@@ -1705,15 +1665,15 @@ void Graphics::createSwapChain()
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
if ((swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) ||
(swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR))
if ((swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) ||
(swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR))
{
uint32_t width, height;
width = extent.width;
height = extent.height;
extent.width = height;
extent.height = width;
}
uint32_t width, height;
width = extent.width;
height = extent.height;
extent.width = height;
extent.height = width;
}
auto currentTransform = swapChainSupport.capabilities.currentTransform;
constexpr float PI = 3.14159265358979323846f;
@@ -1789,7 +1749,7 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurface
// TODO: turn off GammaCorrect if a sRGB format can't be found?
if (isGammaCorrect())
{
for (const auto& availableFormat : availableFormats)
for (const auto &availableFormat : availableFormats)
// fixme: what if this format and colorspace is not available?
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
return availableFormat;
@@ -1805,8 +1765,6 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurface
VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
{
int vsync = Vulkan::getVsync();
const auto begin = availablePresentModes.begin();
const auto end = availablePresentModes.end();
@@ -1871,12 +1829,12 @@ VkCompositeAlphaFlagBitsKHR Graphics::chooseCompositeAlpha(const VkSurfaceCapabi
return VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
return VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
return VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
return VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
else
throw love::Exception("failed to find composite alpha");
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
return VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
return VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
else
throw love::Exception("failed to find composite alpha");
}
void Graphics::createImageViews()
@@ -2002,7 +1960,7 @@ VkFramebuffer Graphics::createFramebuffer(FramebufferConfiguration &configuratio
{
std::vector<VkImageView> attachments;
for (const auto& colorView : configuration.colorViews)
for (const auto &colorView : configuration.colorViews)
attachments.push_back(colorView);
if (configuration.staticData.depthView)
@@ -2062,8 +2020,8 @@ void Graphics::createDefaultShaders()
VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
{
VkSubpassDescription subPass{};
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkSubpassDescription subPass{};
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
std::vector<VkAttachmentDescription> attachments;
std::vector<VkAttachmentReference> colorAttachmentRefs;
@@ -2091,8 +2049,8 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
attachments.push_back(colorDescription);
}
subPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
subPass.pColorAttachments = colorAttachmentRefs.data();
subPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
subPass.pColorAttachments = colorAttachmentRefs.data();
VkAttachmentReference depthStencilAttachmentRef{};
if (configuration.staticData.depthAttachment.format != VK_FORMAT_UNDEFINED)
@@ -2156,20 +2114,20 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
std::array<VkSubpassDependency, 2> dependencies = { dependency, readbackDependency };
VkRenderPassCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
createInfo.pAttachments = attachments.data();
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subPass;
VkRenderPassCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
createInfo.pAttachments = attachments.data();
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subPass;
createInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
createInfo.pDependencies = dependencies.data();
VkRenderPass renderPass;
if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS)
throw love::Exception("failed to create render pass");
VkRenderPass renderPass;
if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS)
throw love::Exception("failed to create render pass");
return renderPass;
return renderPass;
}
bool Graphics::usesConstantVertexColor(const VertexAttributes &vertexAttributes)
@@ -2261,7 +2219,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
GraphicsPipelineConfiguration configuration{};
configuration.renderPass = renderPassState.beginInfo.renderPass;
configuration.renderPass = renderPassState.beginInfo.renderPass;
configuration.vertexAttributes = attributes;
configuration.shader = (Shader*)Shader::current;
configuration.wireFrame = states.back().wireframe;
@@ -2295,7 +2253,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
}
}
if (usesConstantVertexColor(attributes))
if (!usesConstantVertexColor(attributes))
{
bufferVector.push_back((VkBuffer)defaultConstantColor->getHandle());
offsets.push_back((VkDeviceSize)0);
@@ -2328,35 +2286,15 @@ void Graphics::setDefaultRenderPass()
renderPassState.msaa = msaaSamples;
renderPassState.numColorAttachments = 1;
renderPassState.transitionImages.clear();
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = renderPassState.width;
viewport.height = renderPassState.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
}
void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture)
{
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(pixelw);
viewport.height = static_cast<float>(pixelh);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
auto currentCommandBuffer = commandBuffers.at(currentFrame);
// fixme: hasSRGBtexture
RenderPassConfiguration renderPassConfiguration{};
for (const auto& color : rts.colors)
for (const auto &color : rts.colors)
renderPassConfiguration.colorAttachments.push_back({
Vulkan::getTextureFormat(color.texture->getPixelFormat(), isPixelFormatSRGB(color.texture->getPixelFormat())).internalFormat,
false,
@@ -2406,6 +2344,16 @@ void Graphics::startRenderPass()
{
renderPassState.active = true;
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = renderPassState.width;
viewport.height = renderPassState.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
if (renderPassState.useConfigurations)
{
auto &renderPassConfiguration = renderPassState.renderPassConfiguration;
@@ -2518,6 +2466,14 @@ void Graphics::cleanupUnusedObjects()
eraseUnusedObjects(graphicsPipelines, pipelineUsages, vkDestroyPipeline, device);
}
void Graphics::requestSwapchainRecreation()
{
if (swapChain != VK_NULL_HANDLE)
{
swapChainRecreationRequested = true;
}
}
void Graphics::setComputeShader(Shader *shader)
{
computeShader = shader;
@@ -2688,7 +2644,7 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration &confi
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1;
pipelineInfo.renderPass = configuration.renderPass;
pipelineInfo.renderPass = configuration.renderPass;
VkPipeline graphicsPipeline;
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS)
@@ -2740,6 +2696,26 @@ VkSampleCountFlagBits Graphics::getMsaaCount(int requestedMsaa) const
return VK_SAMPLE_COUNT_1_BIT;
}
void Graphics::setVsync(int vsync)
{
if (vsync != this->vsync)
{
this->vsync = vsync;
// With the extension VK_EXT_swapchain_maintenance1 a swapchain recreation might not be needed
// https://github.com/KhronosGroup/Vulkan-Docs/blob/main/proposals/VK_EXT_swapchain_maintenance1.adoc
// However, there are not any drivers that support it, yet.
// Reevaluate again in the future.
requestSwapchainRecreation();
}
}
int Graphics::getVsync() const
{
return vsync;
}
void Graphics::createColorResources()
{
if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
@@ -2770,7 +2746,8 @@ void Graphics::createColorResources()
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &colorImage, &colorImageAllocation, nullptr);
if (vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &colorImage, &colorImageAllocation, nullptr))
throw love::Exception("failed to create color image");
VkImageViewCreateInfo imageViewInfo{};
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -2787,7 +2764,8 @@ void Graphics::createColorResources()
imageViewInfo.subresourceRange.baseArrayLayer = 0;
imageViewInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device, &imageViewInfo, nullptr, &colorImageView);
if (vkCreateImageView(device, &imageViewInfo, nullptr, &colorImageView) != VK_SUCCESS)
throw love::Exception("failed to create color image view");
}
}
@@ -2838,7 +2816,8 @@ void Graphics::createDepthResources()
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &depthImage, &depthImageAllocation, nullptr);
if (vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &depthImage, &depthImageAllocation, nullptr) != VK_SUCCESS)
throw love::Exception("failed to create depth image");
VkImageViewCreateInfo imageViewInfo{};
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -2857,7 +2836,8 @@ void Graphics::createDepthResources()
imageViewInfo.subresourceRange.baseArrayLayer = 0;
imageViewInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device, &imageViewInfo, nullptr, &depthImageView);
if (vkCreateImageView(device, &imageViewInfo, nullptr, &depthImageView) != VK_SUCCESS)
throw love::Exception("failed to create depth image view");
}
void Graphics::createCommandPool()
@@ -2972,10 +2952,12 @@ void Graphics::cleanupSwapChain()
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
vkDestroyImageView(device, depthImageView, nullptr);
vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation);
for (const auto &swapChainImageView : swapChainImageViews)
vkDestroyImageView(device, swapChainImageView, nullptr);
swapChainImageViews.clear();
for (const auto &swapChainImageView : swapChainImageViews)
vkDestroyImageView(device, swapChainImageView, nullptr);
swapChainImageViews.clear();
vkDestroySwapchainKHR(device, swapChain, nullptr);
swapChain = VK_NULL_HANDLE;
}
void Graphics::recreateSwapChain()
+20 -18
View File
@@ -70,23 +70,23 @@ struct RenderPassConfiguration
bool resolve = false;
} staticData;
bool operator==(const RenderPassConfiguration &conf) const
bool operator==(const RenderPassConfiguration &conf) const
{
return colorAttachments == conf.colorAttachments &&
(memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0);
}
}
};
struct RenderPassConfigurationHasher
{
size_t operator()(const RenderPassConfiguration &configuration) const
size_t operator()(const RenderPassConfiguration &configuration) const
{
size_t hashes[] = {
XXH32(configuration.colorAttachments.data(), configuration.colorAttachments.size() * sizeof(VkFormat), 0),
XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
};
return XXH32(hashes, sizeof(hashes), 0);
}
}
};
struct FramebufferConfiguration
@@ -126,7 +126,8 @@ struct FramebufferConfigurationHasher
struct OptionalInstanceExtensions
{
bool physicalDeviceProperties2 = false;
// VK_KHR_get_physical_device_properties2
bool physicalDeviceProperties2 = false;
};
struct OptionalDeviceFeatures
@@ -155,7 +156,7 @@ struct OptionalDeviceFeatures
struct GraphicsPipelineConfiguration
{
VkRenderPass renderPass;
VkRenderPass renderPass;
VertexAttributes vertexAttributes;
Shader *shader = nullptr;
bool wireFrame;
@@ -288,8 +289,6 @@ public:
void queueCleanUp(std::function<void()> cleanUp);
void addReadbackCallback(std::function<void()> callback);
void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
uint32_t getNumImagesInFlight() const;
uint32_t getFrameIndex() const;
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
graphics::Texture *getDefaultTexture() const;
VkSampler getCachedSampler(const SamplerState &sampler);
@@ -298,6 +297,8 @@ public:
graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const;
void setVsync(int vsync);
int getVsync() const;
protected:
graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
@@ -328,10 +329,10 @@ private:
void createScreenshotCallbackBuffers();
void createDefaultRenderPass();
void createDefaultFramebuffers();
VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
void createDefaultShaders();
VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration &configuration);
void createColorResources();
VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
@@ -346,8 +347,8 @@ private:
void recreateSwapChain();
void initDynamicState();
void beginFrame();
void startRecordingGraphicsCommands(bool newFrame);
void endRecordingGraphicsCommands(bool present);
void startRecordingGraphicsCommands();
void endRecordingGraphicsCommands();
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
bool usesConstantVertexColor(const VertexAttributes &attribs);
void createVulkanVertexFormat(
@@ -364,8 +365,8 @@ private:
void endRenderPass();
VkSampler createSampler(const SamplerState &sampler);
void cleanupUnusedObjects();
void requestSwapchainRecreation();
uint32_t instanceVersion = VK_API_VERSION_1_0;
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
uint32_t deviceApiVersion = VK_API_VERSION_1_0;
@@ -377,7 +378,7 @@ private:
VkQueue graphicsQueue = VK_NULL_HANDLE;
VkQueue presentQueue = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
VkSurfaceTransformFlagBitsKHR preTransform = {};
Matrix4 displayRotation;
std::vector<VkImage> swapChainImages;
@@ -393,7 +394,7 @@ private:
VmaAllocation depthImageAllocation = VK_NULL_HANDLE;
VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
std::vector<VkFramebuffer> defaultFramebuffers;
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<VkRenderPass, bool> renderPassUsages;
@@ -402,17 +403,18 @@ private:
std::unordered_map<uint64, VkSampler> samplers;
VkCommandPool commandPool = VK_NULL_HANDLE;
std::vector<VkCommandBuffer> commandBuffers;
Shader* computeShader = nullptr;
Shader *computeShader = nullptr;
std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
std::vector<VkFence> imagesInFlight;
int vsync = 1;
VkDeviceSize minUniformBufferOffsetAlignment = 0;
bool imageRequested = false;
uint32_t frameCounter = 0;
size_t currentFrame = 0;
uint32_t imageIndex = 0;
bool framebufferResized = false;
bool swapChainRecreationRequested = false;
bool transitionColorDepthLayouts = false;
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
StrongRef<love::graphics::Texture> defaultTexture;
+46 -24
View File
@@ -196,7 +196,7 @@ bool Shader::loadVolatile()
createPipelineLayout();
createDescriptorPoolSizes();
createStreamBuffers();
descriptorSetsVector.resize(vgfx->getNumImagesInFlight());
descriptorSetsVector.resize(MAX_FRAMES_IN_FLIGHT);
currentFrame = 0;
currentUsedUniformStreamBuffersCount = 0;
currentUsedDescriptorSetsCount = 0;
@@ -234,8 +234,7 @@ void Shader::unloadVolatile()
}
}
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
gfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
vgfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
for (const auto pool : descriptorPools)
vkDestroyDescriptorPool(device, pool, nullptr);
for (const auto shaderModule : shaderModules)
@@ -274,10 +273,11 @@ VkPipeline Shader::getComputePipeline() const
return computePipeline;
}
void Shader::newFrame(uint32_t frameIndex)
void Shader::newFrame()
{
currentFrame = frameIndex;
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
updatedUniforms.clear();
currentUsedUniformStreamBuffersCount = 0;
currentUsedDescriptorSetsCount = 0;
@@ -295,12 +295,10 @@ void Shader::newFrame(uint32_t frameIndex)
else
streamBuffers.at(0)->nextFrame();
if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(descriptorSetsVector.at(currentFrame).size()))
if (descriptorSetsVector.at(currentFrame).size() == 0)
descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
initDescriptorSet();
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(0);
}
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint)
@@ -336,15 +334,17 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
VkWriteDescriptorSet uniformWrite{};
uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
uniformWrite.dstSet = currentDescriptorSet;
uniformWrite.dstBinding = uniformLocation;
uniformWrite.dstBinding = localUniformLocation;
uniformWrite.dstArrayElement = 0;
uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uniformWrite.descriptorCount = 1;
uniformWrite.pBufferInfo = &bufferInfo;
uniformWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr);
currentUsedUniformStreamBuffersCount++;
updatedUniforms.insert(localUniformLocation);
}
static const std::vector<BuiltinUniform> builtinUniformTextures = {
@@ -365,18 +365,28 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
imageInfo.imageView = (VkImageView)texture->getRenderTargetHandle();
imageInfo.sampler = (VkSampler)texture->getSamplerHandle();
auto location = builtinUniformInfo[builtin]->location;
VkWriteDescriptorSet textureWrite{};
textureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
textureWrite.dstSet = currentDescriptorSet;
textureWrite.dstBinding = builtinUniformInfo[builtin]->location;
textureWrite.dstBinding = location;
textureWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
textureWrite.descriptorCount = 1;
textureWrite.pImageInfo = &imageInfo;
vkUpdateDescriptorSets(device, 1, &textureWrite, 0, nullptr);
updatedUniforms.insert(location);
}
}
for (const auto &u : uniformInfos)
{
if (updatedUniforms.find(u.second.location) == updatedUniforms.end())
updateUniform(&u.second, u.second.count);
}
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
currentUsedDescriptorSetsCount++;
@@ -386,7 +396,7 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
initDescriptorSet();
updatedUniforms.clear();
}
Shader::~Shader()
@@ -399,7 +409,7 @@ void Shader::attach()
auto &usedShadersInFrame = vgfx->getUsedShadersInFrame();
if (usedShadersInFrame.find(this) == usedShadersInFrame.end())
{
newFrame(vgfx->getFrameIndex());
newFrame();
usedShadersInFrame.insert(this);
}
@@ -463,6 +473,9 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
{
auto vkTexture = dynamic_cast<Texture*>(info->textures[i]);
if (vkTexture == nullptr)
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = vkTexture->getImageLayout();
@@ -501,6 +514,9 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
for (int i = 0; i < info->count; i++)
{
if (info->buffers[i] == nullptr)
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = (VkBuffer)info->buffers[i]->getHandle();;
bufferInfo.offset = 0;
@@ -526,12 +542,19 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
std::vector<VkBufferView> bufferViews;
for (int i = 0; i < info->count; i++)
{
if (info->buffers[i] == nullptr)
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
bufferViews.push_back((VkBufferView)info->buffers[i]->getTexelBufferHandle());
}
write.pTexelBufferView = bufferViews.data();
vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
}
updatedUniforms.insert(info->location);
}
void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
@@ -544,6 +567,8 @@ void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures,
if (oldTexture)
oldTexture->release();
}
updateUniform(info, count);
}
void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count)
@@ -556,6 +581,8 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
if (oldBuffer)
oldBuffer->release();
}
updateUniform(info, count);
}
void Shader::calculateUniformBufferSizeAligned()
@@ -568,13 +595,6 @@ void Shader::calculateUniformBufferSizeAligned()
uniformBufferSizeAligned = factor * minAlignment;
}
void Shader::initDescriptorSet()
{
for (const auto &entry : uniformInfos)
if (Vulkan::getDescriptorType(entry.second.baseType) != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
updateUniform(&entry.second, entry.second.count, true);
}
void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
{
using namespace spirv_cross;
@@ -776,7 +796,7 @@ void Shader::compileShaders()
auto defaultUniformBlockSize = comp.get_declared_struct_size(type);
localUniformStagingData.resize(defaultUniformBlockSize);
localUniformData.resize(defaultUniformBlockSize);
uniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
localUniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
memset(localUniformStagingData.data(), 0, defaultUniformBlockSize);
memset(localUniformData.data(), 0, defaultUniformBlockSize);
@@ -956,7 +976,7 @@ void Shader::createDescriptorSetLayout()
if (!localUniformStagingData.empty())
{
VkDescriptorSetLayoutBinding uniformBinding{};
uniformBinding.binding = uniformLocation;
uniformBinding.binding = localUniformLocation;
uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uniformBinding.descriptorCount = 1;
uniformBinding.stageFlags = stageFlags;
@@ -1023,7 +1043,9 @@ void Shader::createDescriptorPoolSizes()
void Shader::createStreamBuffers()
{
streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
size_t size = STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned;
if (size > 0)
streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, size));
}
void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture)
+6 -4
View File
@@ -35,6 +35,7 @@
#include <memory>
#include <unordered_map>
#include <queue>
#include <set>
namespace love
@@ -63,7 +64,7 @@ public:
const VkPipelineLayout getGraphicsPipelineLayout() const;
void newFrame(uint32_t frameIndex);
void newFrame();
void cmdPushDescriptorSets(VkCommandBuffer, VkPipelineBindPoint);
@@ -101,8 +102,7 @@ private:
const spirv_cross::SPIRType &type,
size_t baseoff,
const std::string &basename);
void initDescriptorSet();
void updateUniform(const UniformInfo* info, int count, bool internal);
void updateUniform(const UniformInfo *info, int count, bool internal);
VkDescriptorSet allocateDescriptorSet();
@@ -121,6 +121,8 @@ private:
std::queue<VkDescriptorSet> freeDescriptorSets;
std::vector<std::vector<VkDescriptorSet>> descriptorSetsVector;
std::set<uint32_t> updatedUniforms;
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
std::vector<VkShaderModule> shaderModules;
@@ -135,7 +137,7 @@ private:
std::unique_ptr<StreamBuffer> uniformBufferObjectBuffer;
std::vector<uint8> localUniformData;
std::vector<uint8> localUniformStagingData;
uint32_t uniformLocation;
uint32_t localUniformLocation;
OptionalInt builtinUniformDataOffset;
std::unordered_map<std::string, int> attributes;
-11
View File
@@ -31,7 +31,6 @@ namespace vulkan
{
static uint32_t numShaderSwitches;
static int vsync = 1;
void Vulkan::shaderSwitch()
{
@@ -48,16 +47,6 @@ void Vulkan::resetShaderSwitches()
numShaderSwitches = 0;
}
void Vulkan::setVsync(int value)
{
vsync = value;
}
int Vulkan::getVsync()
{
return vsync;
}
VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
{
switch (format)
-3
View File
@@ -58,9 +58,6 @@ public:
static uint32_t getNumShaderSwitches();
static void resetShaderSwitches();
static void setVsync(int vsync);
static int getVsync();
static VkFormat getVulkanVertexFormat(DataFormat format);
static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
static std::string getVendorName(uint32_t vendorId);
+9 -3
View File
@@ -1100,8 +1100,11 @@ void Window::setVSync(int vsync)
}
#ifdef LOVE_GRAPHICS_VULKAN
// TODO: this doesn't update the swap-chain, but it should.
love::graphics::vulkan::Vulkan::setVsync(vsync);
if (windowRenderer == love::graphics::RENDERER_VULKAN)
{
auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
vgfx->setVsync(vsync);
}
#endif
#if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS)
@@ -1132,7 +1135,10 @@ int Window::getVSync() const
#ifdef LOVE_GRAPHICS_VULKAN
if (windowRenderer == love::graphics::RENDERER_VULKAN)
return love::graphics::vulkan::Vulkan::getVsync();
{
auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
return vgfx->getVsync();
}
#endif
return 0;