Revert "vulkan: use push constants for builtin uniforms"

This reverts commit 47e3fc85d2.
This commit is contained in:
niki
2022-09-15 15:55:47 +02:00
parent 47e3fc85d2
commit f4c38eb00a
9 changed files with 79 additions and 223 deletions
+60 -159
View File
@@ -4,7 +4,7 @@
#include "libraries/glslang/glslang/Public/ShaderLang.h"
#include "libraries/glslang/SPIRV/GlslangToSpv.h"
#include <set>
#include <vector>
namespace love
@@ -327,24 +327,10 @@ void Shader::newFrame(uint32_t frameIndex)
vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
}
}
if (useBuiltinUniformPushConstant)
{
if (!localUniformData.empty())
{
}
}
}
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint)
{
if (useBuiltinUniformPushConstant)
{
auto builtinData = vgfx->getCurrentBuiltinUniformData();
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(BuiltinUniformData), &builtinData);
}
if (!localUniformData.empty())
{
auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned;
@@ -539,7 +525,6 @@ void Shader::calculateUniformBufferSizeAligned()
uniformBufferSizeAligned = factor * minAlignment;
}
void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
{
using namespace spirv_cross;
@@ -616,40 +601,6 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::
}
}
static void parse(glslang::TShader* tshader, EShLanguage stage, const std::string &glsl, bool spirv14)
{
using namespace glslang;
tshader->setEnvInput(EShSourceGlsl, stage, EShClientVulkan, 450);
tshader->setEnvClient(EShClientVulkan, EShTargetVulkan_1_2);
if (spirv14)
tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_4);
else
tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_0);
tshader->setAutoMapLocations(true);
tshader->setAutoMapBindings(true);
tshader->setEnvInputVulkanRulesRelaxed();
tshader->setGlobalUniformBinding(0);
tshader->setGlobalUniformSet(0);
const char* csrc = glsl.c_str();
const int sourceLength = static_cast<int>(glsl.length());
tshader->setStringsWithLengths(&csrc, &sourceLength, 1);
int defaultVersion = 450;
EProfile defaultProfile = ECoreProfile;
bool forceDefault = false;
bool forwardCompat = true;
if (!tshader->parse(&defaultTBuiltInResource, defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings))
{
const char* msg1 = tshader->getInfoLog();
const char* msg2 = tshader->getInfoDebugLog();
throw love::Exception("error while parsing shader");
}
}
void Shader::compileShaders()
{
using namespace glslang;
@@ -662,7 +613,6 @@ void Shader::compileShaders()
device = vgfx->getDevice();
const auto &enabledExtensions = vgfx->getEnabledOptionalDeviceExtensions();
auto useSpirv14 = enabledExtensions.spirv14;
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
{
@@ -677,7 +627,35 @@ void Shader::compileShaders()
auto glslangShaderStage = getGlslShaderType(stage);
auto tshader = new TShader(glslangShaderStage);
parse(tshader, glslangShaderStage, stages[i]->getSource(), useSpirv14);
tshader->setEnvInput(EShSourceGlsl, glslangShaderStage, EShClientVulkan, 450);
tshader->setEnvClient(EShClientVulkan, EShTargetVulkan_1_2);
if (enabledExtensions.spirv14)
tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_4);
else
tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_0);
tshader->setAutoMapLocations(true);
tshader->setAutoMapBindings(true);
tshader->setEnvInputVulkanRulesRelaxed();
tshader->setGlobalUniformBinding(0);
tshader->setGlobalUniformSet(0);
auto &glsl = stages[i]->getSource();
const char *csrc = glsl.c_str();
const int sourceLength = static_cast<int>(glsl.length());
tshader->setStringsWithLengths(&csrc, &sourceLength, 1);
int defaultVersion = 450;
EProfile defaultProfile = ECoreProfile;
bool forceDefault = false;
bool forwardCompat = true;
if (!tshader->parse(&defaultTBuiltInResource, defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings))
{
const char *msg1 = tshader->getInfoLog();
const char *msg2 = tshader->getInfoDebugLog();
throw love::Exception("error while parsing shader");
}
program->addShader(tshader);
glslangShaders.push_back(tshader);
@@ -691,8 +669,6 @@ void Shader::compileShaders()
uniformInfos.clear();
std::set<uint32_t> usedBufferBindings;
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
{
auto shaderStage = (ShaderStageType)i;
@@ -702,26 +678,6 @@ void Shader::compileShaders()
continue;
}
bool recompile = false;
auto getFreeBinding = [&](uint32_t binding) {
if (usedBufferBindings.find(binding) == usedBufferBindings.end())
{
usedBufferBindings.insert(binding);
return binding;
}
recompile = true;
for (uint32_t i = 0; ; i++)
{
if (usedBufferBindings.find(i) == usedBufferBindings.end())
{
usedBufferBindings.insert(i);
return i;
}
}
};
spv::SpvBuildLogger logger;
glslang::SpvOptions opt;
opt.validate = true;
@@ -731,6 +687,29 @@ void Shader::compileShaders()
std::string msgs = logger.getAllMessages();
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = spirv.size() * sizeof(uint32_t);
createInfo.pCode = spirv.data();
auto device = vgfx->getDevice();
VkShaderModule shaderModule;
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw love::Exception("failed to create shader module");
}
shaderModules.push_back(shaderModule);
VkPipelineShaderStageCreateInfo shaderStageInfo{};
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStageInfo.stage = getStageBit((ShaderStageType)i);
shaderStageInfo.module = shaderModule;
shaderStageInfo.pName = "main";
shaderStages.push_back(shaderStageInfo);
spirv_cross::CompilerGLSL comp(spirv);
// we only care about variables that are actually getting used.
@@ -738,25 +717,16 @@ void Shader::compileShaders()
auto shaderResources = comp.get_shader_resources(active);
comp.set_enabled_interface_variables(std::move(active));
for (const auto &resource : shaderResources.push_constant_buffers)
for (const auto &resource : shaderResources.uniform_buffers)
{
useBuiltinUniformPushConstant = true;
}
for (const auto &resource : shaderResources.uniform_buffers)
{
if (uniformInfos.find(resource.name) != uniformInfos.end())
continue;
if (resource.name == "gl_DefaultUniformBlock")
{
const auto &type = comp.get_type(resource.base_type_id);
const auto& type = comp.get_type(resource.base_type_id);
size_t uniformBufferObjectSize = comp.get_declared_struct_size(type);
auto defaultUniformBlockSize = comp.get_declared_struct_size(type);
localUniformStagingData.resize(defaultUniformBlockSize);
localUniformData.resize(defaultUniformBlockSize);
uniformLocation = getFreeBinding(comp.get_decoration(resource.id, spv::DecorationBinding));
comp.set_decoration(resource.id, spv::DecorationBinding, uniformLocation);
uniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
memset(localUniformStagingData.data(), 0, defaultUniformBlockSize);
memset(localUniformData.data(), 0, defaultUniformBlockSize);
@@ -772,16 +742,12 @@ void Shader::compileShaders()
for (const auto &r : shaderResources.sampled_images)
{
if (uniformInfos.find(r.name) != uniformInfos.end())
continue;
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 = getFreeBinding(comp.get_decoration(r.id, spv::DecorationBinding));
comp.set_decoration(r.id, spv::DecorationBinding, info.location);
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];
@@ -846,9 +812,6 @@ void Shader::compileShaders()
for (const auto &r : shaderResources.storage_buffers)
{
if (uniformInfos.find(r.name) != uniformInfos.end())
continue;
const auto &type = comp.get_type(r.type_id);
UniformInfo u{};
@@ -856,9 +819,8 @@ void Shader::compileShaders()
u.components = 1;
u.name = r.name;
u.count = type.array.empty() ? 1 : type.array[0];
u.location = getFreeBinding(comp.get_decoration(r.id, spv::DecorationBinding));
comp.set_decoration(r.id, spv::DecorationBinding, u.location);
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
const auto reflectionit = validationReflection.storageBuffers.find(u.name);
if (reflectionit != validationReflection.storageBuffers.end())
{
@@ -882,9 +844,6 @@ void Shader::compileShaders()
for (const auto &r : shaderResources.storage_images)
{
if (uniformInfos.find(r.name) != uniformInfos.end())
continue;
const auto &type = comp.get_type(r.type_id);
UniformInfo u{};
@@ -892,10 +851,8 @@ void Shader::compileShaders()
u.components = 1;
u.name = r.name;
u.count = type.array.empty() ? 1 : type.array[0];
// fixme: memory leak
u.textures = new love::graphics::Texture *[u.count];
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
comp.set_decoration(r.id, spv::DecorationBinding, u.location);
for (int i = 0; i < u.count; i++)
u.textures[i] = nullptr;
@@ -912,50 +869,6 @@ void Shader::compileShaders()
const int attributeLocation = static_cast<int>(comp.get_decoration(r.id, spv::DecorationLocation));
attributes[name] = attributeLocation;
}
if (recompile)
{
auto glslLanguage = getGlslShaderType((ShaderStageType)i);
TShader* shader = new TShader(glslLanguage);
parse(shader, glslLanguage, comp.compile(), useSpirv14);
auto intermediate = shader->getIntermediate();
spv::SpvBuildLogger logger;
glslang::SpvOptions opt;
std::vector<uint32_t> code;
GlslangToSpv(*intermediate, code, &logger, &opt);
spirv = std::move(code);
delete shader;
}
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = spirv.size() * sizeof(uint32_t);
createInfo.pCode = spirv.data();
auto device = vgfx->getDevice();
VkShaderModule shaderModule;
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw love::Exception("failed to create shader module");
}
shaderModules.push_back(shaderModule);
VkPipelineShaderStageCreateInfo shaderStageInfo{};
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStageInfo.stage = getStageBit((ShaderStageType)i);
shaderStageInfo.module = shaderModule;
shaderStageInfo.pName = "main";
shaderStages.push_back(shaderStageInfo);
}
delete program;
@@ -1014,19 +927,7 @@ void Shader::createPipelineLayout()
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
static_assert(sizeof(BuiltinUniformData) % 4 == 0, "size of push constant has to be a multiple of 4.");
VkPushConstantRange range{};
range.offset = 0;
range.size = sizeof(BuiltinUniformData);
range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
if (useBuiltinUniformPushConstant)
{
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &range;
}
pipelineLayoutInfo.pushConstantRangeCount = 0;
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
throw love::Exception("failed to create pipeline layout");