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:
baldurk
2017-07-05 15:56:55 +01:00
parent 7d5e047e66
commit c2b0c2d7d8
7 changed files with 130 additions and 58 deletions
@@ -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);
+29 -9
View File
@@ -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());
+28 -15
View File
@@ -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);
+4 -2
View File
@@ -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);
+20 -16
View File
@@ -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())
{