diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index b95e1c415..89e552b00 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -73,7 +73,10 @@ void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl) vector 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); diff --git a/renderdoc/driver/shaders/spirv/spirv_common.h b/renderdoc/driver/shaders/spirv/spirv_common.h index 1acfbe4e9..db46d0233 100644 --- a/renderdoc/driver/shaders/spirv/spirv_common.h +++ b/renderdoc/driver/shaders/spirv/spirv_common.h @@ -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 &sources, +string CompileSPIRV(const SPIRVCompilationSettings &settings, const vector &sources, vector &spirv); void ParseSPIRV(uint32_t *spirv, size_t spirvLength, SPVModule &module); diff --git a/renderdoc/driver/shaders/spirv/spirv_compile.cpp b/renderdoc/driver/shaders/spirv/spirv_compile.cpp index a85e1e2b2..5498e231b 100644 --- a/renderdoc/driver/shaders/spirv/spirv_compile.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_compile.cpp @@ -130,10 +130,10 @@ TBuiltInResource DefaultResources = { }, }; -string CompileSPIRV(SPIRVShaderStage shadType, const std::vector &sources, - vector &spirv) +string CompileSPIRV(const SPIRVCompilationSettings &settings, + const std::vector &sources, vector &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 &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) { diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp index 4d1c4c923..1ce4fb193 100644 --- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp @@ -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()); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 429e33237..3997ef25b 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -170,7 +170,7 @@ struct VulkanBlobShaderCallbacks byte *GetData(vector *blob) const { return (byte *)&(*blob)[0]; } } ShaderCacheCallbacks; -string VulkanDebugManager::GetSPIRVBlob(SPIRVShaderStage shadType, +string VulkanDebugManager::GetSPIRVBlob(const SPIRVCompilationSettings &settings, const std::vector &sources, vector **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 *spirv = new vector(); - 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 *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 *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 *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); diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index aade18bce..ff1a8d6c0 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -98,6 +98,8 @@ struct VulkanPostVSData } }; +struct SPIRVCompilationSettings; + class VulkanResourceManager; class VulkanDebugManager @@ -344,8 +346,8 @@ private: bool m_ShaderCacheDirty, m_CacheShaders; map *> m_ShaderCache; - string GetSPIRVBlob(SPIRVShaderStage shadType, const std::vector &sources, - vector **outBlob); + string GetSPIRVBlob(const SPIRVCompilationSettings &settings, + const std::vector &sources, vector **outBlob); void CopyDepthTex2DMSToArray(VkImage destArray, VkImage srcMS, VkExtent3D extent, uint32_t layers, uint32_t samples, VkFormat fmt); diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index d2a7aea4b..78f7ed448 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -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 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 spirv; - string output = CompileSPIRV(stage, sources, spirv); + SPIRVCompilationSettings settings(SPIRVSourceLanguage::VulkanGLSL, stage); + + string output = CompileSPIRV(settings, sources, spirv); if(spirv.empty()) {