From 7a3e9ed71e2f9c77f97d42e52be45f14cb666cc8 Mon Sep 17 00:00:00 2001 From: niki Date: Fri, 29 Jul 2022 21:04:35 +0200 Subject: [PATCH] vulkan: fix uniform buffer descriptor There was a bug where the count of used builtin uniform buffer objects was not advanced. This caused another problem since vulkan requires a certain alignment for the buffer. This commit fixes both of those things. --- src/modules/graphics/vulkan/Buffer.cpp | 2 +- src/modules/graphics/vulkan/Graphics.cpp | 29 +++++++++++++-------- src/modules/graphics/vulkan/Graphics.h | 2 ++ src/modules/graphics/vulkan/Shader.cpp | 32 ++++++++++++++++++------ src/modules/graphics/vulkan/Shader.h | 2 ++ src/modules/graphics/vulkan/Texture.cpp | 2 +- 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/modules/graphics/vulkan/Buffer.cpp b/src/modules/graphics/vulkan/Buffer.cpp index 7217b512a..7e5ac6604 100644 --- a/src/modules/graphics/vulkan/Buffer.cpp +++ b/src/modules/graphics/vulkan/Buffer.cpp @@ -26,7 +26,7 @@ namespace love { } Buffer::Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) - : love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), allocator(allocator), gfx(gfx) { + : love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), gfx(gfx) { loadVolatile(); } diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 9ad7674d9..d88245e5f 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -7,6 +7,7 @@ #include "graphics/Texture.h" #include "Vulkan.h" #include "common/version.h" +#include "common/pixelformat.h" #include #include @@ -99,8 +100,8 @@ namespace love { VkClearRect rect{}; rect.layerCount = 1; - rect.rect.extent.width = currentViewportWidth; - rect.rect.extent.height = currentViewportHeight; + rect.rect.extent.width = static_cast(currentViewportWidth); + rect.rect.extent.height = static_cast(currentViewportHeight); vkCmdClearAttachments(commandBuffers[imageIndex], 1, &attachment, 1, &rect); } @@ -121,8 +122,8 @@ namespace love { VkClearRect rect{}; rect.layerCount = 1; - rect.rect.extent.width = currentViewportWidth; - rect.rect.extent.height = currentViewportHeight; + rect.rect.extent.width = static_cast(currentViewportWidth); + rect.rect.extent.height = static_cast(currentViewportHeight); vkCmdClearAttachments(commandBuffers[imageIndex], static_cast(attachments.size()), attachments.data(), 1, &rect); } @@ -433,7 +434,7 @@ namespace love { PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const { switch (format) { - PIXELFORMAT_NORMAL: + case PIXELFORMAT_NORMAL: if (isGammaCorrect()) { return PIXELFORMAT_RGBA8_UNORM_sRGB; } @@ -534,6 +535,10 @@ namespace love { return MAX_FRAMES_IN_FLIGHT; } + const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const { + return minUniformBufferOffsetAlignment; + } + const PFN_vkCmdPushDescriptorSetKHR Graphics::getVkCmdPushDescriptorSetKHRFunctionPointer() const { return vkCmdPushDescriptorSet; } @@ -596,8 +601,8 @@ namespace love { // Same with point size. data.normalMatrix[1].w = getPointSize(); - data.screenSizeParams.x = swapChainExtent.width; - data.screenSizeParams.y = swapChainExtent.height; + data.screenSizeParams.x = static_cast(swapChainExtent.width); + data.screenSizeParams.y = static_cast(swapChainExtent.height); data.screenSizeParams.z = 1.0f; data.screenSizeParams.w = 0.0f; @@ -711,6 +716,10 @@ namespace love { else { throw love::Exception("failed to find a suitable gpu"); } + + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(physicalDevice, &properties); + minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment; } bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device) { @@ -1184,7 +1193,7 @@ namespace love { ensureGraphicsPipelineConfiguration(configuration); - configuration.shader->cmdPushDescriptorSets(commandBuffers.at(imageIndex), currentFrame); + configuration.shader->cmdPushDescriptorSets(commandBuffers.at(imageIndex), static_cast(currentFrame)); vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, static_cast(bufferVector.size()), bufferVector.data(), offsets.data()); } @@ -1241,9 +1250,9 @@ namespace love { VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = configuration.vertexInputBindingDescriptions.size(); + vertexInputInfo.vertexBindingDescriptionCount = static_cast(configuration.vertexInputBindingDescriptions.size()); vertexInputInfo.pVertexBindingDescriptions = configuration.vertexInputBindingDescriptions.data(); - vertexInputInfo.vertexAttributeDescriptionCount = configuration.vertexInputAttributeDescriptions.size(); + vertexInputInfo.vertexAttributeDescriptionCount = static_cast(configuration.vertexInputAttributeDescriptions.size()); vertexInputInfo.pVertexAttributeDescriptions = configuration.vertexInputAttributeDescriptions.data(); VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index e2440e600..5854ed59e 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -118,6 +118,7 @@ namespace love { uint32_t getNumImagesInFlight() const; const PFN_vkCmdPushDescriptorSetKHR getVkCmdPushDescriptorSetKHRFunctionPointer() const; + const VkDeviceSize getMinUniformBufferOffsetAlignment() const; protected: graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override { @@ -189,6 +190,7 @@ namespace love { std::vector renderFinishedSemaphores; std::vector inFlightFences; std::vector imagesInFlight; + VkDeviceSize minUniformBufferOffsetAlignment; PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet; size_t currentFrame = 0; uint32_t imageIndex = 0; diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 6d9717331..b2cab1b77 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -150,6 +150,7 @@ namespace love { } bool Shader::loadVolatile() { + calculateUniformBufferSizeAligned(); compileShaders(); createDescriptorSetLayout(); createPipelineLayout(); @@ -211,15 +212,15 @@ namespace love { } } - auto mapInfo = streamBuffers[currentImage]->map(sizeof(BuiltinUniformData)); - memcpy(mapInfo.data, &uniformData, sizeof(BuiltinUniformData)); - streamBuffers[currentImage]->unmap(sizeof(BuiltinUniformData)); - streamBuffers[currentImage]->markUsed(sizeof(BuiltinUniformData)); + auto mapInfo = streamBuffers[currentImage]->map(uniformBufferSizeAligned); + memcpy(mapInfo.data, &uniformData, uniformBufferSizeAligned); + streamBuffers[currentImage]->unmap(uniformBufferSizeAligned); + streamBuffers[currentImage]->markUsed(uniformBufferSizeAligned); VkDescriptorBufferInfo bufferInfo{}; bufferInfo.buffer = (VkBuffer)streamBuffers[currentImage]->getHandle(); - bufferInfo.offset = count * sizeof(BuiltinUniformData); - bufferInfo.range = sizeof(graphics::Shader::BuiltinUniformData); + bufferInfo.offset = count * uniformBufferSizeAligned; + bufferInfo.range = sizeof(BuiltinUniformData); auto mainTexImageInfo = createDescriptorImageInfo(mainTex); auto ytextureImageInfo = createDescriptorImageInfo(ytexture); @@ -268,6 +269,8 @@ namespace love { descriptorWrite[4].pImageInfo = &crtextureImageInfo; vkCmdPushDescriptorSet(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast(descriptorWrite.size()), descriptorWrite.data()); + + count++; } Shader::~Shader() { @@ -286,6 +289,19 @@ namespace love { return vertexAttributeIndices.at(name); } + void Shader::calculateUniformBufferSizeAligned() { + gfx = Module::getInstance(Module::ModuleType::M_GRAPHICS); + auto vgfx = (Graphics*)gfx; + auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment(); + uniformBufferSizeAligned = + static_cast( + std::ceil( + static_cast(sizeof(BuiltinUniformData)) / static_cast(minAlignment) + ) + ) + * minAlignment; + } + void Shader::compileShaders() { using namespace glslang; using namespace spirv_cross; @@ -315,7 +331,7 @@ namespace love { auto& glsl = stages[i]->getSource(); const char* csrc = glsl.c_str(); - const int sourceLength = glsl.length(); + const int sourceLength = static_cast(glsl.length()); tshader->setStringsWithLengths(&csrc, &sourceLength, 1); int defaultVersio = 450; @@ -451,7 +467,7 @@ namespace love { const auto numImagesInFlight = vgfx->getNumImagesInFlight(); streamBuffers.resize(numImagesInFlight); for (uint32_t i = 0; i < numImagesInFlight; i++) { - streamBuffers[i] = new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_SIZE * sizeof(BuiltinUniformData)); + streamBuffers[i] = new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_SIZE * uniformBufferSizeAligned); } } diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index b123872b9..956c01cd0 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -52,11 +52,13 @@ namespace love { void setMainTex(graphics::Texture* texture); private: + void calculateUniformBufferSizeAligned(); void compileShaders(); void createDescriptorSetLayout(); void createPipelineLayout(); void createStreamBuffers(); + VkDeviceSize uniformBufferSizeAligned; PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet; VkDescriptorSetLayout descriptorSetLayout; diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 21d5b71d3..e0654b454 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -146,7 +146,7 @@ namespace love { VkImageSubresourceRange range{}; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.layerCount = 1; + range.layerCount = getMipmapCount(); range.levelCount = 1; vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);