diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 0e0dde6ce..9714fb15c 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -498,8 +498,6 @@ Graphics::RendererInfo Graphics::getRendererInfo() const ss << "Vulkan( "; if (optionalDeviceFeatures.extendedDynamicState) ss << VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME << " "; - if (optionalDeviceFeatures.pushDescriptor) - ss << VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME << " "; ss << ")"; info.name = ss.str(); @@ -732,7 +730,7 @@ bool Graphics::dispatch(int x, int y, int z) vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_COMPUTE, computeShader->getComputePipeline()); - computeShader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), static_cast(currentFrame), VK_PIPELINE_BIND_POINT_COMPUTE); + computeShader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_COMPUTE); vkCmdDispatch(commandBuffers.at(currentFrame), static_cast(x), static_cast(y), static_cast(z)); @@ -836,6 +834,8 @@ void Graphics::beginFrame() VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); Vulkan::resetShaderSwitches(); + + usedShadersInFrame.clear(); } void Graphics::startRecordingGraphicsCommands(bool newFrame) @@ -883,6 +883,11 @@ uint32_t Graphics::getNumImagesInFlight() const return MAX_FRAMES_IN_FLIGHT; } +uint32_t Graphics::getFrameIndex() const +{ + return currentFrame; +} + const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const { return minUniformBufferOffsetAlignment; @@ -1189,8 +1194,6 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option { if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0) optionalDeviceFeatures.extendedDynamicState = true; - if (strcmp(extension.extensionName, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) == 0) - optionalDeviceFeatures.pushDescriptor = true; } } @@ -1231,8 +1234,6 @@ void Graphics::createLogicalDevice() if (optionalDeviceFeatures.extendedDynamicState) enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - if (optionalDeviceFeatures.pushDescriptor) - enabledExtensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); createInfo.enabledExtensionCount = static_cast(enabledExtensions.size()); createInfo.ppEnabledExtensionNames = enabledExtensions.data(); @@ -1288,14 +1289,6 @@ void Graphics::createLogicalDevice() ext.vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilOpEXT"); ext.vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT"); ext.vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT"); -#endif - } - if (optionalDeviceFeatures.pushDescriptor) - { -#ifdef LOVE_ANDROID - ext.vkCmdPushDescriptorSetKHR = vkCmdPushDescriptorSetKHR; -#else - ext.vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(device, "vkCmdPushDescriptorSetKHR"); #endif } } @@ -1852,6 +1845,8 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi if (!renderPassState.active) startRenderPass(); + Shader::current->attach(); + GraphicsPipelineConfiguration configuration{}; configuration.renderPass = renderPassState.renderPass; @@ -1892,8 +1887,6 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi offsets.push_back((VkDeviceSize)0); } - auto currentUniformData = getCurrentBuiltinUniformData(); - configuration.shader->setUniformData(currentUniformData); if (texture == nullptr) configuration.shader->setMainTex(standardTexture.get()); else @@ -1901,7 +1894,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi ensureGraphicsPipelineConfiguration(configuration); - configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), static_cast(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS); + configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS); vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast(bufferVector.size()), bufferVector.data(), offsets.data()); } @@ -2074,6 +2067,11 @@ void Graphics::setComputeShader(Shader *shader) computeShader = shader; } +std::set &Graphics::getUsedShadersInFrame() +{ + return usedShadersInFrame; +} + const OptionalDeviceFeatures &Graphics::getOptionalDeviceFeatures() const { return optionalDeviceFeatures; diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 85a6e4d01..7289cc323 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace love @@ -99,7 +100,6 @@ struct OptionalInstanceExtensions struct OptionalDeviceFeatures { bool extendedDynamicState = false; - bool pushDescriptor = false; }; struct OptionalDeviceExtensionFunctions @@ -116,9 +116,6 @@ struct OptionalDeviceExtensionFunctions PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT = nullptr; PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT = nullptr; PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT = nullptr; - - // push descriptor - PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = nullptr; }; struct GraphicsPipelineConfiguration @@ -232,7 +229,7 @@ public: virtual ~Graphics(); - const char* getName() const override; + const char *getName() const override; const VkDevice getDevice() const; const VkPhysicalDevice getPhysicalDevice() const; const VmaAllocator getVmaAllocator() const; @@ -281,15 +278,20 @@ public: void submitGpuCommands(bool present); uint32_t getNumImagesInFlight() const; + uint32_t getFrameIndex() const; + const VkDeviceSize getMinUniformBufferOffsetAlignment() const; graphics::Texture *getDefaultTexture() const; VkSampler getCachedSampler(const SamplerState&); void setComputeShader(Shader*); + std::set &getUsedShadersInFrame(); const OptionalDeviceFeatures &getOptionalDeviceFeatures() const; const OptionalDeviceExtensionFunctions &getExtensionFunctions() const; + graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData(); + protected: graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override; graphics::Shader *newShaderInternal(StrongRef stages[SHADERSTAGE_MAX_ENUM]) override; @@ -319,11 +321,11 @@ private: void createImageViews(); void createDefaultRenderPass(); void createDefaultFramebuffers(); - VkFramebuffer createFramebuffer(FramebufferConfiguration&); - VkFramebuffer getFramebuffer(FramebufferConfiguration&); + VkFramebuffer createFramebuffer(FramebufferConfiguration &); + VkFramebuffer getFramebuffer(FramebufferConfiguration &); void createDefaultShaders(); - VkRenderPass createRenderPass(RenderPassConfiguration&); - VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration&); + VkRenderPass createRenderPass(RenderPassConfiguration &); + VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration &); void createColorResources(); VkFormat findSupportedFormat(const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); VkFormat findDepthFormat(); @@ -339,10 +341,9 @@ private: void beginFrame(); void startRecordingGraphicsCommands(bool newFrame); void endRecordingGraphicsCommands(bool present); - void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration&); - graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData(); + void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &); void updatedBatchedDrawBuffers(); - bool usesConstantVertexColor(const VertexAttributes&); + bool usesConstantVertexColor(const VertexAttributes &); void createVulkanVertexFormat( VertexAttributes vertexAttributes, std::vector &bindingDescriptions, @@ -405,6 +406,7 @@ private: // just like batchedDrawBuffers we need a vector for each frame in flight. std::vector>> cleanUpFunctions; std::vector>> readbackCallbacks; + std::set usedShadersInFrame; RenderpassState renderPassState; }; diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 19e8419d7..a311735a6 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -160,8 +160,6 @@ Shader::Shader(StrongRef stages[]) auto gfx = Module::getInstance(Module::ModuleType::M_GRAPHICS); vgfx = dynamic_cast(gfx); auto &optionalDeviceFeaures = vgfx->getOptionalDeviceFeatures(); - if (optionalDeviceFeaures.pushDescriptor) - pfn_vkCmdPushDescriptorSetKHR = vgfx->getExtensionFunctions().vkCmdPushDescriptorSetKHR; loadVolatile(); } @@ -232,7 +230,7 @@ VkPipeline Shader::getComputePipeline() const return computePipeline; } -static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture *texture, bool sampler) +static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture* texture, bool sampler) { auto vkTexture = (Texture*)texture; @@ -246,90 +244,38 @@ static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture *textu return imageInfo; } -void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frameIndex, VkPipelineBindPoint bindPoint) +void Shader::newFrame(uint32_t frameIndex) { - // detect whether a new frame has begun - if (currentFrame != frameIndex) + currentFrame = frameIndex; + + currentUsedUniformStreamBuffersCount = 0; + currentUsedDescriptorSetsCount = 0; + + if (streamBuffers.at(currentFrame).size() > 1) { - currentFrame = frameIndex; - - currentUsedUniformStreamBuffersCount = 0; - currentUsedDescriptorSetsCount = 0; - - // we needed more memory last frame, let's collapse all buffers into a single one. - if (streamBuffers.at(currentFrame).size() > 1) + size_t newSize = 0; + for (auto streamBuffer : streamBuffers.at(currentFrame)) { - size_t newSize = 0; - for (auto streamBuffer : streamBuffers.at(currentFrame)) - { - newSize += streamBuffer->getSize(); - delete streamBuffer; - } - streamBuffers.at(currentFrame).clear(); - streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, newSize)); + newSize += streamBuffer->getSize(); + delete streamBuffer; } - // no collapse necessary, can just call nextFrame to reset the current (only) streambuffer - else - streamBuffers.at(currentFrame).at(0)->nextFrame(); + streamBuffers.at(currentFrame).clear(); + streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, newSize)); } - // still the same frame else - { - auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; - if (usedStreamBufferMemory >= streamBuffers.at(currentFrame).back()->getSize()) - { - // we ran out of memory in the current frame, need to allocate more. - streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); - currentUsedUniformStreamBuffersCount = 0; - } - } + streamBuffers.at(currentFrame).at(0)->nextFrame(); - VkDescriptorSet currentDescriptorSet; + if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) + descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); - if (pfn_vkCmdPushDescriptorSetKHR) - currentDescriptorSet = 0; - else - { - if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) - descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); - - currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); - } + currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); std::vector descriptorWrite{}; - VkDescriptorBufferInfo* bufferInfo = nullptr; - - if (!localUniformStagingData.empty()) { - // additional data is always added onto the last stream buffer in the current frame - auto currentStreamBuffer = streamBuffers.at(currentFrame).back(); - - auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned); - memcpy(mapInfo.data, localUniformStagingData.data(), localUniformStagingData.size()); - currentStreamBuffer->unmap(uniformBufferSizeAligned); - currentStreamBuffer->markUsed(uniformBufferSizeAligned); - - bufferInfo = new VkDescriptorBufferInfo(); - bufferInfo->buffer = (VkBuffer)currentStreamBuffer->getHandle(); - bufferInfo->offset = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; - bufferInfo->range = localUniformStagingData.size(); - - VkWriteDescriptorSet uniformWrite{}; - uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - uniformWrite.dstSet = currentDescriptorSet; - uniformWrite.dstBinding = uniformLocation; - uniformWrite.dstArrayElement = 0; - uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniformWrite.descriptorCount = 1; - uniformWrite.pBufferInfo = bufferInfo; - - descriptorWrite.push_back(uniformWrite); - } - std::vector imageInfos; - - // update everything other than uniform buffers (since that's already taken care of. - for (const auto& [key, val] : uniformInfos) { + + // update everything other than uniform buffers + for (const auto &[key, val] : uniformInfos) { // fixme: other types. if (val.baseType == UNIFORM_SAMPLER) { VkWriteDescriptorSet write{}; @@ -364,29 +310,93 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame } } - if (pfn_vkCmdPushDescriptorSetKHR) - pfn_vkCmdPushDescriptorSetKHR( - commandBuffer, - bindPoint, - pipelineLayout, - 0, - static_cast(descriptorWrite.size()), - descriptorWrite.data()); - else - { - vkUpdateDescriptorSets(device, static_cast(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr); - - vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); - - currentUsedDescriptorSetsCount++; - } + vkUpdateDescriptorSets(device, static_cast(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr); for (const auto imageInfo : imageInfos) delete imageInfo; - if (bufferInfo) - delete bufferInfo; +} - currentUsedUniformStreamBuffersCount++; +void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint) +{ + if (!localUniformData.empty()) + { + auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; + if (usedStreamBufferMemory >= streamBuffers.at(currentFrame).back()->getSize()) + { + streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); + currentUsedUniformStreamBuffersCount = 0; + } + + if (builtinUniformDataOffset.has_value()) + { + auto builtinData = vgfx->getCurrentBuiltinUniformData(); + auto dst = localUniformData.data() + builtinUniformDataOffset.value(); + memcpy(dst, &builtinData, sizeof(builtinData)); + } + + // additional data is always added onto the last stream buffer in the current frame + auto currentStreamBuffer = streamBuffers.at(currentFrame).back(); + + auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned); + memcpy(mapInfo.data, localUniformData.data(), localUniformData.size()); + currentStreamBuffer->unmap(uniformBufferSizeAligned); + currentStreamBuffer->markUsed(uniformBufferSizeAligned); + + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = (VkBuffer)currentStreamBuffer->getHandle(); + bufferInfo.offset = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; + bufferInfo.range = localUniformData.size(); + + VkWriteDescriptorSet uniformWrite{}; + uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + uniformWrite.dstSet = currentDescriptorSet; + uniformWrite.dstBinding = uniformLocation; + uniformWrite.dstArrayElement = 0; + uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uniformWrite.descriptorCount = 1; + uniformWrite.pBufferInfo = &bufferInfo; + + vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr); + + currentUsedUniformStreamBuffersCount++; + } + + static const std::vector builtinUniformTextures = { + BUILTIN_TEXTURE_MAIN, + BUILTIN_TEXTURE_VIDEO_Y, + BUILTIN_TEXTURE_VIDEO_CB, + BUILTIN_TEXTURE_VIDEO_CR, + }; + + for (const auto &builtin : builtinUniformTextures) + if (builtinUniformInfo[builtin] != nullptr) + { + auto texture = dynamic_cast(builtinUniformInfo[builtin]->textures[0]); + + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = texture->getImageLayout(); + imageInfo.imageView = (VkImageView)texture->getRenderTargetHandle(); + imageInfo.sampler = (VkSampler)texture->getSamplerHandle(); + + VkWriteDescriptorSet mainTexWrite{}; + mainTexWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + mainTexWrite.dstSet = currentDescriptorSet; + mainTexWrite.dstBinding = builtinUniformInfo[builtin]->location; + mainTexWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + mainTexWrite.descriptorCount = 1; + mainTexWrite.pImageInfo = &imageInfo; + + vkUpdateDescriptorSets(device, 1, &mainTexWrite, 0, nullptr); + } + + vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); + + currentUsedDescriptorSetsCount++; + + if (currentUsedDescriptorSetsCount >= static_cast(descriptorSetsVector.at(currentFrame).size())) + descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); + + currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); } Shader::~Shader() @@ -396,6 +406,13 @@ Shader::~Shader() void Shader::attach() { + auto &usedShadersInFrame = vgfx->getUsedShadersInFrame(); + if (usedShadersInFrame.find(this) == usedShadersInFrame.end()) + { + newFrame(vgfx->getFrameIndex()); + usedShadersInFrame.insert(this); + } + if (!isCompute) { if (Shader::current != this) @@ -415,25 +432,68 @@ int Shader::getVertexAttributeIndex(const std::string &name) return it == attributes.end() ? -1 : it->second; } -const Shader::UniformInfo* Shader::getUniformInfo(const std::string &name) const +const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const { return &uniformInfos.at(name); } -const Shader::UniformInfo* Shader::getUniformInfo(BuiltinUniform builtin) const +const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const { return builtinUniformInfo[builtin]; } -void Shader::updateUniform(const UniformInfo* info, int count) +static bool usesLocalUniformData(const graphics::Shader::UniformInfo *info) +{ + return info->baseType == graphics::Shader::UNIFORM_BOOL || + info->baseType == graphics::Shader::UNIFORM_FLOAT || + info->baseType == graphics::Shader::UNIFORM_INT || + info->baseType == graphics::Shader::UNIFORM_MATRIX || + info->baseType == graphics::Shader::UNIFORM_UINT; +} + +void Shader::updateUniform(const UniformInfo *info, int count) { if (current == this) Graphics::flushBatchedDrawsGlobal(); + + if (usesLocalUniformData(info)) + memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size()); + else if (info->baseType == UNIFORM_SAMPLER || info->baseType == UNIFORM_STORAGETEXTURE) + { + bool isSampler = info->baseType == UNIFORM_SAMPLER; + + std::vector imageInfos; + + for (int i = 0; i < count; i++) + { + auto vkTexture = dynamic_cast(info->textures[i]); + + VkDescriptorImageInfo imageInfo{}; + + imageInfo.imageLayout = vkTexture->getImageLayout(); + imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle(); + if (isSampler) + imageInfo.sampler = (VkSampler)vkTexture->getSamplerHandle(); + + imageInfos.push_back(imageInfo); + } + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = currentDescriptorSet; + write.dstBinding = info->location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write.descriptorCount = static_cast(count); + write.pImageInfo = imageInfos.data(); + + vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); + } } void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count) { - for (unsigned i = 0; i < count; i++) + for (int i = 0; i < count; i++) { auto oldTexture = info->textures[i]; info->textures[i] = textures[i]; @@ -457,11 +517,11 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: { using namespace spirv_cross; - const auto& membertypes = type.member_types; + const auto &membertypes = type.member_types; for (size_t uindex = 0; uindex < membertypes.size(); uindex++) { - const auto& memberType = comp.get_type(membertypes[uindex]); + const auto &memberType = comp.get_type(membertypes[uindex]); size_t memberSize = comp.get_declared_struct_member_size(type, uindex); size_t offset = baseoff + comp.type_struct_member_offset(type, uindex); @@ -505,11 +565,11 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: u.matrix.columns = memberType.columns; } - const auto& reflectionIt = validationReflection.localUniforms.find(u.name); + const auto &reflectionIt = validationReflection.localUniforms.find(u.name); if (reflectionIt != validationReflection.localUniforms.end()) { - const auto& localUniform = reflectionIt->second; - const auto& values = localUniform.initializerValues; + const auto &localUniform = reflectionIt->second; + const auto &values = localUniform.initializerValues; if (!values.empty()) memcpy( u.data, @@ -562,8 +622,8 @@ void Shader::compileShaders() tshader->setGlobalUniformBinding(0); tshader->setGlobalUniformSet(0); - auto& glsl = stages[i]->getSource(); - const char* csrc = glsl.c_str(); + auto &glsl = stages[i]->getSource(); + const char *csrc = glsl.c_str(); const int sourceLength = static_cast(glsl.length()); tshader->setStringsWithLengths(&csrc, &sourceLength, 1); @@ -574,8 +634,8 @@ void Shader::compileShaders() if (!tshader->parse(&defaultTBuiltInResource, defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings)) { - const char* msg1 = tshader->getInfoLog(); - const char* msg2 = tshader->getInfoDebugLog(); + const char *msg1 = tshader->getInfoLog(); + const char *msg2 = tshader->getInfoDebugLog(); throw love::Exception("error while parsing shader"); } @@ -640,7 +700,7 @@ void Shader::compileShaders() auto shaderResources = comp.get_shader_resources(active); comp.set_enabled_interface_variables(std::move(active)); - for (const auto& resource : shaderResources.uniform_buffers) + for (const auto &resource : shaderResources.uniform_buffers) { if (resource.name == "gl_DefaultUniformBlock") { @@ -648,22 +708,26 @@ void Shader::compileShaders() size_t uniformBufferObjectSize = comp.get_declared_struct_size(type); auto defaultUniformBlockSize = comp.get_declared_struct_size(type); localUniformStagingData.resize(defaultUniformBlockSize); + localUniformData.resize(defaultUniformBlockSize); uniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding); memset(localUniformStagingData.data(), 0, defaultUniformBlockSize); + memset(localUniformData.data(), 0, defaultUniformBlockSize); std::string basename(""); buildLocalUniforms(comp, type, 0, basename); + + memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size()); } else throw love::Exception("unimplemented: non default uniform blocks."); } - for (const auto& r : shaderResources.sampled_images) + for (const auto &r : shaderResources.sampled_images) { - const SPIRType& basetype = comp.get_type(r.base_type_id); - const SPIRType& type = comp.get_type(r.type_id); - const SPIRType& imagetype = comp.get_type(basetype.image.type); + const SPIRType &basetype = comp.get_type(r.base_type_id); + const SPIRType &type = comp.get_type(r.type_id); + const SPIRType &imagetype = comp.get_type(basetype.image.type); graphics::Shader::UniformInfo info; info.location = comp.get_decoration(r.id, spv::DecorationBinding); @@ -729,9 +793,9 @@ void Shader::compileShaders() builtinUniformInfo[builtin] = &uniformInfos[info.name]; } - for (const auto& r : shaderResources.storage_buffers) + for (const auto &r : shaderResources.storage_buffers) { - const auto& type = comp.get_type(r.type_id); + const auto &type = comp.get_type(r.type_id); UniformInfo u{}; u.baseType = UNIFORM_STORAGEBUFFER; @@ -752,7 +816,7 @@ void Shader::compileShaders() // todo: some stuff missing - u.buffers = new love::graphics::Buffer * [u.count]; + u.buffers = new love::graphics::Buffer *[u.count]; for (int i = 0; i < u.count; i++) u.buffers[i] = nullptr; @@ -760,16 +824,16 @@ void Shader::compileShaders() uniformInfos[u.name] = u; } - for (const auto& r : shaderResources.storage_images) + for (const auto &r : shaderResources.storage_images) { - const auto& type = comp.get_type(r.type_id); + const auto &type = comp.get_type(r.type_id); UniformInfo u{}; u.baseType = UNIFORM_STORAGETEXTURE; u.components = 1; u.name = r.name; u.count = type.array.empty() ? 1 : type.array[0]; - u.textures = new love::graphics::Texture * [u.count]; + u.textures = new love::graphics::Texture *[u.count]; u.location = comp.get_decoration(r.id, spv::DecorationBinding); for (int i = 0; i < u.count; i++) @@ -781,9 +845,9 @@ void Shader::compileShaders() } if (shaderStage == SHADERSTAGE_VERTEX) - for (const auto& r : shaderResources.stage_inputs) + for (const auto &r : shaderResources.stage_inputs) { - const auto& name = r.name; + const auto &name = r.name; const int attributeLocation = static_cast(comp.get_decoration(r.id, spv::DecorationLocation)); attributes[name] = attributeLocation; } @@ -798,7 +862,7 @@ void Shader::createDescriptorSetLayout() { std::vector bindings; - for (auto const& [key, val] : uniformInfos) + for (auto const &[key, val] : uniformInfos) { auto type = Vulkan::getDescriptorType(val.baseType); if (type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) @@ -834,8 +898,6 @@ void Shader::createDescriptorSetLayout() layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.bindingCount = static_cast(bindings.size()); layoutInfo.pBindings = bindings.data(); - if (pfn_vkCmdPushDescriptorSetKHR) - layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) throw love::Exception("failed to create descriptor set layout"); @@ -874,7 +936,7 @@ void Shader::createStreamBuffers() streamBuffers[i].push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); } -void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) +void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture) { // if the shader doesn't actually use these textures they might get optimized out // in that case this function becomes a noop. @@ -901,21 +963,13 @@ void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cb } } -bool Shader::hasUniform(const std::string& name) const +bool Shader::hasUniform(const std::string &name) const { return uniformInfos.find(name) != uniformInfos.end(); } -void Shader::setUniformData(BuiltinUniformData& data) +void Shader::setMainTex(graphics::Texture *texture) { - char* ptr = (char*) builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW]->data + builtinUniformDataOffset; - memcpy(ptr, &data, sizeof(BuiltinUniformData)); -} - -void Shader::setMainTex(graphics::Texture* texture) -{ - // if the shader doesn't actually use the texture it might get optimized out - // in that case this function becomes a noop. if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN] != nullptr) { auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0]; @@ -938,7 +992,7 @@ VkDescriptorSet Shader::allocateDescriptorSet() sizes.push_back(size); - for (const auto& [key, val] : uniformInfos) + for (const auto &[key, val] : uniformInfos) { VkDescriptorPoolSize size{}; auto type = Vulkan::getDescriptorType(val.baseType); diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 8ec87c2c5..dbd418c02 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -12,9 +12,9 @@ // C++ #include #include -#include #include #include +#include namespace love @@ -43,7 +43,9 @@ public: const VkPipelineLayout getGraphicsPipelineLayout() const; - void cmdPushDescriptorSets(VkCommandBuffer, uint32_t currentFrame, VkPipelineBindPoint); + void newFrame(uint32_t frameIndex); + + void cmdPushDescriptorSets(VkCommandBuffer, VkPipelineBindPoint); void attach() override; @@ -65,8 +67,6 @@ public: void setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture) override; - // fixme: use normal methods for this in the future. - void setUniformData(BuiltinUniformData &data); void setMainTex(graphics::Texture *texture); private: @@ -83,8 +83,6 @@ private: VkDescriptorSet allocateDescriptorSet(); - PFN_vkCmdPushDescriptorSetKHR pfn_vkCmdPushDescriptorSetKHR = nullptr; - VkDeviceSize uniformBufferSizeAligned; VkPipeline computePipeline; @@ -112,12 +110,15 @@ private: UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM]; std::unique_ptr uniformBufferObjectBuffer; + std::vector localUniformData; std::vector localUniformStagingData; uint32_t uniformLocation; - size_t builtinUniformDataOffset; + std::optional builtinUniformDataOffset; std::unordered_map attributes; + VkDescriptorSet currentDescriptorSet; + uint32_t currentFrame; uint32_t currentUsedUniformStreamBuffersCount; uint32_t currentUsedDescriptorSetsCount;