diff --git a/renderdoc/data/glsl_shaders.cpp b/renderdoc/data/glsl_shaders.cpp index e3a134123..3830ed881 100644 --- a/renderdoc/data/glsl_shaders.cpp +++ b/renderdoc/data/glsl_shaders.cpp @@ -74,7 +74,7 @@ std::string GenerateGLSLShader(const std::string &shader, ShaderType type, int v std::string combined; - if(type == eShaderGLSLES) + if(type == ShaderType::GLSLES) { if(version == 100) combined = "#version 100\n"; // no es suffix @@ -95,11 +95,11 @@ std::string GenerateGLSLShader(const std::string &shader, ShaderType type, int v combined += include_ext; - if(type == eShaderGLSLES) + if(type == ShaderType::GLSLES) combined += "#define OPENGL 1\n" "#define OPENGL_ES 1\n"; - else if(type == eShaderGLSL) + else if(type == ShaderType::GLSL) combined += "#define OPENGL 1\n" "#define OPENGL_CORE 1\n"; @@ -110,9 +110,9 @@ std::string GenerateGLSLShader(const std::string &shader, ShaderType type, int v const char *c_src = combined.c_str(); glslang::EShClient client = - type == eShaderVulkan ? glslang::EShClientVulkan : glslang::EShClientOpenGL; + type == ShaderType::Vulkan ? glslang::EShClientVulkan : glslang::EShClientOpenGL; glslang::EShTargetClientVersion targetversion = - type == eShaderVulkan ? glslang::EShTargetVulkan_1_0 : glslang::EShTargetOpenGL_450; + type == ShaderType::Vulkan ? glslang::EShTargetVulkan_1_0 : glslang::EShTargetOpenGL_450; sh.setStrings(&c_src, 1); sh.setEnvInput(glslang::EShSourceGlsl, EShLangFragment, client, 100); @@ -123,9 +123,9 @@ std::string GenerateGLSLShader(const std::string &shader, ShaderType type, int v EShMessages flags = EShMsgOnlyPreprocessor; - if(type == eShaderVulkan) + if(type == ShaderType::Vulkan) flags = EShMessages(flags | EShMsgSpvRules | EShMsgVulkanRules); - else if(type == eShaderGLSPIRV) + else if(type == ShaderType::GLSPIRV) flags = EShMessages(flags | EShMsgSpvRules); std::string ret; @@ -174,7 +174,7 @@ void TestGLSLReflection(ShaderType testType, ReflectionMaker compile) REQUIRE(size >= min); \ CHECK(size == min); - if(testType == ShaderType::eShaderGLSL || testType == ShaderType::eShaderGLSPIRV) + if(testType == ShaderType::GLSL || testType == ShaderType::GLSPIRV) { // test GL only features @@ -196,7 +196,7 @@ void main() { ShaderBindpointMapping mapping; compile(ShaderStage::Fragment, source, "main", refl, mapping); - if(testType == ShaderType::eShaderGLSPIRV) + if(testType == ShaderType::GLSPIRV) CHECK(refl.encoding == ShaderEncoding::SPIRV); else CHECK(refl.encoding == ShaderEncoding::GLSL); @@ -299,7 +299,7 @@ void main() { } }; } - else if(testType == ShaderType::eShaderVulkan) + else if(testType == ShaderType::Vulkan) { // test Vulkan only features @@ -598,7 +598,7 @@ void main() { CHECK(refl.debugInfo.files[0].contents == source); - if(testType == eShaderGLSL) + if(testType == ShaderType::GLSL) { CHECK(refl.debugInfo.files[0].filename == "main.glsl"); } @@ -610,7 +610,7 @@ void main() { CHECK(refl.debugInfo.compileFlags.flags[0].name == "@cmdline"); - if(testType == eShaderGLSPIRV) + if(testType == ShaderType::GLSPIRV) CHECK(refl.debugInfo.compileFlags.flags[0].value == " --client opengl100 --target-env opengl --entry-point main"); else @@ -798,7 +798,7 @@ void main() { REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 1); { // blocks get different reflected names in SPIR-V - const rdcstr ubo_name = testType == ShaderType::eShaderGLSL ? "ubo_block" : "ubo_root"; + const rdcstr ubo_name = testType == ShaderType::GLSL ? "ubo_block" : "ubo_root"; CHECK(refl.constantBlocks[0].name == ubo_name); { @@ -810,16 +810,15 @@ void main() { CHECK(cblock.byteSize == 272); // GLSL reflects out a root structure - if(testType == ShaderType::eShaderGLSL) + if(testType == ShaderType::GLSL) { REQUIRE_ARRAY_SIZE(cblock.variables.size(), 1); CHECK(cblock.variables[0].name == ubo_name); } - const rdcarray &ubo_root = testType == ShaderType::eShaderGLSL - ? cblock.variables[0].type.members - : cblock.variables; + const rdcarray &ubo_root = + testType == ShaderType::GLSL ? cblock.variables[0].type.members : cblock.variables; REQUIRE_ARRAY_SIZE(ubo_root.size(), 7); { @@ -1101,7 +1100,7 @@ void main() { REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), 2); { // blocks get different reflected names in SPIR-V - const rdcstr ssbo_name = testType == ShaderType::eShaderGLSL ? "ssbo" : "ssbo_root"; + const rdcstr ssbo_name = testType == ShaderType::GLSL ? "ssbo" : "ssbo_root"; CHECK(refl.readWriteResources[0].name == ssbo_name); { @@ -1648,8 +1647,8 @@ void main() REQUIRE_ARRAY_SIZE(refl.inputSignature.size(), 2); { // blocks get different reflected names in SPIR-V - const rdcstr gl_in_name = testType == ShaderType::eShaderGLSL ? "gl_PerVertex" : "gl_in"; - const rdcstr block_name = testType == ShaderType::eShaderGLSL ? "block" : "In"; + const rdcstr gl_in_name = testType == ShaderType::GLSL ? "gl_PerVertex" : "gl_in"; + const rdcstr block_name = testType == ShaderType::GLSL ? "block" : "In"; CHECK(refl.inputSignature[0].varName == (gl_in_name + ".gl_Position")); { @@ -1680,7 +1679,7 @@ void main() REQUIRE_ARRAY_SIZE(refl.outputSignature.size(), 2); { - const rdcstr block_name = testType == ShaderType::eShaderGLSL ? "block" : "Out"; + const rdcstr block_name = testType == ShaderType::GLSL ? "block" : "Out"; CHECK(refl.outputSignature[0].varName.contains("gl_Position")); { @@ -1739,8 +1738,8 @@ void main() { compile(ShaderStage::Fragment, source, "main", refl, mapping); // GLSL 'expands' these arrays - size_t countRO = (testType == ShaderType::eShaderGLSL ? 7 : 1); - size_t arraySizeRO = (testType == ShaderType::eShaderGLSL ? 1 : 7); + size_t countRO = (testType == ShaderType::GLSL ? 7 : 1); + size_t arraySizeRO = (testType == ShaderType::GLSL ? 1 : 7); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -1749,7 +1748,7 @@ void main() { for(size_t i = 0; i < countRO; i++) { const rdcstr ro_name = - (testType == ShaderType::eShaderGLSL ? StringFormat::Fmt("tex2D[%zu]", i) : "tex2D"); + (testType == ShaderType::GLSL ? StringFormat::Fmt("tex2D[%zu]", i) : "tex2D"); CHECK(refl.readOnlyResources[i].name == ro_name); { @@ -1775,8 +1774,8 @@ void main() { } } - size_t countRW = (testType == ShaderType::eShaderGLSL ? 5 : 1); - size_t arraySizeRW = (testType == ShaderType::eShaderGLSL ? 1 : 5); + size_t countRW = (testType == ShaderType::GLSL ? 5 : 1); + size_t arraySizeRW = (testType == ShaderType::GLSL ? 1 : 5); REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), countRW); { @@ -1784,7 +1783,7 @@ void main() { { // blocks get different reflected names in SPIR-V const rdcstr ssbo_name = - (testType == ShaderType::eShaderGLSL ? StringFormat::Fmt("ssbo[%zu]", i) : "ssbo_root"); + (testType == ShaderType::GLSL ? StringFormat::Fmt("ssbo[%zu]", i) : "ssbo_root"); CHECK(refl.readWriteResources[i].name == ssbo_name); { @@ -1799,7 +1798,7 @@ void main() { // glslang with the fix const ShaderVariableType *varType = &res.variableType; - if(testType == ShaderType::eShaderGLSL && res.variableType.members.size() != 2) + if(testType == ShaderType::GLSL && res.variableType.members.size() != 2) { REQUIRE(varType->members.size() == 1); REQUIRE(varType->members[0].name == "a"); diff --git a/renderdoc/data/glsl_shaders.h b/renderdoc/data/glsl_shaders.h index de5df4298..b873b89a6 100644 --- a/renderdoc/data/glsl_shaders.h +++ b/renderdoc/data/glsl_shaders.h @@ -22,12 +22,12 @@ * THE SOFTWARE. ******************************************************************************/ -enum ShaderType +enum class ShaderType { - eShaderGLSL, - eShaderGLSLES, - eShaderVulkan, - eShaderGLSPIRV, + GLSL, + GLSLES, + Vulkan, + GLSPIRV, }; #include diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index b25dfa03f..bc22b036c 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -1191,6 +1191,10 @@ bool GLInitParams::IsSupportedVersion(uint64_t ver) if(ver == 0x1F) return true; + // 0x20 -> 0x21 - added multisampled texture initial data + if(ver == 0x20) + return true; + return false; } diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index cf5ba814e..9250f20a4 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -826,10 +826,19 @@ enum VendorCheckEnum }; extern bool VendorCheck[VendorCheck_Count]; +enum class ShaderType; + // fills out the extension supported array and the version-specific checks above void DoVendorChecks(GLPlatform &platform, GLWindowingData context); void GetContextVersion(bool &ctxGLES, int &ctxVersion); void FetchEnabledExtensions(); +void GetGLSLVersions(ShaderType &shaderType, int &glslVersion, int &glslBaseVer, int &glslCSVer); + +GLuint CreateShader(GLenum shaderType, const std::string &src); +GLuint CreateSPIRVShader(GLenum shaderType, const std::string &src); +GLuint CreateShaderProgram(const std::string &vs, const std::string &fs, const std::string &gs = ""); +GLuint CreateShaderProgram(GLuint vs, GLuint fs, GLuint gs = 0); +GLuint CreateCShaderProgram(const std::string &cs); // verify that we got a replay context that we can work with bool CheckReplayContext(); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index b8fdd4837..b26d7ed15 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -39,7 +39,25 @@ #define OPENGL 1 #include "data/glsl/glsl_ubos_cpp.h" -GLuint GLReplay::CreateShader(GLenum shaderType, const std::string &src) +void GetGLSLVersions(ShaderType &shaderType, int &glslVersion, int &glslBaseVer, int &glslCSVer) +{ + if(IsGLES) + { + shaderType = ShaderType::GLSLES; + glslVersion = glslBaseVer = glslCSVer = 310; + + if(GLCoreVersion >= 32) + glslVersion = glslBaseVer = glslCSVer = 320; + } + else + { + shaderType = ShaderType::GLSL; + glslVersion = glslBaseVer = 150; + glslCSVer = 420; + } +} + +GLuint CreateShader(GLenum shaderType, const std::string &src) { GLuint ret = GL.glCreateShader(shaderType); @@ -61,7 +79,7 @@ GLuint GLReplay::CreateShader(GLenum shaderType, const std::string &src) return ret; } -GLuint GLReplay::CreateSPIRVShader(GLenum shaderType, const std::string &src) +GLuint CreateSPIRVShader(GLenum shaderType, const std::string &src) { if(!HasExt[ARB_gl_spirv]) { @@ -101,13 +119,8 @@ GLuint GLReplay::CreateSPIRVShader(GLenum shaderType, const std::string &src) return ret; } -GLuint GLReplay::CreateCShaderProgram(const std::string &src) +GLuint CreateCShaderProgram(const std::string &src) { - if(m_pDriver == NULL) - return 0; - - MakeCurrentReplayContext(m_DebugCtx); - GLuint cs = CreateShader(eGL_COMPUTE_SHADER, src); if(cs == 0) return 0; @@ -134,7 +147,7 @@ GLuint GLReplay::CreateCShaderProgram(const std::string &src) return ret; } -GLuint GLReplay::CreateShaderProgram(GLuint vs, GLuint fs, GLuint gs) +GLuint CreateShaderProgram(GLuint vs, GLuint fs, GLuint gs) { GLuint ret = GL.glCreateProgram(); @@ -157,14 +170,9 @@ GLuint GLReplay::CreateShaderProgram(GLuint vs, GLuint fs, GLuint gs) return ret; } -GLuint GLReplay::CreateShaderProgram(const std::string &vsSrc, const std::string &fsSrc, - const std::string &gsSrc) +GLuint CreateShaderProgram(const std::string &vsSrc, const std::string &fsSrc, + const std::string &gsSrc) { - if(m_pDriver == NULL) - return 0; - - MakeCurrentReplayContext(m_DebugCtx); - GLuint vs = 0; GLuint fs = 0; GLuint gs = 0; @@ -366,21 +374,17 @@ void GLReplay::InitDebugData() std::string gs; std::string cs; + ShaderType shaderType; int glslVersion; int glslBaseVer; int glslCSVer; // compute shader - ShaderType shaderType; + + GetGLSLVersions(shaderType, glslVersion, glslBaseVer, glslCSVer); std::string texSampleDefines; if(IsGLES) { - glslVersion = glslBaseVer = glslCSVer = 310; - shaderType = eShaderGLSLES; - - if(GLCoreVersion >= 32) - glslVersion = glslBaseVer = glslCSVer = 320; - if(HasExt[OES_texture_cube_map_array] || HasExt[EXT_texture_cube_map_array] || GLCoreVersion >= 32) texSampleDefines += "#define TEXSAMPLE_CUBE_ARRAY 1\n"; @@ -399,10 +403,6 @@ void GLReplay::InitDebugData() } else { - glslVersion = glslBaseVer = 150; - glslCSVer = 420; - shaderType = eShaderGLSL; - if(HasExt[ARB_texture_cube_map_array]) texSampleDefines += "#define TEXSAMPLE_CUBE_ARRAY 1\n" @@ -432,7 +432,7 @@ void GLReplay::InitDebugData() { // SPIR-V shaders are always generated as desktop GL 430, for ease std::string source = - GenerateGLSLShader(GetEmbeddedResource(glsl_fixedcol_frag), eShaderGLSPIRV, 430); + GenerateGLSLShader(GetEmbeddedResource(glsl_fixedcol_frag), ShaderType::GLSPIRV, 430); DebugData.fixedcolFragShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, source); if(HasExt[ARB_gpu_shader5] && HasExt[ARB_shader_image_load_store]) @@ -445,8 +445,8 @@ void GLReplay::InitDebugData() defines += "#define dFdyFine dFdy\n\n"; } - source = - GenerateGLSLShader(GetEmbeddedResource(glsl_quadwrite_frag), eShaderGLSPIRV, 430, defines); + source = GenerateGLSLShader(GetEmbeddedResource(glsl_quadwrite_frag), ShaderType::GLSPIRV, + 430, defines); DebugData.quadoverdrawFragShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, source); } } @@ -871,65 +871,6 @@ void GLReplay::InitDebugData() eGL_DYNAMIC_READ); } - if(HasExt[ARB_compute_shader] && HasExt[ARB_shader_image_load_store] && - HasExt[ARB_texture_multisample]) - { - cs = GenerateGLSLShader(GetEmbeddedResource(glsl_ms2array_comp), shaderType, glslCSVer); - DebugData.MS2Array = CreateCShaderProgram(cs); - - // GLES doesn't have multisampled image load/store even with any extension - DebugData.Array2MS = 0; - if(!IsGLES) - { - cs = GenerateGLSLShader(GetEmbeddedResource(glsl_array2ms_comp), shaderType, glslCSVer); - DebugData.Array2MS = CreateCShaderProgram(cs); - } - } - else - { - DebugData.MS2Array = 0; - DebugData.Array2MS = 0; - RDCWARN( - "GL_ARB_compute_shader or ARB_shader_image_load_store or ARB_texture_multisample not " - "supported, disabling 2DMS save/load."); - m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium, - MessageSource::RuntimeWarning, - "GL_ARB_compute_shader or ARB_shader_image_load_store not " - "supported, disabling 2DMS save/load."); - } - - DebugData.DepthArray2MS = DebugData.DepthMS2Array = 0; - - if(HasExt[ARB_texture_multisample]) - { - vs = GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer); - - fs = GenerateGLSLShader(GetEmbeddedResource(glsl_depthms2arr_frag), shaderType, glslBaseVer); - DebugData.DepthMS2Array = CreateShaderProgram(vs, fs); - - GL.glUseProgram(DebugData.DepthMS2Array); - - GL.glUniform1i(GL.glGetUniformLocation(DebugData.DepthMS2Array, "srcDepthMS"), 0); - GL.glUniform1i(GL.glGetUniformLocation(DebugData.DepthMS2Array, "srcStencilMS"), 1); - - fs = GenerateGLSLShader(GetEmbeddedResource(glsl_deptharr2ms_frag), shaderType, glslBaseVer); - DebugData.DepthArray2MS = CreateShaderProgram(vs, fs); - - GL.glUseProgram(DebugData.DepthArray2MS); - - GL.glUniform1i(GL.glGetUniformLocation(DebugData.DepthArray2MS, "srcDepthArray"), 0); - GL.glUniform1i(GL.glGetUniformLocation(DebugData.DepthArray2MS, "srcStencilArray"), 1); - } - else - { - DebugData.MS2Array = 0; - DebugData.Array2MS = 0; - RDCWARN("GL_ARB_texture_multisample not supported, disabling 2DMS depth-stencil save/load."); - m_pDriver->AddDebugMessage( - MessageCategory::Portability, MessageSeverity::Medium, MessageSource::RuntimeWarning, - "GL_ARB_texture_multisample not supported, disabling 2DMS depth-stencil save/load."); - } - if(HasExt[ARB_compute_shader]) { cs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_comp), shaderType, glslCSVer); @@ -1256,16 +1197,6 @@ void GLReplay::DeleteDebugData() drv.glDeleteBuffers(1, &DebugData.pickVBBuf); drv.glDeleteBuffers(1, &DebugData.pickResultBuf); - if(DebugData.Array2MS) - drv.glDeleteProgram(DebugData.Array2MS); - if(DebugData.MS2Array) - drv.glDeleteProgram(DebugData.MS2Array); - - if(DebugData.DepthArray2MS) - drv.glDeleteProgram(DebugData.DepthArray2MS); - if(DebugData.DepthMS2Array) - drv.glDeleteProgram(DebugData.DepthMS2Array); - drv.glDeleteBuffers(1, &DebugData.minmaxTileResult); drv.glDeleteBuffers(1, &DebugData.minmaxResult); drv.glDeleteBuffers(1, &DebugData.histogramBuf); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index d2492f6b7..fb2f178de 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -712,6 +712,8 @@ void WrappedOpenGL::Initialise(GLInitParams ¶ms, uint64_t sectionVersion, m_SectionVersion = sectionVersion; m_GlobalInitParams = params; m_ReplayOptions = opts; + + m_ArrayMS.Create(); } void WrappedOpenGL::MarkReferencedWhileCapturing(GLResourceRecord *record, FrameRefType refType) @@ -925,6 +927,8 @@ WrappedOpenGL::~WrappedOpenGL() if(m_IndirectBuffer) GL.glDeleteBuffers(1, &m_IndirectBuffer); + m_ArrayMS.Destroy(); + SAFE_DELETE(m_FrameReader); GetResourceManager()->ClearReferencedResources(); @@ -1025,6 +1029,7 @@ void WrappedOpenGL::DeleteContext(void *contextHandle) if(ctxdata.built && ctxdata.ready) { + ctxdata.ArrayMS.Destroy(); if(ctxdata.Program) GL.glDeleteProgram(ctxdata.Program); if(ctxdata.ArrayBuffer) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index b774e7198..ad3e64470 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -60,7 +60,7 @@ struct GLInitParams rdcstr renderer, version; // check if a frame capture section version is supported - static const uint64_t CurrentVersion = 0x20; + static const uint64_t CurrentVersion = 0x21; static bool IsSupportedVersion(uint64_t ver); }; @@ -128,6 +128,21 @@ private: GLReplay m_Replay; RDCDriver m_DriverType; + struct ArrayMSPrograms + { + void Create(); + void Destroy(); + + GLuint MS2Array = 0, Array2MS = 0; + GLuint DepthMS2Array = 0, DepthArray2MS = 0; + }; + + void CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat, + uint32_t selectedSlice); + void CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat); + uint64_t m_SectionVersion; GLInitParams m_GlobalInitParams; ReplayOptions m_ReplayOptions; @@ -231,6 +246,13 @@ private: std::vector m_CurEvents, m_Events; bool m_AddedDrawcall; + ArrayMSPrograms m_ArrayMS; + + const ArrayMSPrograms &GetArrayMS() + { + return IsReplayMode(m_State) ? m_ArrayMS : GetCtxData().ArrayMS; + } + bool HasNonDebugMarkers(); bool m_ReplayMarkers = true; @@ -316,6 +338,11 @@ private: void CleanupCapture(); void FreeCaptureData(); + void CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat, uint32_t selectedSlice); + void CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat); + struct ContextData { ContextData() @@ -387,6 +414,8 @@ private: GLuint GlyphTexture; GLuint DummyVAO; + ArrayMSPrograms ArrayMS; + float CharSize; float CharAspect; diff --git a/renderdoc/driver/gl/gl_initstate.cpp b/renderdoc/driver/gl/gl_initstate.cpp index 5f5b82c32..232ff82ac 100644 --- a/renderdoc/driver/gl/gl_initstate.cpp +++ b/renderdoc/driver/gl/gl_initstate.cpp @@ -885,6 +885,23 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc GL.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAG_FILTER, (GLint *)&state.magFilter); } + + // if this is an MSAA texture we now need to unpack to an array, ready to serialise + if(ms) + { + GLuint oldtex = 0; + GL.glGetIntegerv(eGL_TEXTURE_BINDING_2D_ARRAY, (GLint *)&oldtex); + + GLuint msaaTex = tex; + + m_Driver->CopyTex2DMSToArray(tex, msaaTex, details.width, details.height, details.depth, + details.samples, details.internalFormat); + + // destroy the MSAA texture, we don't need it anymore + GL.glDeleteTextures(1, &msaaTex); + + GL.glBindTexture(eGL_TEXTURE_2D_ARRAY, oldtex); + } } initContents.resource = GLResource(res.ContextShareGroup, eResTexture, tex); @@ -971,6 +988,9 @@ uint64_t GLResourceManager::GetSize_InitialState(ResourceId resid, const GLIniti if(TextureState.type == eGL_TEXTURE_CUBE_MAP_ARRAY || TextureState.type == eGL_TEXTURE_2D_ARRAY) d = TextureState.depth; + if(TextureState.samples > 1) + d = RDCMAX(1U, TextureState.depth) * TextureState.samples; + if(TextureState.type == eGL_TEXTURE_1D_ARRAY) h = TextureState.height; @@ -1430,28 +1450,14 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i GLuint tex = 0; GLuint prevtex = 0; + GLuint prevArrayTex = 0; + GLuint msaaTex = 0; // push the texture binding if(!IsStructuredExporting(m_State) && !ser.IsErrored()) + { GL.glGetIntegerv(TextureBinding(TextureState.type), (GLint *)&prevtex); - - // create texture of identical format/size as the live resource to store initial contents - if(IsReplayingAndReading() && !ser.IsErrored()) - { - GL.glGenTextures(1, &tex); - GL.glBindTexture(TextureState.type, tex); - - m_Driver->CreateTextureImage(tex, TextureState.internalformat, details.internalFormatHint, - TextureState.type, TextureState.dim, TextureState.width, - TextureState.height, TextureState.depth, - TextureState.samples, TextureState.mips); - } - else if(ser.IsWriting()) - { - // on writing, bind the prepared texture with initial contents to grab - tex = initial->resource.name; - - GL.glBindTexture(TextureState.type, tex); + GL.glGetIntegerv(eGL_TEXTURE_BINDING_2D_ARRAY, (GLint *)&prevArrayTex); } // multisample textures have no mips @@ -1459,11 +1465,78 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i TextureState.type == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY) TextureState.mips = 1; + bool hasInitialData = true; + if(TextureState.samples > 1) { - GLNOTIMP("Not implemented - initial states of multisampled textures"); + // multisampled initial data was added in 0x21, before then, multisampled textures had no + // initial data. + hasInitialData = ser.VersionAtLeast(0x21); } - else + + uint32_t copySlices = RDCMAX(1U, TextureState.depth); + uint32_t texDim = TextureState.dim; + + // create texture of identical format/size as the live resource to store initial contents + if(IsReplayingAndReading() && !ser.IsErrored()) + { + GL.glGenTextures(1, &tex); + GL.glBindTexture(TextureState.type, tex); + + // create MSAA texture we'll use for applying + m_Driver->CreateTextureImage(tex, TextureState.internalformat, details.internalFormatHint, + TextureState.type, TextureState.dim, TextureState.width, + TextureState.height, TextureState.depth, + TextureState.samples, TextureState.mips); + + // create intermediary array for serialising + if(TextureState.samples > 1) + { + msaaTex = tex; + + GL.glGenTextures(1, &tex); + GL.glBindTexture(eGL_TEXTURE_2D_ARRAY, tex); + + copySlices = RDCMAX(1U, TextureState.depth) * TextureState.samples; + texDim = 3; + + GL.glTextureParameteriEXT(tex, eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); + GL.glTextureParameteriEXT(tex, eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST); + GL.glTextureParameteriEXT(tex, eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST); + GL.glTextureParameteriEXT(tex, eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_WRAP_S, + eGL_CLAMP_TO_EDGE); + GL.glTextureParameteriEXT(tex, eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_WRAP_T, + eGL_CLAMP_TO_EDGE); + + // must use immutable tex storage here, for MSAA<->Array copies + GL.glTextureStorage3DEXT(tex, eGL_TEXTURE_2D_ARRAY, 1, TextureState.internalformat, + TextureState.width, TextureState.height, copySlices); + + // read back from the array we prepared + targets[0] = eGL_TEXTURE_2D_ARRAY; + } + } + else if(ser.IsWriting()) + { + // on writing, bind the prepared texture with initial contents to grab + tex = initial->resource.name; + + // if this is an MSAA texture, we prepared an array to serialise + if(TextureState.samples > 1) + { + GL.glBindTexture(eGL_TEXTURE_2D_ARRAY, tex); + + copySlices = RDCMAX(1U, TextureState.depth) * TextureState.samples; + + targets[0] = eGL_TEXTURE_2D_ARRAY; + } + else + { + GL.glBindTexture(TextureState.type, tex); + } + } + + if(hasInitialData) { GLenum fmt = eGL_NONE; GLenum type = eGL_NONE; @@ -1480,8 +1553,8 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i { fmt = GetBaseFormat(TextureState.internalformat); type = GetDataType(TextureState.internalformat); - size = (uint32_t)GetByteSize(TextureState.width, TextureState.height, - TextureState.depth, fmt, type); + size = (uint32_t)GetByteSize(TextureState.width, TextureState.height, copySlices, fmt, + type); } // on read and write, we allocate a single buffer big enough for all mips and re-use it @@ -1495,11 +1568,10 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i uint32_t h = RDCMAX(TextureState.height >> i, 1U); uint32_t d = RDCMAX(TextureState.depth >> i, 1U); - if(TextureState.type == eGL_TEXTURE_CUBE_MAP_ARRAY || - TextureState.type == eGL_TEXTURE_2D_ARRAY) - d = TextureState.depth; + if(targets[0] == eGL_TEXTURE_CUBE_MAP_ARRAY || targets[0] == eGL_TEXTURE_2D_ARRAY) + d = copySlices; - if(TextureState.type == eGL_TEXTURE_1D_ARRAY) + if(targets[0] == eGL_TEXTURE_1D_ARRAY) h = TextureState.height; // calculate the actual byte size of this mip @@ -1545,27 +1617,27 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i memcpy(details.compressedData[i].data() + startOffs, scratchBuf, size); } - if(TextureState.dim == 1) + if(texDim == 1) GL.glCompressedTextureSubImage1DEXT(tex, targets[trg], i, 0, w, TextureState.internalformat, (GLsizei)size, scratchBuf); - else if(TextureState.dim == 2) + else if(texDim == 2) GL.glCompressedTextureSubImage2DEXT(tex, targets[trg], i, 0, 0, w, h, TextureState.internalformat, (GLsizei)size, scratchBuf); - else if(TextureState.dim == 3) + else if(texDim == 3) GL.glCompressedTextureSubImage3DEXT(tex, targets[trg], i, 0, 0, 0, w, h, d, TextureState.internalformat, (GLsizei)size, scratchBuf); } else { - if(TextureState.dim == 1) + if(texDim == 1) GL.glTextureSubImage1DEXT(tex, targets[trg], i, 0, w, fmt, type, scratchBuf); - else if(TextureState.dim == 2) + else if(texDim == 2) GL.glTextureSubImage2DEXT(tex, targets[trg], i, 0, 0, w, h, fmt, type, scratchBuf); - else if(TextureState.dim == 3) + else if(texDim == 3) GL.glTextureSubImage3DEXT(tex, targets[trg], i, 0, 0, 0, w, h, d, fmt, type, scratchBuf); } @@ -1579,7 +1651,22 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId i // restore the previous texture binding if(!IsStructuredExporting(m_State) && !ser.IsErrored()) + { GL.glBindTexture(TextureState.type, prevtex); + GL.glBindTexture(eGL_TEXTURE_2D_ARRAY, prevArrayTex); + } + + // the array texture has been serialised. If we're reading, copy back into the MSAA texture + // and destroy the temp array texture + if(IsReplayingAndReading() && TextureState.samples > 1) + { + m_Driver->CopyArrayToTex2DMS(msaaTex, tex, TextureState.width, TextureState.height, + TextureState.depth, TextureState.samples, + TextureState.internalformat, ~0U); + + GL.glDeleteTextures(1, &tex); + tex = msaaTex; + } initContents.resource = TextureRes(m_Driver->GetCtx(), tex); } diff --git a/renderdoc/driver/gl/gl_msaa_array_conv.cpp b/renderdoc/driver/gl/gl_msaa_array_conv.cpp index 9eeb3ff19..7b9482460 100644 --- a/renderdoc/driver/gl/gl_msaa_array_conv.cpp +++ b/renderdoc/driver/gl/gl_msaa_array_conv.cpp @@ -22,21 +22,98 @@ * THE SOFTWARE. ******************************************************************************/ +#include "data/glsl_shaders.h" #include "maths/matrix.h" #include "gl_driver.h" #define OPENGL 1 #include "data/glsl/glsl_ubos_cpp.h" -void GLReplay::CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat) +void WrappedOpenGL::ArrayMSPrograms::Create() { - WrappedOpenGL &drv = *m_pDriver; + std::string cs, vs, fs; + + ShaderType shaderType; + int glslVersion; + int glslBaseVer; + int glslCSVer; // compute shader + + GetGLSLVersions(shaderType, glslVersion, glslBaseVer, glslCSVer); + + if(HasExt[ARB_compute_shader] && HasExt[ARB_shader_image_load_store] && + HasExt[ARB_texture_multisample]) + { + cs = GenerateGLSLShader(GetEmbeddedResource(glsl_ms2array_comp), shaderType, glslCSVer); + MS2Array = CreateCShaderProgram(cs); + + // GLES doesn't have multisampled image load/store even with any extension + Array2MS = 0; + if(!IsGLES) + { + cs = GenerateGLSLShader(GetEmbeddedResource(glsl_array2ms_comp), shaderType, glslCSVer); + Array2MS = CreateCShaderProgram(cs); + } + } + else + { + MS2Array = 0; + Array2MS = 0; + RDCWARN( + "GL_ARB_compute_shader or ARB_shader_image_load_store or ARB_texture_multisample not " + "supported, disabling 2DMS save/load."); + } + + DepthArray2MS = DepthMS2Array = 0; + + if(HasExt[ARB_texture_multisample]) + { + vs = GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer); + + fs = GenerateGLSLShader(GetEmbeddedResource(glsl_depthms2arr_frag), shaderType, glslBaseVer); + DepthMS2Array = CreateShaderProgram(vs, fs); + + GL.glUseProgram(DepthMS2Array); + + GL.glUniform1i(GL.glGetUniformLocation(DepthMS2Array, "srcDepthMS"), 0); + GL.glUniform1i(GL.glGetUniformLocation(DepthMS2Array, "srcStencilMS"), 1); + + fs = GenerateGLSLShader(GetEmbeddedResource(glsl_deptharr2ms_frag), shaderType, glslBaseVer); + DepthArray2MS = CreateShaderProgram(vs, fs); + + GL.glUseProgram(DepthArray2MS); + + GL.glUniform1i(GL.glGetUniformLocation(DepthArray2MS, "srcDepthArray"), 0); + GL.glUniform1i(GL.glGetUniformLocation(DepthArray2MS, "srcStencilArray"), 1); + } + else + { + MS2Array = 0; + Array2MS = 0; + RDCWARN("GL_ARB_texture_multisample not supported, disabling 2DMS depth-stencil save/load."); + } +} + +void WrappedOpenGL::ArrayMSPrograms::Destroy() +{ + if(MS2Array) + GL.glDeleteProgram(MS2Array); + if(Array2MS) + GL.glDeleteProgram(Array2MS); + if(DepthMS2Array) + GL.glDeleteProgram(DepthMS2Array); + if(DepthArray2MS) + GL.glDeleteProgram(DepthArray2MS); +} + +void WrappedOpenGL::CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat) +{ + const ArrayMSPrograms &arrms = GetArrayMS(); // create temporary texture array, which we'll initialise to be the width/height in same format, // with the same number of array slices as multi samples. - drv.glGenTextures(1, &destArray); - drv.glBindTexture(eGL_TEXTURE_2D_ARRAY, destArray); + GL.glGenTextures(1, &destArray); + GL.glBindTexture(eGL_TEXTURE_2D_ARRAY, destArray); bool failed = false; @@ -61,20 +138,25 @@ void GLReplay::CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, failed = true; } + if(!arrms.MS2Array || (IsDepthStencilFormat(intFormat) && !arrms.DepthMS2Array)) + { + failed = true; + } + if(failed) { // create using the non-storage API which is always available, so the texture is at least valid // (but with undefined/empty contents). - drv.glTextureImage3DEXT(destArray, eGL_TEXTURE_2D_ARRAY, 0, intFormat, width, height, - arraySize * samples, 0, GetBaseFormat(intFormat), - GetDataType(intFormat), NULL); - drv.glTexParameteri(eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); + GL.glTextureImage3DEXT(destArray, eGL_TEXTURE_2D_ARRAY, 0, intFormat, width, height, + arraySize * samples, 0, GetBaseFormat(intFormat), GetDataType(intFormat), + NULL); + GL.glTexParameteri(eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); return; } // initialise the texture using texture storage, as required for texture views. - drv.glTextureStorage3DEXT(destArray, eGL_TEXTURE_2D_ARRAY, 1, intFormat, width, height, - arraySize * samples); + GL.glTextureStorage3DEXT(destArray, eGL_TEXTURE_2D_ARRAY, 1, intFormat, width, height, + arraySize * samples); if(IsDepthStencilFormat(intFormat)) { @@ -85,11 +167,11 @@ void GLReplay::CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLMarkerRegion renderoverlay("CopyTex2DMSToArray"); GLRenderState rs; - rs.FetchState(m_pDriver); + rs.FetchState(this); GLenum viewClass; - drv.glGetInternalformativ(eGL_TEXTURE_2D_ARRAY, intFormat, eGL_VIEW_COMPATIBILITY_CLASS, - sizeof(GLenum), (GLint *)&viewClass); + GL.glGetInternalformativ(eGL_TEXTURE_2D_ARRAY, intFormat, eGL_VIEW_COMPATIBILITY_CLASS, + sizeof(GLenum), (GLint *)&viewClass); GLenum fmt = eGL_R32UI; if(viewClass == eGL_VIEW_CLASS_8_BITS) @@ -100,55 +182,52 @@ void GLReplay::CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, fmt = eGL_RGB8UI; else if(viewClass == eGL_VIEW_CLASS_32_BITS) fmt = eGL_RGBA8UI; - else if(viewClass == eGL_VIEW_CLASS_48_BITS) - fmt = eGL_RGB16UI; else if(viewClass == eGL_VIEW_CLASS_64_BITS) fmt = eGL_RG32UI; - else if(viewClass == eGL_VIEW_CLASS_96_BITS) - fmt = eGL_RGB32UI; else if(viewClass == eGL_VIEW_CLASS_128_BITS) fmt = eGL_RGBA32UI; + else + return; GLuint texs[2]; - drv.glGenTextures(2, texs); - drv.glTextureView(texs[0], eGL_TEXTURE_2D_ARRAY, destArray, fmt, 0, 1, 0, arraySize * samples); - drv.glTextureView(texs[1], eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, srcMS, fmt, 0, 1, 0, arraySize); + GL.glGenTextures(2, texs); + GL.glTextureView(texs[0], eGL_TEXTURE_2D_ARRAY, destArray, fmt, 0, 1, 0, arraySize * samples); + GL.glTextureView(texs[1], eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, srcMS, fmt, 0, 1, 0, arraySize); - drv.glBindImageTexture(2, texs[0], 0, GL_TRUE, 0, eGL_WRITE_ONLY, fmt); - drv.glActiveTexture(eGL_TEXTURE0); - drv.glBindTexture(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, texs[1]); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_BASE_LEVEL, 0); - drv.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); + GL.glBindImageTexture(2, texs[0], 0, GL_TRUE, 0, eGL_WRITE_ONLY, fmt); + GL.glActiveTexture(eGL_TEXTURE0); + GL.glBindTexture(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, texs[1]); + GL.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_BASE_LEVEL, 0); + GL.glTexParameteri(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); - drv.glUseProgram(DebugData.MS2Array); + GL.glUseProgram(arrms.MS2Array); - GLint loc = drv.glGetUniformLocation(DebugData.MS2Array, "mscopy"); + GLint loc = GL.glGetUniformLocation(arrms.MS2Array, "mscopy"); if(loc >= 0) { - drv.glProgramUniform4i(DebugData.MS2Array, loc, samples, 0, 0, 0); + GL.glProgramUniform4i(arrms.MS2Array, loc, samples, 0, 0, 0); - drv.glDispatchCompute((GLuint)width, (GLuint)height, GLuint(arraySize * samples)); + GL.glDispatchCompute((GLuint)width, (GLuint)height, GLuint(arraySize * samples)); } - drv.glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + GL.glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - drv.glDeleteTextures(2, texs); + GL.glDeleteTextures(2, texs); - rs.ApplyState(m_pDriver); + rs.ApplyState(this); } -void GLReplay::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat) +void WrappedOpenGL::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, + GLint height, GLint arraySize, GLint samples, + GLenum intFormat) { GLMarkerRegion renderoverlay("CopyDepthTex2DMSToArray"); - WrappedOpenGL &drv = *m_pDriver; + WrappedOpenGL &drv = *this; + + const ArrayMSPrograms &arrms = GetArrayMS(); GLRenderState rs; - rs.FetchState(m_pDriver); + rs.FetchState(this); GLuint texs[3]; drv.glGenTextures(3, texs); @@ -164,7 +243,7 @@ void GLReplay::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint wi drv.glBindFramebuffer(eGL_FRAMEBUFFER, fbo); drv.glDrawBuffers(0, NULL); - drv.glUseProgram(DebugData.DepthMS2Array); + drv.glUseProgram(arrms.DepthMS2Array); drv.glViewport(0, 0, width, height); drv.glDisable(eGL_CULL_FACE); @@ -229,7 +308,7 @@ void GLReplay::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint wi eGL_STENCIL_INDEX); } - GLint loc = drv.glGetUniformLocation(DebugData.DepthMS2Array, "mscopy"); + GLint loc = drv.glGetUniformLocation(arrms.DepthMS2Array, "mscopy"); if(loc >= 0) { for(GLint i = 0; i < arraySize * samples; i++) @@ -242,7 +321,7 @@ void GLReplay::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint wi drv.glStencilFunc(eGL_ALWAYS, int(s), 0xff); - drv.glProgramUniform4i(DebugData.DepthMS2Array, loc, samples, i % samples, i / samples, + drv.glProgramUniform4i(arrms.DepthMS2Array, loc, samples, i % samples, i / samples, currentStencil); drv.glDrawArrays(eGL_TRIANGLE_STRIP, 0, 4); @@ -253,14 +332,16 @@ void GLReplay::CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint wi drv.glDeleteFramebuffers(1, &fbo); drv.glDeleteTextures(3, texs); - rs.ApplyState(m_pDriver); + rs.ApplyState(this); } -void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat, - uint32_t selectedSlice) +void WrappedOpenGL::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, + GLint arraySize, GLint samples, GLenum intFormat, + uint32_t selectedSlice) { - WrappedOpenGL &drv = *m_pDriver; + WrappedOpenGL &drv = *this; + + const ArrayMSPrograms &arrms = GetArrayMS(); if(!HasExt[ARB_compute_shader]) { @@ -283,6 +364,11 @@ void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, G return; } + if(!arrms.Array2MS || (IsDepthStencilFormat(intFormat) && !arrms.DepthArray2MS)) + { + return; + } + if(IsDepthStencilFormat(intFormat)) { CopyDepthArrayToTex2DMS(destMS, srcArray, width, height, arraySize, samples, intFormat, @@ -295,7 +381,7 @@ void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, G bool singleSliceMode = (selectedSlice != ~0U); GLRenderState rs; - rs.FetchState(m_pDriver); + rs.FetchState(this); GLenum viewClass; drv.glGetInternalformativ(eGL_TEXTURE_2D_ARRAY, intFormat, eGL_VIEW_COMPATIBILITY_CLASS, @@ -310,14 +396,12 @@ void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, G fmt = eGL_RGB8UI; else if(viewClass == eGL_VIEW_CLASS_32_BITS) fmt = eGL_RGBA8UI; - else if(viewClass == eGL_VIEW_CLASS_48_BITS) - fmt = eGL_RGB16UI; else if(viewClass == eGL_VIEW_CLASS_64_BITS) fmt = eGL_RG32UI; - else if(viewClass == eGL_VIEW_CLASS_96_BITS) - fmt = eGL_RGB32UI; else if(viewClass == eGL_VIEW_CLASS_128_BITS) fmt = eGL_RGBA32UI; + else + return; GLuint texs[2]; drv.glGenTextures(2, texs); @@ -334,22 +418,22 @@ void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, G drv.glTexParameteri(eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_BASE_LEVEL, 0); drv.glTexParameteri(eGL_TEXTURE_2D_ARRAY, eGL_TEXTURE_MAX_LEVEL, 0); - drv.glUseProgram(DebugData.Array2MS); + drv.glUseProgram(arrms.Array2MS); - GLint loc = drv.glGetUniformLocation(DebugData.Array2MS, "mscopy"); + GLint loc = drv.glGetUniformLocation(arrms.Array2MS, "mscopy"); if(loc >= 0) { if(singleSliceMode) { GLint sampleOffset = (selectedSlice % samples); GLint sliceOffset = (selectedSlice / samples); - drv.glProgramUniform4i(DebugData.Array2MS, loc, samples, sampleOffset, sliceOffset, 0); + drv.glProgramUniform4i(arrms.Array2MS, loc, samples, sampleOffset, sliceOffset, 0); drv.glDispatchCompute((GLuint)width, (GLuint)height, 1); } else { - drv.glProgramUniform4i(DebugData.Array2MS, loc, samples, 0, 0, 0); + drv.glProgramUniform4i(arrms.Array2MS, loc, samples, 0, 0, 0); drv.glDispatchCompute((GLuint)width, (GLuint)height, GLuint(arraySize * samples)); } @@ -358,21 +442,23 @@ void GLReplay::CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, G drv.glDeleteTextures(2, texs); - rs.ApplyState(m_pDriver); + rs.ApplyState(this); } -void GLReplay::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat, - uint32_t selectedSlice) +void WrappedOpenGL::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, + GLint height, GLint arraySize, GLint samples, + GLenum intFormat, uint32_t selectedSlice) { GLMarkerRegion renderoverlay("CopyDepthArrayToTex2DMS"); bool singleSliceMode = (selectedSlice != ~0U); - WrappedOpenGL &drv = *m_pDriver; + WrappedOpenGL &drv = *this; + + const ArrayMSPrograms &arrms = GetArrayMS(); GLRenderState rs; - rs.FetchState(m_pDriver); + rs.FetchState(this); GLuint texs[3]; drv.glGenTextures(3, texs); @@ -387,7 +473,7 @@ void GLReplay::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint wid drv.glBindFramebuffer(eGL_FRAMEBUFFER, fbo); drv.glDrawBuffers(0, NULL); - drv.glUseProgram(DebugData.DepthArray2MS); + drv.glUseProgram(arrms.DepthArray2MS); drv.glViewport(0, 0, width, height); drv.glDisable(eGL_CULL_FACE); @@ -452,7 +538,7 @@ void GLReplay::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint wid drv.glTexParameteri(eGL_TEXTURE_2D_ARRAY, eGL_DEPTH_STENCIL_TEXTURE_MODE, eGL_STENCIL_INDEX); } - GLint loc = drv.glGetUniformLocation(DebugData.DepthArray2MS, "mscopy"); + GLint loc = drv.glGetUniformLocation(arrms.DepthArray2MS, "mscopy"); if(loc >= 0) { for(GLint i = 0; i < arraySize; i++) @@ -471,7 +557,7 @@ void GLReplay::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint wid drv.glStencilFunc(eGL_ALWAYS, int(s), 0xff); - drv.glProgramUniform4i(DebugData.DepthArray2MS, loc, samples, 0, i, currentStencil); + drv.glProgramUniform4i(arrms.DepthArray2MS, loc, samples, 0, i, currentStencil); drv.glDrawArrays(eGL_TRIANGLE_STRIP, 0, 4); } @@ -484,5 +570,5 @@ void GLReplay::CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint wid drv.glDeleteFramebuffers(1, &fbo); drv.glDeleteTextures(3, texs); - rs.ApplyState(m_pDriver); + rs.ApplyState(this); } diff --git a/renderdoc/driver/gl/gl_overlay.cpp b/renderdoc/driver/gl/gl_overlay.cpp index d35210744..71b133550 100644 --- a/renderdoc/driver/gl/gl_overlay.cpp +++ b/renderdoc/driver/gl/gl_overlay.cpp @@ -262,7 +262,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeCast, FloatVec if(IsGLES) { - shaderType = eShaderGLSLES; + shaderType = ShaderType::GLSLES; // default to 100 just in case something is broken glslVer = 100; @@ -289,7 +289,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeCast, FloatVec { // Desktop GL is vastly better, it can link any program so we just default to 150 glslVer = 150; - shaderType = eShaderGLSL; + shaderType = ShaderType::GLSL; } // this is always compatible. @@ -300,7 +300,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeCast, FloatVec } // this is not supported on GLES - if(shaderType == eShaderGLSL) + if(shaderType == ShaderType::GLSL) { std::string defines = ""; diff --git a/renderdoc/driver/gl/gl_rendertext.cpp b/renderdoc/driver/gl/gl_rendertext.cpp index a6550be31..ce8d32ad3 100644 --- a/renderdoc/driver/gl/gl_rendertext.cpp +++ b/renderdoc/driver/gl/gl_rendertext.cpp @@ -173,13 +173,13 @@ void WrappedOpenGL::ContextData::CreateDebugData() if(IsGLES) { - shaderType = eShaderGLSLES; + shaderType = ShaderType::GLSLES; glslVersion = 100; fragDefines = "precision highp float;"; } else { - shaderType = eShaderGLSL; + shaderType = ShaderType::GLSL; glslVersion = 110; #if ENABLED(RDOC_APPLE) @@ -268,6 +268,8 @@ void WrappedOpenGL::ContextData::CreateDebugData() GL.glDeleteShader(vert); GL.glDeleteShader(frag); + + ArrayMS.Create(); } } diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 54786ebc3..5ec6c8342 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -2533,7 +2533,10 @@ void GLReplay::GetTextureData(ResourceId tex, const Subresource &sub, // copy multisampled texture to an array. This creates tempTex and returns it in that variable, // for us to own - CopyTex2DMSToArray(tempTex, texname, width, height, arraysize, samples, intFormat); + m_pDriver->CopyTex2DMSToArray(tempTex, texname, width, height, arraysize, samples, intFormat); + + // CopyTex2DMSToArray is unwrapped, so register the resource here now + m_pDriver->GetResourceManager()->RegisterResource(TextureRes(m_pDriver->GetCtx(), tempTex)); // rewrite the variables to temporary texture texType = eGL_TEXTURE_2D_ARRAY; @@ -3291,8 +3294,8 @@ void GLReplay::SetProxyTextureData(ResourceId texid, const Subresource &sub, byt height, 1, baseformat, datatype, data); // copy this slice into the 2D MSAA texture - CopyArrayToTex2DMS(tex, uploadTex, width, height, texdetails.depth, texdetails.samples, - texdetails.internalFormat, unpackedSlice); + m_pDriver->CopyArrayToTex2DMS(tex, uploadTex, width, height, texdetails.depth, + texdetails.samples, texdetails.internalFormat, unpackedSlice); // delete the temporary texture drv.glDeleteTextures(1, &uploadTex); diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index e81463bb1..ee0d671b2 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -249,16 +249,6 @@ private: bool CreateOverlayProgram(GLuint Program, GLuint Pipeline, GLuint fragShader, GLuint fragShaderSPIRV); - void CopyArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat, uint32_t selectedSlice); - void CopyTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat); - void CopyDepthArrayToTex2DMS(GLuint destMS, GLuint srcArray, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat, - uint32_t selectedSlice); - void CopyDepthTex2DMSToArray(GLuint &destArray, GLuint srcMS, GLint width, GLint height, - GLint arraySize, GLint samples, GLenum intFormat); - struct OutputWindow : public GLWindowingData { OutputWindow(const GLWindowingData &data) : GLWindowingData(data) {} @@ -347,9 +337,6 @@ private: uint32_t pickIBSize, pickVBSize; GLuint pickResultBuf; - GLuint MS2Array, Array2MS; - GLuint DepthMS2Array, DepthArray2MS; - GLuint checkerProg; GLuint fixedcolFragShader; @@ -419,13 +406,6 @@ private: void FillTimers(GLCounterContext &ctx, const DrawcallDescription &drawnode, const std::vector &counters); - GLuint CreateShader(GLenum shaderType, const std::string &src); - GLuint CreateSPIRVShader(GLenum shaderType, const std::string &src); - GLuint CreateShaderProgram(const std::string &vs, const std::string &fs, - const std::string &gs = ""); - GLuint CreateShaderProgram(GLuint vs, GLuint fs, GLuint gs = 0); - GLuint CreateCShaderProgram(const std::string &cs); - void InitOutputWindow(OutputWindow &outwin); void CreateOutputWindowBackbuffer(OutputWindow &outwin, bool depth); diff --git a/renderdoc/driver/gl/wrappers/gl_emulated.cpp b/renderdoc/driver/gl/wrappers/gl_emulated.cpp index e1c620585..ea10b5c7a 100644 --- a/renderdoc/driver/gl/wrappers/gl_emulated.cpp +++ b/renderdoc/driver/gl/wrappers/gl_emulated.cpp @@ -3602,7 +3602,7 @@ void MakeOnlineShaderReflection(ShaderStage stage, const std::string &source, TEST_CASE("Validate ARB_program_interface_query emulation", "[opengl][glslang][reflection]") { - TestGLSLReflection(ShaderType::eShaderGLSL, MakeOfflineShaderReflection); + TestGLSLReflection(ShaderType::GLSL, MakeOfflineShaderReflection); SECTION("shader stage references") { diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 003fbfc9d..bd816a1c7 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -2195,7 +2195,7 @@ void Reflector::AddSignatureParameter(const bool isInput, const ShaderStage stag TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]") { - ShaderType type = ShaderType::eShaderVulkan; + ShaderType type = ShaderType::Vulkan; auto compiler = [&type](ShaderStage stage, const std::string &source, const std::string &entryPoint, ShaderReflection &refl, ShaderBindpointMapping &mapping) { @@ -2203,7 +2203,7 @@ TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]") RenderDoc::Inst().RegisterShutdownFunction(&rdcspv::Shutdown); std::vector spirv; - rdcspv::CompilationSettings settings(type == ShaderType::eShaderVulkan + rdcspv::CompilationSettings settings(type == ShaderType::Vulkan ? rdcspv::InputLanguage::VulkanGLSL : rdcspv::InputLanguage::OpenGLGLSL, rdcspv::ShaderStage(stage)); @@ -2218,20 +2218,20 @@ TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]") spv.Parse(spirv); SPIRVPatchData patchData; - spv.MakeReflection(type == ShaderType::eShaderVulkan ? GraphicsAPI::Vulkan : GraphicsAPI::OpenGL, + spv.MakeReflection(type == ShaderType::Vulkan ? GraphicsAPI::Vulkan : GraphicsAPI::OpenGL, stage, entryPoint, {}, refl, mapping, patchData); }; // test both Vulkan and GL SPIR-V reflection SECTION("Vulkan GLSL reflection") { - type = ShaderType::eShaderVulkan; + type = ShaderType::Vulkan; TestGLSLReflection(type, compiler); }; SECTION("OpenGL GLSL reflection") { - type = ShaderType::eShaderGLSPIRV; + type = ShaderType::GLSPIRV; TestGLSLReflection(type, compiler); }; } diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 3462a4ddf..7820ac35a 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -2598,8 +2598,8 @@ void VulkanReplay::HistogramMinMax::Init(WrappedVulkan *driver, VkDescriptorPool defines += std::string("#define UINT_TEX ") + (f == 1 ? "1" : "0") + "\n"; defines += std::string("#define SINT_TEX ") + (f == 2 ? "1" : "0") + "\n"; - glsl = - GenerateGLSLShader(GetEmbeddedResource(glsl_histogram_comp), eShaderVulkan, 430, defines); + glsl = GenerateGLSLShader(GetEmbeddedResource(glsl_histogram_comp), ShaderType::Vulkan, 430, + defines); err = shaderCache->GetSPIRVBlob(compileSettings, glsl, histogram); if(!err.empty()) @@ -2609,8 +2609,8 @@ void VulkanReplay::HistogramMinMax::Init(WrappedVulkan *driver, VkDescriptorPool histogram = NULL; } - glsl = - GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxtile_comp), eShaderVulkan, 430, defines); + glsl = GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxtile_comp), ShaderType::Vulkan, 430, + defines); err = shaderCache->GetSPIRVBlob(compileSettings, glsl, minmaxtile); if(!err.empty()) @@ -2625,8 +2625,8 @@ void VulkanReplay::HistogramMinMax::Init(WrappedVulkan *driver, VkDescriptorPool if(t == 1) { - glsl = GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxresult_comp), eShaderVulkan, 430, - defines); + glsl = GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxresult_comp), ShaderType::Vulkan, + 430, defines); err = shaderCache->GetSPIRVBlob(compileSettings, glsl, minmaxresult); if(!err.empty()) diff --git a/renderdoc/driver/vulkan/vk_shader_cache.cpp b/renderdoc/driver/vulkan/vk_shader_cache.cpp index 71f6853a5..e949a56c1 100644 --- a/renderdoc/driver/vulkan/vk_shader_cache.cpp +++ b/renderdoc/driver/vulkan/vk_shader_cache.cpp @@ -194,8 +194,8 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver) else if(config.builtin == BuiltinShader::TexRemapSInt) defines += std::string("#define UINT_TEX 0\n#define SINT_TEX 1\n"); - src = - GenerateGLSLShader(GetDynamicEmbeddedResource(config.resource), eShaderVulkan, 430, defines); + src = GenerateGLSLShader(GetDynamicEmbeddedResource(config.resource), ShaderType::Vulkan, 430, + defines); compileSettings.stage = config.stage; std::string err = GetSPIRVBlob(compileSettings, src, m_BuiltinShaderBlobs[i]);