Allow building SPIR-V with debug info and check debug info in reflection

This commit is contained in:
baldurk
2019-08-16 17:38:35 +01:00
parent 47e10a5c2d
commit dc660aa26c
8 changed files with 95 additions and 10 deletions
+62
View File
@@ -196,6 +196,11 @@ void main() {
ShaderBindpointMapping mapping;
compile(ShaderStage::Fragment, source, "main", refl, mapping);
if(testType == ShaderType::eShaderGLSPIRV)
CHECK(refl.encoding == ShaderEncoding::SPIRV);
else
CHECK(refl.encoding == ShaderEncoding::GLSL);
REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 1);
{
CHECK(refl.constantBlocks[0].name == "$Globals");
@@ -308,6 +313,8 @@ void main() {
ShaderBindpointMapping mapping;
compile(ShaderStage::Fragment, source, "main", refl, mapping);
CHECK(refl.encoding == ShaderEncoding::SPIRV);
REQUIRE_ARRAY_SIZE(refl.samplers.size(), 1);
{
CHECK(refl.samplers[0].name == "S");
@@ -526,6 +533,61 @@ void main() {
RDCFATAL("Unexpected test type");
}
SECTION("Debug information")
{
std::string source = R"(
#version 450 core
layout(location = 3) in vec2 a_input;
layout(location = 6) flat in uvec3 z_input;
layout(location = 0) out vec4 a_output;
layout(location = 1) out vec3 z_output;
layout(location = 2) out int b_output;
void main() {
a_output = vec4(a_input.y + gl_FragCoord.x, 0, 0, 1);
z_output = vec3(a_output.xy, a_output.z);
b_output = int(z_input.x);
gl_FragDepth = float(z_output.y);
}
)";
ShaderReflection refl;
ShaderBindpointMapping mapping;
compile(ShaderStage::Fragment, source, "main", refl, mapping);
CHECK(refl.entryPoint == "main");
CHECK(refl.stage == ShaderStage::Fragment);
CHECK(refl.debugInfo.encoding == ShaderEncoding::GLSL);
REQUIRE(refl.debugInfo.files.size() == 1);
CHECK(refl.debugInfo.files[0].contents == source);
if(testType == eShaderGLSL)
{
CHECK(refl.debugInfo.files[0].filename == "main.glsl");
}
else
{
CHECK(refl.debugInfo.files[0].filename == "source0.glsl");
REQUIRE(refl.debugInfo.compileFlags.flags.size() == 1);
CHECK(refl.debugInfo.compileFlags.flags[0].name == "@cmdline");
if(testType == eShaderGLSPIRV)
CHECK(refl.debugInfo.compileFlags.flags[0].value ==
" --client opengl100 --target-env opengl --entry-point main");
else
CHECK(refl.debugInfo.compileFlags.flags[0].value ==
" --client vulkan100 --target-env vulkan1.0 --entry-point main");
}
};
SECTION("Input and output signatures")
{
std::string source = R"(
+5
View File
@@ -1103,6 +1103,11 @@ static void AddSigParameter(std::vector<SigParameter> &sigs, uint32_t &regIndex,
void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &refl,
const FixedFunctionVertexOutputs &outputUsage)
{
refl.stage = MakeShaderStage(shadType);
refl.entryPoint = "main";
refl.encoding = ShaderEncoding::GLSL;
refl.debugInfo.encoding = ShaderEncoding::GLSL;
if(shadType == eGL_COMPUTE_SHADER)
{
GL.glGetProgramiv(sepProg, eGL_COMPUTE_WORK_GROUP_SIZE, (GLint *)refl.dispatchThreadsDimension);
+8 -2
View File
@@ -3469,6 +3469,10 @@ void MakeOfflineShaderReflection(ShaderStage stage, const std::string &source,
MakeShaderReflection(ShaderEnum((size_t)stage), fakeProg, refl, outputUsage);
refl.debugInfo.files.resize(1);
refl.debugInfo.files[0].filename = "main.glsl";
refl.debugInfo.files[0].contents = source;
// implement some stubs for testing
GL.glGetUniformLocation = &_testStub_GetUniformLocation;
GL.glGetUniformiv = &_testStub_GetUniformiv;
@@ -3488,8 +3492,6 @@ void MakeOfflineShaderReflection(ShaderStage stage, const std::string &source,
// helper function that uses the replay proxy system to compile and reflect the shader using the
// current driver. Unused by default but you can change the unit test below to call this function
// instead of MakeOfflineShaderReflection.
//
// Note that we can't fill out ShaderBindpointMapping easily on the actual driver
void MakeOnlineShaderReflection(ShaderStage stage, const std::string &source,
const std::string &entryPoint, ShaderReflection &refl,
ShaderBindpointMapping &mapping)
@@ -3526,6 +3528,10 @@ void MakeOnlineShaderReflection(ShaderStage stage, const std::string &source,
refl = *driver->GetShader(id, ShaderEntryPoint("main", ShaderStage::Fragment));
// Note that we can't fill out ShaderBindpointMapping easily on the actual driver through the
// replay interface
WARN("Using online reflection - all checks with ShaderBindpointMapping will fail");
driver->FreeCustomShader(id);
driver->Shutdown();
@@ -272,15 +272,9 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
disassembly = s;
reflection.resourceId = id;
reflection.entryPoint = "main";
reflection.stage = MakeShaderStage(type);
reflection.encoding = ShaderEncoding::GLSL;
reflection.rawBytes.assign((byte *)concatenated.c_str(), concatenated.size());
reflection.debugInfo.encoding = ShaderEncoding::GLSL;
reflection.debugInfo.files.resize(1);
reflection.debugInfo.files[0].filename = "main.glsl";
reflection.debugInfo.files[0].contents = concatenated;
@@ -41,9 +41,16 @@ std::string rdcspv::Compile(const rdcspv::CompilationSettings &settings,
std::string errors = "";
const char **strs = new const char *[sources.size()];
const char **names = new const char *[sources.size()];
std::vector<std::string> names_str;
names_str.resize(sources.size());
for(size_t i = 0; i < sources.size(); i++)
{
strs[i] = sources[i].c_str();
names_str[i] = StringFormat::Fmt("source%d.glsl", i);
names[i] = names_str[i].c_str();
}
RDCCOMPILE_ASSERT((int)EShLangVertex == (int)rdcspv::ShaderStage::Vertex &&
(int)EShLangTessControl == (int)rdcspv::ShaderStage::TessControl &&
@@ -58,7 +65,7 @@ std::string rdcspv::Compile(const rdcspv::CompilationSettings &settings,
glslang::TShader *shader = new glslang::TShader(lang);
shader->setStrings(strs, (int)sources.size());
shader->setStringsWithLengthsAndNames(strs, NULL, names, (int)sources.size());
if(!settings.entryPoint.empty())
shader->setEntryPoint(settings.entryPoint.c_str());
@@ -70,6 +77,9 @@ std::string rdcspv::Compile(const rdcspv::CompilationSettings &settings,
if(settings.lang == rdcspv::InputLanguage::VulkanHLSL)
flags = EShMessages(flags | EShMsgVulkanRules | EShMsgReadHlsl);
if(settings.debugInfo)
flags = EShMessages(flags | EShMsgDebugInfo);
bool success = shader->parse(GetDefaultResources(), 110, false, flags);
if(!success)
@@ -101,7 +111,11 @@ std::string rdcspv::Compile(const rdcspv::CompilationSettings &settings,
// if we successfully compiled and linked, we must have the stage we started with
RDCASSERT(intermediate);
glslang::GlslangToSpv(*intermediate, spirv);
glslang::SpvOptions opts;
if(settings.debugInfo)
opts.generateDebugInfo = true;
glslang::GlslangToSpv(*intermediate, spirv, &opts);
}
delete program;
@@ -111,6 +125,7 @@ std::string rdcspv::Compile(const rdcspv::CompilationSettings &settings,
}
delete[] strs;
delete[] names;
return errors;
}
@@ -55,6 +55,7 @@ struct CompilationSettings
ShaderStage stage = ShaderStage::Invalid;
InputLanguage lang = InputLanguage::Unknown;
bool debugInfo = false;
std::string entryPoint;
};
@@ -4209,6 +4209,7 @@ void SPVModule::MakeReflection(GraphicsAPI sourceAPI, ShaderStage stage,
// VKTODOLOW filter to only functions/resources used by entryPoint
reflection.entryPoint = entryPoint;
reflection.stage = stage;
reflection.encoding = ShaderEncoding::SPIRV;
// TODO sort these so that the entry point is in the first file
if(!sourceFiles.empty())
@@ -218,6 +218,7 @@ TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]")
? rdcspv::InputLanguage::VulkanGLSL
: rdcspv::InputLanguage::OpenGLGLSL,
rdcspv::ShaderStage(stage));
settings.debugInfo = true;
std::string errors = rdcspv::Compile(settings, {source}, spirv);
INFO("SPIR-V compile output: " << errors);