From f9ad1842b52f57e68f859de12780b707a46ae872 Mon Sep 17 00:00:00 2001 From: niki Date: Sun, 14 Aug 2022 04:56:20 +0200 Subject: [PATCH] vulkan: first iteration for generic uniforms Until now we only considered the builtin uniform variables. This commit attempts to make the code in the vulkan Shader implementation more general, as to allow for custom uniforms. This is not possible yet, but should be easier to implement now. --- CMakeLists.txt | 38 +++ src/modules/graphics/vulkan/Shader.cpp | 357 ++++++++++++++++++------- src/modules/graphics/vulkan/Shader.h | 31 ++- 3 files changed, 315 insertions(+), 111 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be5315b04..4e6a6c949 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1671,6 +1671,43 @@ endif() add_library(love_3p_physfs ${LOVE_SRC_3P_PHYSFS}) +# +# spirv_cross +# + +set(LOVE_SRC_3P_SPIRV_CROSS + src/libraries/spirv_cross/GLSL.std.450.h + src/libraries/spirv_cross/spirv_cfg.cpp + src/libraries/spirv_cross/spirv_cfg.hpp + src/libraries/spirv_cross/spirv_common.hpp + src/libraries/spirv_cross/spirv_cpp.cpp + src/libraries/spirv_cross/spirv_cpp.hpp + src/libraries/spirv_cross/spirv_cross_c.cpp + src/libraries/spirv_cross/spirv_cross_c.h + src/libraries/spirv_cross/spirv_cross_containers.hpp + src/libraries/spirv_cross/spirv_cross_error_handling.hpp + src/libraries/spirv_cross/spirv_cross_parsed_ir.cpp + src/libraries/spirv_cross/spirv_cross_parsed_ir.hpp + src/libraries/spirv_cross/spirv_cross_util.cpp + src/libraries/spirv_cross/spirv_cross_util.hpp + src/libraries/spirv_cross/spirv_cross.cpp + src/libraries/spirv_cross/spirv_cross.hpp + src/libraries/spirv_cross/spirv_glsl.cpp + src/libraries/spirv_cross/spirv_glsl.hpp + src/libraries/spirv_cross/spirv_hlsl.cpp + src/libraries/spirv_cross/spirv_hlsl.hpp + src/libraries/spirv_cross/spirv_msl.cpp + src/libraries/spirv_cross/spirv_msl.hpp + src/libraries/spirv_cross/spirv_parser.cpp + src/libraries/spirv_cross/spirv_parser.hpp + src/libraries/spirv_cross/spirv_reflect.cpp + src/libraries/spirv_cross/spirv_reflect.hpp + src/libraries/spirv_cross/spirv.h + src/libraries/spirv_cross/spirv.hpp +) + +add_library(love_3p_spirv_cross ${LOVE_SRC_3P_SPIRV_CROSS}) + # # stb_image # @@ -1752,6 +1789,7 @@ set(LOVE_3P love_3p_lz4 love_3p_noise1234 love_3p_physfs + love_3p_spirv_cross love_3p_wuff love_3p_xxhash ) diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index db42763fc..35209cd7b 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -3,7 +3,7 @@ #include "libraries/glslang/glslang/Public/ShaderLang.h" #include "libraries/glslang/SPIRV/GlslangToSpv.h" -#include "libraries/spirv_cross/spirv_cross.hpp" + #include @@ -150,12 +150,12 @@ Shader::Shader(StrongRef stages[]) } bool Shader::loadVolatile() { - calculateUniformBufferSizeAligned(); compileShaders(); + calculateUniformBufferSizeAligned(); createDescriptorSetLayout(); createPipelineLayout(); createStreamBuffers(); - currentImage = 0; + currentFrame = 0; count = 0; return true; @@ -201,42 +201,42 @@ static VkDescriptorImageInfo createDescriptorImageInfo(graphics::Texture* textur return imageInfo; } -void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t imageIndex) { +void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frameIndex) { // detect wether a new frame has begun - if (currentImage != imageIndex) { - currentImage = imageIndex; + if (currentFrame != frameIndex) { + currentFrame = frameIndex; count = 0; // we needed more memory last frame, let's collapse all buffers into a single one. - if (streamBuffers.at(currentImage).size() > 1) { + if (streamBuffers.at(currentFrame).size() > 1) { size_t newSize = 0; - for (auto streamBuffer : streamBuffers.at(currentImage)) { + for (auto streamBuffer : streamBuffers.at(currentFrame)) { newSize += streamBuffer->getSize(); delete streamBuffer; } - streamBuffers.at(currentImage).clear(); - streamBuffers.at(currentImage).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, newSize)); + streamBuffers.at(currentFrame).clear(); + streamBuffers.at(currentFrame).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, newSize)); } // no collapse necessary, can just call nextFrame to reset the current (only) streambuffer else { - streamBuffers.at(currentImage).at(0)->nextFrame(); + streamBuffers.at(currentFrame).at(0)->nextFrame(); } } // still the same frame else { auto usedStreamBufferMemory = count * uniformBufferSizeAligned; - if (usedStreamBufferMemory >= streamBuffers.at(currentImage).back()->getSize()) { + if (usedStreamBufferMemory >= streamBuffers.at(currentFrame).back()->getSize()) { // we ran out of memory in the current frame, need to allocate more. - streamBuffers.at(currentImage).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); + streamBuffers.at(currentFrame).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); count = 0; } } // additional data is always added onto the last stream buffer in the current frame - auto currentStreamBuffer = streamBuffers.at(currentImage).back(); + auto currentStreamBuffer = streamBuffers.at(currentFrame).back(); auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned); - memcpy(mapInfo.data, &uniformData, uniformBufferSizeAligned); + memcpy(mapInfo.data, localUniformStagingData.data(), uniformBufferSizeAligned); currentStreamBuffer->unmap(uniformBufferSizeAligned); currentStreamBuffer->markUsed(uniformBufferSizeAligned); @@ -245,53 +245,42 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t image bufferInfo.offset = count * uniformBufferSizeAligned; bufferInfo.range = sizeof(BuiltinUniformData); - auto mainTexImageInfo = createDescriptorImageInfo(mainTex); - auto ytextureImageInfo = createDescriptorImageInfo(ytexture); - auto cbtextureImageInfo = createDescriptorImageInfo(cbtexture); - auto crtextureImageInfo = createDescriptorImageInfo(crtexture); + std::vector descriptorWrite{}; - std::array descriptorWrite{}; - descriptorWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite[0].dstSet = 0; - descriptorWrite[0].dstBinding = 0; - descriptorWrite[0].dstArrayElement = 0; - descriptorWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrite[0].descriptorCount = 1; - descriptorWrite[0].pBufferInfo = &bufferInfo; + // uniform buffer update always happens. + VkWriteDescriptorSet uniformWrite{}; + uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + uniformWrite.dstSet = 0; + uniformWrite.dstBinding = builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW]->location; + uniformWrite.dstArrayElement = 0; + uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uniformWrite.descriptorCount = 1; + uniformWrite.pBufferInfo = &bufferInfo; - descriptorWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite[1].dstSet = 0; - descriptorWrite[1].dstBinding = 1; - descriptorWrite[1].dstArrayElement = 0; - descriptorWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite[1].descriptorCount = 1; - descriptorWrite[1].pImageInfo = &mainTexImageInfo; + descriptorWrite.push_back(uniformWrite); - descriptorWrite[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite[2].dstSet = 0; - descriptorWrite[2].dstBinding = 2; - descriptorWrite[2].dstArrayElement = 0; - descriptorWrite[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite[2].descriptorCount = 1; - descriptorWrite[2].pImageInfo = &ytextureImageInfo; + // update everything other than uniform buffers (since that's already taken care of. + for (const auto& [key, val] : uniformInfos) { + // fixme: other types. + if (val.baseType == UNIFORM_SAMPLER) { + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = 0; + write.dstBinding = val.location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write.descriptorCount = 1; + const auto imageInfo = createDescriptorImageInfo(val.textures[0]); // fixme: arrays + write.pImageInfo = &imageInfo; - descriptorWrite[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite[3].dstSet = 0; - descriptorWrite[3].dstBinding = 3; - descriptorWrite[3].dstArrayElement = 0; - descriptorWrite[3].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite[3].descriptorCount = 1; - descriptorWrite[3].pImageInfo = &cbtextureImageInfo; + descriptorWrite.push_back(write); + } + } - descriptorWrite[4].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite[4].dstSet = 0; - descriptorWrite[4].dstBinding = 4; - descriptorWrite[4].dstArrayElement = 0; - descriptorWrite[4].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite[4].descriptorCount = 1; - descriptorWrite[4].pImageInfo = &crtextureImageInfo; - - vkCmdPushDescriptorSet(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast(descriptorWrite.size()), descriptorWrite.data()); + vkCmdPushDescriptorSet( + commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipelineLayout, 0, + static_cast(descriptorWrite.size()), descriptorWrite.data()); count++; } @@ -309,22 +298,89 @@ void Shader::attach() { } int Shader::getVertexAttributeIndex(const std::string& name) { - return vertexAttributeIndices.at(name); + return 0; } void Shader::calculateUniformBufferSizeAligned() { gfx = Module::getInstance(Module::ModuleType::M_GRAPHICS); auto vgfx = (Graphics*)gfx; auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment(); + size_t size = localUniformStagingData.size(); uniformBufferSizeAligned = static_cast( std::ceil( - static_cast(sizeof(BuiltinUniformData)) / static_cast(minAlignment) + static_cast(size) / static_cast(minAlignment) ) ) * minAlignment; } +void Shader::buildLocalUniforms(spirv_cross::Compiler& comp, const spirv_cross::SPIRType& type, size_t baseoff, const std::string& basename) { + using namespace spirv_cross; + + const auto& membertypes = type.member_types; + + for (size_t uindex = 0; uindex < membertypes.size(); 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); + + std::string name = basename + comp.get_member_name(type.self, uindex); + + switch (memberType.basetype) { + case SPIRType::Struct: + name += "."; + buildLocalUniforms(comp, memberType, offset, name); + continue; + case SPIRType::Int: + case SPIRType::UInt: + case SPIRType::Float: + break; + default: + continue; + } + + UniformInfo u = {}; + u.name = name; + u.dataSize = memberSize; + u.count = memberType.array.empty() ? 1 : memberType.array[0]; + u.components = 1; + u.data = localUniformStagingData.data() + offset; + + if (memberType.columns == 1) { + if (memberType.basetype == SPIRType::Int) { + u.baseType = UNIFORM_INT; + } + else if (memberType.basetype == SPIRType::UInt) { + u.baseType = UNIFORM_UINT; + } + else { + u.baseType = UNIFORM_FLOAT; + } + u.components = memberType.vecsize; + } + else { + u.baseType = UNIFORM_MATRIX; + u.matrix.rows = memberType.vecsize; + u.matrix.columns = memberType.columns; + } + + // fixme: initializer values + + uniformInfos[u.name] = u; + + BuiltinUniform builtin = BUILTIN_MAX_ENUM; + if (getConstant(u.name.c_str(), builtin)) { + if (builtin == BUILTIN_UNIFORMS_PER_DRAW) { + builtinUniformDataOffset = offset; + } + builtinUniformInfo[builtin] = &uniformInfos[u.name]; + } + + // update uniform. + } +} + void Shader::compileShaders() { using namespace glslang; using namespace spirv_cross; @@ -335,7 +391,6 @@ void Shader::compileShaders() { auto vgfx = (Graphics*)gfx; device = vgfx->getDevice(); - mainTex = vgfx->getDefaultTexture(); ytexture = vgfx->getDefaultTexture(); crtexture = vgfx->getDefaultTexture(); cbtexture = vgfx->getDefaultTexture(); @@ -385,6 +440,8 @@ void Shader::compileShaders() { throw love::Exception("mapIO failed"); } + uniformInfos.clear(); + for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) { auto glslangStage = getGlslShaderType((ShaderStageType)i); auto intermediate = program->getIntermediate(glslangStage); @@ -424,49 +481,158 @@ void Shader::compileShaders() { shaderStageInfo.pName = "main"; shaderStages.push_back(shaderStageInfo); + + spirv_cross::CompilerGLSL comp(spirv); + + // we only care about variables that are actually getting used. + auto active = comp.get_active_interface_variables(); + auto shaderResources = comp.get_shader_resources(active); + comp.set_enabled_interface_variables(std::move(active)); + + std::string builtinUniformName = "love_UniformsPerDraw"; + + for (const auto& resource : shaderResources.uniform_buffers) { + size_t uniformBufferObjectSize = comp.get_declared_struct_size(comp.get_type(resource.base_type_id)); + + const auto& resourceType = comp.get_type(resource.type_id); + unsigned memberCount = resourceType.member_types.size(); + for (unsigned i = 0; i < memberCount; i++) { + auto& type = comp.get_type(resourceType.member_types[i]); + auto baseType = type.basetype; + const std::string& name = comp.get_member_name(resourceType.self, i); + + if (name == "gl_DefaultUniformBlock") { + auto defaultUniformBlockSize = comp.get_declared_struct_size(type); + localUniformStagingData.resize(defaultUniformBlockSize); + + std::string basename(""); + buildLocalUniforms(comp, type, 0, basename); + } + else if (name == builtinUniformName) { + UniformInfo u{}; + u.name = name; + u.dataSize = sizeof(BuiltinUniformData); + + localUniformStagingData.resize(u.dataSize); + builtinUniformDataOffset = 0; + + u.count = type.array.empty() ? 1 : type.array[0]; + u.components = 1; + u.data = localUniformStagingData.data(); + + if (type.columns == 1) { + if (type.basetype == SPIRType::Int) { + u.baseType = UNIFORM_INT; + } + else if (type.basetype == SPIRType::UInt) { + u.baseType = UNIFORM_UINT; + } + else { + u.baseType = UNIFORM_FLOAT; + } + u.components = type.vecsize; + } + else { + u.baseType = UNIFORM_MATRIX; + u.matrix.rows = type.vecsize; + u.matrix.columns = type.columns; + } + + uniformInfos[u.name] = u; + + builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW] = &uniformInfos[u.name]; + } + else { + throw love::Exception("unimplemented: non default uniform blocks."); + } + } + + 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); + + graphics::Shader::UniformInfo info; + info.location = comp.get_decoration(r.id, spv::DecorationBinding); + info.baseType = UNIFORM_SAMPLER; + info.name = r.name; + info.count = type.array.empty() ? 1 : type.array[0]; + info.isDepthSampler = type.image.depth; + info.components = 1; + + switch (imagetype.basetype) { + case SPIRType::Float: + info.dataBaseType = DATA_BASETYPE_FLOAT; + break; + case SPIRType::Int: + info.dataBaseType = DATA_BASETYPE_INT; + break; + case SPIRType::UInt: + info.dataBaseType = DATA_BASETYPE_UINT; + break; + default: + break; + } + + switch (basetype.image.dim) { + case spv::Dim2D: + info.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D; + info.textures = new love::graphics::Texture * [info.count]; + break; + case spv::Dim3D: + info.textureType = TEXTURE_VOLUME; + info.textures = new love::graphics::Texture * [info.count]; + break; + case spv::DimCube: + if (basetype.image.arrayed) { + throw love::Exception("cubemap arrays are not currently supported"); + } + info.textureType = TEXTURE_CUBE; + info.textures = new love::graphics::Texture * [info.count]; + break; + case spv::DimBuffer: + throw love::Exception("dim buffers not implemented yet"); + default: + throw love::Exception("unknown dim"); + } + + if (info.baseType == UNIFORM_SAMPLER) { + auto tex = vgfx->getDefaultTexture(); + for (int i = 0; i < info.count; i++) { + info.textures[i] = tex; + } + } + // fixme + else if (info.baseType == UNIFORM_TEXELBUFFER) { + throw love::Exception("texel buffers not supported yet"); + } + + uniformInfos[r.name] = info; + BuiltinUniform builtin; + if (getConstant(r.name.c_str(), builtin)) { + builtinUniformInfo[builtin] = &uniformInfos[info.name]; + } + } + } } } -// fixme: should generate this dynamically. void Shader::createDescriptorSetLayout() { auto vgfx = (Graphics*)gfx; vkCmdPushDescriptorSet = vgfx->getVkCmdPushDescriptorSetKHRFunctionPointer(); - VkDescriptorSetLayoutBinding uboLayoutBinding{}; - uboLayoutBinding.binding = 0; - uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uboLayoutBinding.descriptorCount = 1; - uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + std::vector bindings; - VkDescriptorSetLayoutBinding samplerLayoutBinding{}; - samplerLayoutBinding.binding = 1; - samplerLayoutBinding.descriptorCount = 1; - samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - samplerLayoutBinding.pImmutableSamplers = nullptr; - samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + for (auto const& [key, val] : uniformInfos) { + VkDescriptorSetLayoutBinding layoutBinding{}; + layoutBinding.binding = val.location; + layoutBinding.descriptorType = val.baseType == UNIFORM_SAMPLER ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layoutBinding.descriptorCount = 1; // is this correct? + layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; // fixme: can we determine in what shader it got used? - VkDescriptorSetLayoutBinding videoYBinding{}; - videoYBinding.binding = 2; - videoYBinding.descriptorCount = 1; - videoYBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - videoYBinding.pImmutableSamplers = nullptr; - videoYBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings.push_back(layoutBinding); + } - VkDescriptorSetLayoutBinding videoCBBinding{}; - videoCBBinding.binding = 3; - videoCBBinding.descriptorCount = 1; - videoCBBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - videoCBBinding.pImmutableSamplers = nullptr; - videoCBBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutBinding videoCRinding{}; - videoCRinding.binding = 4; - videoCRinding.descriptorCount = 1; - videoCRinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - videoCRinding.pImmutableSamplers = nullptr; - videoCRinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - std::array bindings = { uboLayoutBinding, samplerLayoutBinding, videoYBinding, videoCBBinding, videoCRinding }; VkDescriptorSetLayoutCreateInfo layoutInfo{}; layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; @@ -506,11 +672,12 @@ void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cb } void Shader::setUniformData(BuiltinUniformData& data) { - uniformData = data; + char* ptr = (char*) builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW]->data + builtinUniformDataOffset; + memcpy(ptr, &data, sizeof(BuiltinUniformData)); } void Shader::setMainTex(graphics::Texture* texture) { - mainTex = texture; + builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0] = texture; } } // vulkan } // graphics diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 13976a114..a23da784d 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -6,9 +6,12 @@ #include "Vulkan.h" #include +#include "libraries/spirv_cross/spirv_reflect.hpp" #include +#include #include +#include namespace love { @@ -26,7 +29,7 @@ public: const VkPipelineLayout getGraphicsPipelineLayout() const; - void cmdPushDescriptorSets(VkCommandBuffer, uint32_t currentImage); + void cmdPushDescriptorSets(VkCommandBuffer, uint32_t currentFrame); void attach() override; @@ -58,6 +61,11 @@ private: void createDescriptorSetLayout(); void createPipelineLayout(); void createStreamBuffers(); + void buildLocalUniforms( + spirv_cross::Compiler& comp, + const spirv_cross::SPIRType& type, + size_t baseoff, + const std::string& basename); VkDeviceSize uniformBufferSizeAligned; PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet; @@ -75,27 +83,18 @@ private: Graphics* gfx; VkDevice device; - std::map vertexAttributeIndices = { - { "VertexPosition", 0 }, - { "VertexTexCoord", 1 }, - { "VertexColor", 2 } - }; + std::unordered_map uniformInfos; + UniformInfo* builtinUniformInfo[BUILTIN_MAX_ENUM]; - std::map uniformBindings = { - { "love_UniformsPerDraw", 0 }, - { "love_VideoYChannel", 1 }, - { "love_VideoCbChannel", 2 }, - { "love_VideoCrChannel", 3 }, - { "MainTex", 4 } - }; + std::unique_ptr uniformBufferObjectBuffer; + std::vector localUniformStagingData; + size_t builtinUniformDataOffset; - BuiltinUniformData uniformData; - graphics::Texture* mainTex; graphics::Texture* ytexture; graphics::Texture* cbtexture; graphics::Texture* crtexture; - uint32_t currentImage; + uint32_t currentFrame; // todo: give this variable a better name uint32_t count; };