diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 02ec07095..202bb070d 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -358,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); @@ -410,7 +410,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData) callbacks.clear(); } - startRecordingGraphicsCommands(false); + startRecordingGraphicsCommands(); } } @@ -1103,7 +1103,7 @@ void Graphics::beginFrame() cleanUpFn(); cleanUpFunctions.at(currentFrame).clear(); - startRecordingGraphicsCommands(true); + startRecordingGraphicsCommands(); Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), @@ -1134,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; @@ -1149,7 +1149,7 @@ void Graphics::startRecordingGraphicsCommands(bool newFrame) setDefaultRenderPass(); } -void Graphics::endRecordingGraphicsCommands(bool present) { +void Graphics::endRecordingGraphicsCommands() { if (renderPassState.active) endRenderPass(); @@ -1157,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(currentFrame); -} - const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const { return minUniformBufferOffsetAlignment; @@ -2263,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); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 8e389bd72..e7c43ebc5 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -289,8 +289,6 @@ public: void queueCleanUp(std::function cleanUp); void addReadbackCallback(std::function 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); @@ -349,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( diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index f1f46a4ba..8e30eba28 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -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; @@ -274,10 +274,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 +296,10 @@ void Shader::newFrame(uint32_t frameIndex) else streamBuffers.at(0)->nextFrame(); - if (currentUsedDescriptorSetsCount >= static_cast(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,7 +335,7 @@ 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; @@ -345,6 +344,8 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr); currentUsedUniformStreamBuffersCount++; + + updatedUniforms.insert(localUniformLocation); } static const std::vector builtinUniformTextures = { @@ -365,18 +366,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, ¤tDescriptorSet, 0, nullptr); currentUsedDescriptorSetsCount++; @@ -385,8 +396,6 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); - - initDescriptorSet(); } Shader::~Shader() @@ -399,7 +408,7 @@ void Shader::attach() auto &usedShadersInFrame = vgfx->getUsedShadersInFrame(); if (usedShadersInFrame.find(this) == usedShadersInFrame.end()) { - newFrame(vgfx->getFrameIndex()); + newFrame(); usedShadersInFrame.insert(this); } @@ -532,6 +541,8 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal) vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); } + + updatedUniforms.insert(info->location); } void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count) @@ -544,6 +555,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 +569,8 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe if (oldBuffer) oldBuffer->release(); } + + updateUniform(info, count); } void Shader::calculateUniformBufferSizeAligned() @@ -568,13 +583,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 +784,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 +964,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; diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index ea5124976..e10e09d95 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace love @@ -63,7 +64,7 @@ public: const VkPipelineLayout getGraphicsPipelineLayout() const; - void newFrame(uint32_t frameIndex); + void newFrame(); void cmdPushDescriptorSets(VkCommandBuffer, VkPipelineBindPoint); @@ -101,7 +102,6 @@ private: const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename); - void initDescriptorSet(); void updateUniform(const UniformInfo *info, int count, bool internal); VkDescriptorSet allocateDescriptorSet(); @@ -121,6 +121,8 @@ private: std::queue freeDescriptorSets; std::vector> descriptorSetsVector; + std::set updatedUniforms; + std::vector shaderStages; std::vector shaderModules; @@ -135,7 +137,7 @@ private: std::unique_ptr uniformBufferObjectBuffer; std::vector localUniformData; std::vector localUniformStagingData; - uint32_t uniformLocation; + uint32_t localUniformLocation; OptionalInt builtinUniformDataOffset; std::unordered_map attributes;