mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 05:20:45 +00:00
Add more compilation settings for SPIR-V, including source language
* This e.g. fixes the generation of SPIR-V for GL style GLSL with uniforms that are just global not in a UBO.
This commit is contained in:
@@ -73,7 +73,10 @@ void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl)
|
||||
|
||||
vector<uint32_t> spirvwords;
|
||||
|
||||
string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(type)), sources, spirvwords);
|
||||
SPIRVCompilationSettings settings(SPIRVSourceLanguage::OpenGLGLSL,
|
||||
SPIRVShaderStage(ShaderIdx(type)));
|
||||
|
||||
string s = CompileSPIRV(settings, sources, spirvwords);
|
||||
if(!spirvwords.empty())
|
||||
ParseSPIRV(&spirvwords.front(), spirvwords.size(), spirv);
|
||||
|
||||
|
||||
@@ -33,15 +33,33 @@
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
enum SPIRVShaderStage
|
||||
enum class SPIRVShaderStage
|
||||
{
|
||||
eSPIRVVertex,
|
||||
eSPIRVTessControl,
|
||||
eSPIRVTessEvaluation,
|
||||
eSPIRVGeometry,
|
||||
eSPIRVFragment,
|
||||
eSPIRVCompute,
|
||||
eSPIRVInvalid,
|
||||
Vertex,
|
||||
TessControl,
|
||||
TessEvaluation,
|
||||
Geometry,
|
||||
Fragment,
|
||||
Compute,
|
||||
Invalid,
|
||||
};
|
||||
|
||||
enum class SPIRVSourceLanguage
|
||||
{
|
||||
Unknown,
|
||||
OpenGLGLSL,
|
||||
VulkanGLSL,
|
||||
VulkanHLSL,
|
||||
};
|
||||
|
||||
struct SPIRVCompilationSettings
|
||||
{
|
||||
SPIRVCompilationSettings(SPIRVSourceLanguage l, SPIRVShaderStage s) : stage(s), lang(l) {}
|
||||
SPIRVCompilationSettings() = default;
|
||||
|
||||
SPIRVShaderStage stage = SPIRVShaderStage::Invalid;
|
||||
SPIRVSourceLanguage lang = SPIRVSourceLanguage::Unknown;
|
||||
std::string entryPoint;
|
||||
};
|
||||
|
||||
void InitSPIRVCompiler();
|
||||
@@ -108,10 +126,12 @@ struct SPVModule
|
||||
SPVInstruction *GetByID(uint32_t id);
|
||||
string Disassemble(const string &entryPoint);
|
||||
|
||||
ShaderStage StageForEntry(const string &entryPoint) const;
|
||||
|
||||
void MakeReflection(ShaderStage stage, const string &entryPoint, ShaderReflection &reflection,
|
||||
ShaderBindpointMapping &mapping, SPIRVPatchData &patchData);
|
||||
};
|
||||
|
||||
string CompileSPIRV(SPIRVShaderStage shadType, const vector<string> &sources,
|
||||
string CompileSPIRV(const SPIRVCompilationSettings &settings, const vector<string> &sources,
|
||||
vector<uint32_t> &spirv);
|
||||
void ParseSPIRV(uint32_t *spirv, size_t spirvLength, SPVModule &module);
|
||||
|
||||
@@ -130,10 +130,10 @@ TBuiltInResource DefaultResources = {
|
||||
},
|
||||
};
|
||||
|
||||
string CompileSPIRV(SPIRVShaderStage shadType, const std::vector<std::string> &sources,
|
||||
vector<uint32_t> &spirv)
|
||||
string CompileSPIRV(const SPIRVCompilationSettings &settings,
|
||||
const std::vector<std::string> &sources, vector<uint32_t> &spirv)
|
||||
{
|
||||
if(shadType >= eSPIRVInvalid)
|
||||
if(settings.stage == SPIRVShaderStage::Invalid)
|
||||
return "Invalid shader stage specified";
|
||||
|
||||
string errors = "";
|
||||
@@ -143,22 +143,32 @@ string CompileSPIRV(SPIRVShaderStage shadType, const std::vector<std::string> &s
|
||||
for(size_t i = 0; i < sources.size(); i++)
|
||||
strs[i] = sources[i].c_str();
|
||||
|
||||
RDCCOMPILE_ASSERT(
|
||||
(int)EShLangVertex == (int)eSPIRVVertex && (int)EShLangTessControl == (int)eSPIRVTessControl &&
|
||||
(int)EShLangTessEvaluation == (int)eSPIRVTessEvaluation &&
|
||||
(int)EShLangGeometry == (int)eSPIRVGeometry && (int)EShLangCompute == (int)eSPIRVCompute,
|
||||
"Shader language enums don't match");
|
||||
RDCCOMPILE_ASSERT((int)EShLangVertex == (int)SPIRVShaderStage::Vertex &&
|
||||
(int)EShLangTessControl == (int)SPIRVShaderStage::TessControl &&
|
||||
(int)EShLangTessEvaluation == (int)SPIRVShaderStage::TessEvaluation &&
|
||||
(int)EShLangGeometry == (int)SPIRVShaderStage::Geometry &&
|
||||
(int)EShLangCompute == (int)SPIRVShaderStage::Compute,
|
||||
"Shader language enums don't match");
|
||||
|
||||
{
|
||||
// these enums are matched
|
||||
EShLanguage lang = EShLanguage((int)shadType);
|
||||
EShLanguage lang = EShLanguage(settings.stage);
|
||||
|
||||
glslang::TShader *shader = new glslang::TShader(lang);
|
||||
|
||||
shader->setStrings(strs, (int)sources.size());
|
||||
|
||||
bool success = shader->parse(&DefaultResources, 110, false,
|
||||
EShMessages(EShMsgSpvRules | EShMsgVulkanRules));
|
||||
if(!settings.entryPoint.empty())
|
||||
shader->setEntryPoint(settings.entryPoint.c_str());
|
||||
|
||||
EShMessages flags = EShMsgSpvRules;
|
||||
|
||||
if(settings.lang == SPIRVSourceLanguage::VulkanGLSL)
|
||||
flags = EShMessages(flags | EShMsgVulkanRules);
|
||||
if(settings.lang == SPIRVSourceLanguage::VulkanHLSL)
|
||||
flags = EShMessages(flags | EShMsgVulkanRules | EShMsgReadHlsl);
|
||||
|
||||
bool success = shader->parse(&DefaultResources, 110, false, flags);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
|
||||
@@ -3871,6 +3871,29 @@ void AddSignatureParameter(bool isInput, ShaderStage stage, uint32_t id,
|
||||
}
|
||||
}
|
||||
|
||||
ShaderStage SPVModule::StageForEntry(const string &entryPoint) const
|
||||
{
|
||||
for(SPVInstruction *inst : entries)
|
||||
{
|
||||
if(inst->entry && inst->entry->name == entryPoint)
|
||||
{
|
||||
switch(inst->entry->model)
|
||||
{
|
||||
case spv::ExecutionModelVertex: return ShaderStage::Vertex;
|
||||
case spv::ExecutionModelTessellationControl: return ShaderStage::Tess_Control;
|
||||
case spv::ExecutionModelTessellationEvaluation: return ShaderStage::Tess_Eval;
|
||||
case spv::ExecutionModelGeometry: return ShaderStage::Geometry;
|
||||
case spv::ExecutionModelFragment: return ShaderStage::Fragment;
|
||||
case spv::ExecutionModelGLCompute: return ShaderStage::Compute;
|
||||
case spv::ExecutionModelKernel:
|
||||
case spv::ExecutionModelMax: return ShaderStage::Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ShaderStage::Count;
|
||||
}
|
||||
|
||||
void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
|
||||
ShaderReflection &reflection, ShaderBindpointMapping &mapping,
|
||||
SPIRVPatchData &patchData)
|
||||
@@ -3882,10 +3905,7 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
|
||||
|
||||
// VKTODOLOW filter to only functions/resources used by entryPoint
|
||||
|
||||
// VKTODOLOW set this properly
|
||||
reflection.DebugInfo.entryFile = 0;
|
||||
reflection.DebugInfo.entryFunc = entryPoint;
|
||||
|
||||
// TODO sort these so that the entry point is in the first file
|
||||
if(!sourceFiles.empty())
|
||||
{
|
||||
create_array_uninit(reflection.DebugInfo.files, sourceFiles.size());
|
||||
|
||||
@@ -170,7 +170,7 @@ struct VulkanBlobShaderCallbacks
|
||||
byte *GetData(vector<uint32_t> *blob) const { return (byte *)&(*blob)[0]; }
|
||||
} ShaderCacheCallbacks;
|
||||
|
||||
string VulkanDebugManager::GetSPIRVBlob(SPIRVShaderStage shadType,
|
||||
string VulkanDebugManager::GetSPIRVBlob(const SPIRVCompilationSettings &settings,
|
||||
const std::vector<std::string> &sources,
|
||||
vector<uint32_t> **outBlob)
|
||||
{
|
||||
@@ -180,8 +180,9 @@ string VulkanDebugManager::GetSPIRVBlob(SPIRVShaderStage shadType,
|
||||
for(size_t i = 1; i < sources.size(); i++)
|
||||
hash = strhash(sources[i].c_str(), hash);
|
||||
|
||||
char typestr[2] = {'a', 0};
|
||||
typestr[0] += (char)shadType;
|
||||
char typestr[3] = {'a', 'a', 0};
|
||||
typestr[0] += (char)settings.stage;
|
||||
typestr[1] += (char)settings.lang;
|
||||
hash = strhash(typestr, hash);
|
||||
|
||||
if(m_ShaderCache.find(hash) != m_ShaderCache.end())
|
||||
@@ -191,7 +192,7 @@ string VulkanDebugManager::GetSPIRVBlob(SPIRVShaderStage shadType,
|
||||
}
|
||||
|
||||
vector<uint32_t> *spirv = new vector<uint32_t>();
|
||||
string errors = CompileSPIRV(shadType, sources, *spirv);
|
||||
string errors = CompileSPIRV(settings, sources, *spirv);
|
||||
|
||||
if(!errors.empty())
|
||||
{
|
||||
@@ -747,6 +748,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
SPIRVCompilationSettings compileSettings;
|
||||
compileSettings.lang = SPIRVSourceLanguage::VulkanGLSL;
|
||||
|
||||
// needed in both replay and capture, create depth MS->array pipelines
|
||||
{
|
||||
{
|
||||
@@ -812,7 +816,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
vector<uint32_t> *spirv;
|
||||
|
||||
string err = GetSPIRVBlob(i == 0 ? eSPIRVVertex : eSPIRVFragment, sources, &spirv);
|
||||
compileSettings.stage = i == 0 ? SPIRVShaderStage::Vertex : SPIRVShaderStage::Fragment;
|
||||
string err = GetSPIRVBlob(compileSettings, sources, &spirv);
|
||||
RDCASSERT(err.empty() && spirv);
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
@@ -1031,7 +1036,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
vector<uint32_t> *spirv;
|
||||
|
||||
string err = GetSPIRVBlob(i == 0 ? eSPIRVVertex : eSPIRVFragment, sources, &spirv);
|
||||
compileSettings.stage = i == 0 ? SPIRVShaderStage::Vertex : SPIRVShaderStage::Fragment;
|
||||
string err = GetSPIRVBlob(compileSettings, sources, &spirv);
|
||||
RDCASSERT(err.empty() && spirv);
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
@@ -1054,7 +1060,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
vector<uint32_t> *spirv;
|
||||
|
||||
string err = GetSPIRVBlob(eSPIRVCompute, sources, &spirv);
|
||||
compileSettings.stage = SPIRVShaderStage::Compute;
|
||||
string err = GetSPIRVBlob(compileSettings, sources, &spirv);
|
||||
RDCASSERT(err.empty() && spirv);
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
@@ -1731,9 +1738,12 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
};
|
||||
|
||||
SPIRVShaderStage shaderStages[] = {
|
||||
eSPIRVVertex, eSPIRVFragment, eSPIRVFragment, eSPIRVVertex, eSPIRVGeometry, eSPIRVFragment,
|
||||
eSPIRVCompute, eSPIRVCompute, eSPIRVCompute, eSPIRVFragment, eSPIRVFragment, eSPIRVFragment,
|
||||
eSPIRVCompute, eSPIRVCompute, eSPIRVCompute, eSPIRVGeometry, eSPIRVFragment,
|
||||
SPIRVShaderStage::Vertex, SPIRVShaderStage::Fragment, SPIRVShaderStage::Fragment,
|
||||
SPIRVShaderStage::Vertex, SPIRVShaderStage::Geometry, SPIRVShaderStage::Fragment,
|
||||
SPIRVShaderStage::Compute, SPIRVShaderStage::Compute, SPIRVShaderStage::Compute,
|
||||
SPIRVShaderStage::Fragment, SPIRVShaderStage::Fragment, SPIRVShaderStage::Fragment,
|
||||
SPIRVShaderStage::Compute, SPIRVShaderStage::Compute, SPIRVShaderStage::Compute,
|
||||
SPIRVShaderStage::Geometry, SPIRVShaderStage::Fragment,
|
||||
};
|
||||
|
||||
enum shaderIdx
|
||||
@@ -1770,7 +1780,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
GenerateGLSLShader(sources, eShaderVulkan, "", GetEmbeddedResource(glsl_fixedcol_frag), 430,
|
||||
false);
|
||||
|
||||
string err = GetSPIRVBlob(eSPIRVFragment, sources, &m_FixedColSPIRV);
|
||||
compileSettings.stage = SPIRVShaderStage::Fragment;
|
||||
string err = GetSPIRVBlob(compileSettings, sources, &m_FixedColSPIRV);
|
||||
RDCASSERT(err.empty() && m_FixedColSPIRV);
|
||||
}
|
||||
|
||||
@@ -1786,7 +1797,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
GenerateGLSLShader(sources, eShaderVulkan, defines, shaderSources[i], 430, i != QUADWRITEFS);
|
||||
|
||||
string err = GetSPIRVBlob(shaderStages[i], sources, &shaderSPIRV[i]);
|
||||
compileSettings.stage = shaderStages[i];
|
||||
string err = GetSPIRVBlob(compileSettings, sources, &shaderSPIRV[i]);
|
||||
RDCASSERT(err.empty() && shaderSPIRV[i]);
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
@@ -1925,7 +1937,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
GenerateGLSLShader(sources, eShaderVulkan, defines, shaderSources[HISTOGRAMCS], 430);
|
||||
|
||||
err = GetSPIRVBlob(eSPIRVCompute, sources, &blob);
|
||||
compileSettings.stage = SPIRVShaderStage::Compute;
|
||||
err = GetSPIRVBlob(compileSettings, sources, &blob);
|
||||
RDCASSERT(err.empty() && blob);
|
||||
|
||||
modinfo.codeSize = blob->size() * sizeof(uint32_t);
|
||||
@@ -1936,7 +1949,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
GenerateGLSLShader(sources, eShaderVulkan, defines, shaderSources[MINMAXTILECS], 430);
|
||||
|
||||
err = GetSPIRVBlob(eSPIRVCompute, sources, &blob);
|
||||
err = GetSPIRVBlob(compileSettings, sources, &blob);
|
||||
RDCASSERT(err.empty() && blob);
|
||||
|
||||
modinfo.codeSize = blob->size() * sizeof(uint32_t);
|
||||
@@ -1949,7 +1962,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
{
|
||||
GenerateGLSLShader(sources, eShaderVulkan, defines, shaderSources[MINMAXRESULTCS], 430);
|
||||
|
||||
err = GetSPIRVBlob(eSPIRVCompute, sources, &blob);
|
||||
err = GetSPIRVBlob(compileSettings, sources, &blob);
|
||||
RDCASSERT(err.empty() && blob);
|
||||
|
||||
modinfo.codeSize = blob->size() * sizeof(uint32_t);
|
||||
|
||||
@@ -98,6 +98,8 @@ struct VulkanPostVSData
|
||||
}
|
||||
};
|
||||
|
||||
struct SPIRVCompilationSettings;
|
||||
|
||||
class VulkanResourceManager;
|
||||
|
||||
class VulkanDebugManager
|
||||
@@ -344,8 +346,8 @@ private:
|
||||
bool m_ShaderCacheDirty, m_CacheShaders;
|
||||
map<uint32_t, vector<uint32_t> *> m_ShaderCache;
|
||||
|
||||
string GetSPIRVBlob(SPIRVShaderStage shadType, const std::vector<std::string> &sources,
|
||||
vector<uint32_t> **outBlob);
|
||||
string GetSPIRVBlob(const SPIRVCompilationSettings &settings,
|
||||
const std::vector<std::string> &sources, vector<uint32_t> **outBlob);
|
||||
|
||||
void CopyDepthTex2DMSToArray(VkImage destArray, VkImage srcMS, VkExtent3D extent, uint32_t layers,
|
||||
uint32_t samples, VkFormat fmt);
|
||||
|
||||
@@ -4979,16 +4979,16 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m
|
||||
void VulkanReplay::BuildCustomShader(string source, string entry, const uint32_t compileFlags,
|
||||
ShaderStage type, ResourceId *id, string *errors)
|
||||
{
|
||||
SPIRVShaderStage stage = eSPIRVInvalid;
|
||||
SPIRVShaderStage stage = SPIRVShaderStage::Invalid;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ShaderStage::Vertex: stage = eSPIRVVertex; break;
|
||||
case ShaderStage::Hull: stage = eSPIRVTessControl; break;
|
||||
case ShaderStage::Domain: stage = eSPIRVTessEvaluation; break;
|
||||
case ShaderStage::Geometry: stage = eSPIRVGeometry; break;
|
||||
case ShaderStage::Pixel: stage = eSPIRVFragment; break;
|
||||
case ShaderStage::Compute: stage = eSPIRVCompute; break;
|
||||
case ShaderStage::Vertex: stage = SPIRVShaderStage::Vertex; break;
|
||||
case ShaderStage::Hull: stage = SPIRVShaderStage::TessControl; break;
|
||||
case ShaderStage::Domain: stage = SPIRVShaderStage::TessEvaluation; break;
|
||||
case ShaderStage::Geometry: stage = SPIRVShaderStage::Geometry; break;
|
||||
case ShaderStage::Pixel: stage = SPIRVShaderStage::Fragment; break;
|
||||
case ShaderStage::Compute: stage = SPIRVShaderStage::Compute; break;
|
||||
default:
|
||||
RDCERR("Unexpected type in BuildShader!");
|
||||
*id = ResourceId();
|
||||
@@ -4999,7 +4999,9 @@ void VulkanReplay::BuildCustomShader(string source, string entry, const uint32_t
|
||||
sources.push_back(source);
|
||||
vector<uint32_t> spirv;
|
||||
|
||||
string output = CompileSPIRV(stage, sources, spirv);
|
||||
SPIRVCompilationSettings settings(SPIRVSourceLanguage::VulkanGLSL, stage);
|
||||
|
||||
string output = CompileSPIRV(settings, sources, spirv);
|
||||
|
||||
if(spirv.empty())
|
||||
{
|
||||
@@ -5091,16 +5093,16 @@ ResourceId VulkanReplay::ApplyCustomShader(ResourceId shader, ResourceId texid,
|
||||
void VulkanReplay::BuildTargetShader(string source, string entry, const uint32_t compileFlags,
|
||||
ShaderStage type, ResourceId *id, string *errors)
|
||||
{
|
||||
SPIRVShaderStage stage = eSPIRVInvalid;
|
||||
SPIRVShaderStage stage = SPIRVShaderStage::Invalid;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ShaderStage::Vertex: stage = eSPIRVVertex; break;
|
||||
case ShaderStage::Hull: stage = eSPIRVTessControl; break;
|
||||
case ShaderStage::Domain: stage = eSPIRVTessEvaluation; break;
|
||||
case ShaderStage::Geometry: stage = eSPIRVGeometry; break;
|
||||
case ShaderStage::Pixel: stage = eSPIRVFragment; break;
|
||||
case ShaderStage::Compute: stage = eSPIRVCompute; break;
|
||||
case ShaderStage::Vertex: stage = SPIRVShaderStage::Vertex; break;
|
||||
case ShaderStage::Hull: stage = SPIRVShaderStage::TessControl; break;
|
||||
case ShaderStage::Domain: stage = SPIRVShaderStage::TessEvaluation; break;
|
||||
case ShaderStage::Geometry: stage = SPIRVShaderStage::Geometry; break;
|
||||
case ShaderStage::Pixel: stage = SPIRVShaderStage::Fragment; break;
|
||||
case ShaderStage::Compute: stage = SPIRVShaderStage::Compute; break;
|
||||
default:
|
||||
RDCERR("Unexpected type in BuildShader!");
|
||||
*id = ResourceId();
|
||||
@@ -5111,7 +5113,9 @@ void VulkanReplay::BuildTargetShader(string source, string entry, const uint32_t
|
||||
sources.push_back(source);
|
||||
vector<uint32_t> spirv;
|
||||
|
||||
string output = CompileSPIRV(stage, sources, spirv);
|
||||
SPIRVCompilationSettings settings(SPIRVSourceLanguage::VulkanGLSL, stage);
|
||||
|
||||
string output = CompileSPIRV(settings, sources, spirv);
|
||||
|
||||
if(spirv.empty())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user