in renderdoc/driver/gl/gl_debug.cpp [340:1198]
void GLReplay::InitDebugData()
{
if(m_pDriver == NULL)
return;
// don't reflect any shaders or programs we make
m_pDriver->PushInternalShader();
m_HighlightCache.driver = m_pDriver->GetReplay();
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.0f);
{
WindowingData window = {WindowingSystem::Headless};
uint64_t id = MakeOutputWindow(window, true);
m_DebugCtx = NULL;
if(id == 0)
return;
m_DebugID = id;
m_DebugCtx = &m_OutputWindows[id];
MakeCurrentReplayContext(m_DebugCtx);
m_pDriver->RegisterDebugCallback();
}
WrappedOpenGL &drv = *m_pDriver;
DebugData.outWidth = 0.0f;
DebugData.outHeight = 0.0f;
rdcstr vs;
rdcstr fs;
rdcstr gs;
rdcstr cs;
ShaderType shaderType;
int glslVersion;
int glslBaseVer;
int glslCSVer; // compute shader
GetGLSLVersions(shaderType, glslVersion, glslBaseVer, glslCSVer);
rdcstr texSampleDefines;
if(IsGLES)
{
if(HasExt[OES_texture_cube_map_array] || HasExt[EXT_texture_cube_map_array] || GLCoreVersion >= 32)
texSampleDefines += "#define TEXSAMPLE_CUBE_ARRAY 1\n";
if(HasExt[OES_texture_cube_map_array])
texSampleDefines += "#extension GL_OES_texture_cube_map_array : require\n";
if(HasExt[EXT_texture_cube_map_array])
texSampleDefines += "#extension GL_EXT_texture_cube_map_array : require\n";
if(HasExt[EXT_texture_buffer])
texSampleDefines +=
"#define TEXSAMPLE_BUFFER 1\n"
"#extension GL_EXT_texture_buffer : require\n";
texSampleDefines += "#define HAS_BIT_CONVERSION 1\n";
}
else
{
if(HasExt[ARB_texture_cube_map_array])
texSampleDefines +=
"#define TEXSAMPLE_CUBE_ARRAY 1\n"
"#extension GL_ARB_texture_cube_map_array : require\n";
if(HasExt[ARB_texture_multisample])
texSampleDefines +=
"#define TEXSAMPLE_MULTISAMPLE 1\n"
"#extension GL_ARB_texture_multisample : require\n";
if(HasExt[ARB_gpu_shader5])
texSampleDefines +=
"#define HAS_BIT_CONVERSION 1\n"
"#extension GL_ARB_gpu_shader5 : require\n";
else if(HasExt[ARB_shader_bit_encoding])
texSampleDefines +=
"#define HAS_BIT_CONVERSION 1\n"
"#extension GL_ARB_shader_bit_encoding : require\n";
}
rdcstr vsDefines = "#define FORCE_IO_LOCATION 1";
if(!IsGLES)
{
vsDefines =
"#extension GL_ARB_separate_shader_objects : require\n"
"#extension GL_ARB_explicit_attrib_location : require\n" +
vsDefines;
}
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer, vsDefines);
// used to combine with custom shaders.
// this has to have explicit locations on the output even though we don't normally use that,
// because GL doesn't have a fallback to match by name, and custom shaders are expected to have an
// explicit location on the input
DebugData.texDisplayVertexShader = CreateShader(eGL_VERTEX_SHADER, vs);
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_fixedcol_frag), shaderType, glslBaseVer);
DebugData.fullScreenFixedColProg = CreateShaderProgram(vs, fs);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_depth_copy_frag), shaderType, glslBaseVer);
DebugData.fullScreenCopyDepth = CreateShaderProgram(vs, fs);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_depth_copyms_frag), shaderType, glslBaseVer);
DebugData.fullScreenCopyDepthMS = CreateShaderProgram(vs, fs);
DebugData.fixedcolFragShaderSPIRV = DebugData.quadoverdrawFragShaderSPIRV = 0;
// pre-compile SPIR-V shaders up front since this is more expensive
if(HasExt[ARB_gl_spirv])
{
// SPIR-V shaders are always generated as desktop GL 430, for ease
rdcstr source =
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])
{
rdcstr defines = "";
if(!HasExt[ARB_derivative_control])
{
defines += "#define dFdxFine dFdx\n\n";
defines += "#define dFdyFine dFdy\n\n";
}
source = GenerateGLSLShader(GetEmbeddedResource(glsl_quadwrite_frag), ShaderType::GLSPIRV,
430, defines);
DebugData.quadoverdrawFragShaderSPIRV = CreateSPIRVShader(eGL_FRAGMENT_SHADER, source);
}
}
for(int i = 0; i < 3; i++)
{
rdcstr defines = rdcstr("#define SHADER_BASETYPE ") + ToStr(i) + "\n";
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_texdisplay_frag), shaderType, glslBaseVer,
defines + texSampleDefines);
DebugData.texDisplayProg[i] = CreateShaderProgram(vs, fs);
BindUBO(DebugData.texDisplayProg[i], "TexDisplayUBOData", 0);
BindUBO(DebugData.texDisplayProg[i], "HeatmapData", 1);
ConfigureTexDisplayProgramBindings(DebugData.texDisplayProg[i]);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_texremap_frag), shaderType, glslBaseVer,
defines + texSampleDefines);
DebugData.texRemapProg[i] = CreateShaderProgram(vs, fs);
BindUBO(DebugData.texRemapProg[i], "TexDisplayUBOData", 0);
ConfigureTexDisplayProgramBindings(DebugData.texRemapProg[i]);
}
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.2f);
if(GLCoreVersion >= 43 && !IsGLES)
{
GLint numsl = 0;
drv.glGetIntegerv(eGL_NUM_SHADING_LANGUAGE_VERSIONS, &numsl);
for(GLint i = 0; i < numsl; i++)
{
const char *sl = (const char *)drv.glGetStringi(eGL_SHADING_LANGUAGE_VERSION, (GLuint)i);
CheckGLSLVersion(sl, glslVersion);
}
}
else
{
const char *sl = (const char *)drv.glGetString(eGL_SHADING_LANGUAGE_VERSION);
CheckGLSLVersion(sl, glslVersion);
}
DebugData.glslVersion = glslVersion;
RDCLOG("GLSL version %d", glslVersion);
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer);
DebugData.fixedcolFragShader = DebugData.quadoverdrawFragShader = 0;
DebugData.quadoverdrawResolveProg = 0;
if(IsGLES)
{
// quad overdraw not supported on GLES.
// 1.
// dFdx doesn't support uints - potentially workaroundable with float casts, but highly
// doubtful GLES compilers will do that properly without exploding.
// 2.
// quad overdraw write shader must be linked with user shaders in program, which requires
// matching ESSL version and features required for it aren't exposed as extensions to older
// versions but only in core versions.
}
else if(HasExt[ARB_shader_image_load_store] && HasExt[ARB_gpu_shader5])
{
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_quadresolve_frag), shaderType, glslBaseVer);
DebugData.quadoverdrawResolveProg = CreateShaderProgram(vs, fs);
GL.glUseProgram(DebugData.quadoverdrawResolveProg);
GL.glUniform1i(GL.glGetUniformLocation(DebugData.quadoverdrawResolveProg, "overdrawImage"), 0);
}
else
{
RDCWARN(
"GL_ARB_shader_image_load_store/GL_ARB_gpu_shader5 not supported, disabling quad overdraw "
"feature.");
m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium,
MessageSource::RuntimeWarning,
"GL_ARB_shader_image_load_store/GL_ARB_gpu_shader5 not supported, "
"disabling quad overdraw feature.");
}
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_checkerboard_frag), shaderType, glslBaseVer);
DebugData.checkerProg = CreateShaderProgram(vs, fs);
BindUBO(DebugData.checkerProg, "CheckerboardUBOData", 0);
for(size_t intIdx = 0; intIdx < 3; intIdx++)
{
for(size_t numViews = 0; numViews < ARRAY_COUNT(DebugData.discardProg[intIdx]); numViews++)
{
rdcstr defines;
defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(intIdx) + "\n";
if(numViews > 0 && IsGLES && HasExt[OVR_multiview])
defines = StringFormat::Fmt("#define NUM_VIEWS %zu\n", numViews + 1);
rdcstr blitvs =
GenerateGLSLShader(GetEmbeddedResource(glsl_blit_vert), shaderType, glslBaseVer, defines);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_discard_frag), shaderType, glslBaseVer,
defines);
DebugData.discardProg[intIdx][numViews] = CreateShaderProgram(blitvs, fs);
BindUBO(DebugData.discardProg[intIdx][numViews], "DiscardUBOData", 0);
if(!IsGLES)
{
rdcstr name = "col0";
for(GLuint i = 0; i < 8; i++)
{
name[3] = char('0' + i);
GL.glBindFragDataLocation(DebugData.discardProg[intIdx][numViews], i, name.c_str());
}
}
}
}
{
ResourceFormat fmt;
fmt.type = ResourceFormatType::Regular;
fmt.compType = CompType::Float;
fmt.compByteWidth = 4;
fmt.compCount = 1;
bytebuf pattern = GetDiscardPattern(DiscardType::InvalidateCall, fmt, 1, true);
fmt.compType = CompType::UInt;
pattern.append(GetDiscardPattern(DiscardType::InvalidateCall, fmt, 1, true));
drv.glGenBuffers(1, &DebugData.discardPatternBuffer);
drv.glBindBuffer(eGL_UNIFORM_BUFFER, DebugData.discardPatternBuffer);
drv.glNamedBufferDataEXT(DebugData.discardPatternBuffer, pattern.size(), pattern.data(),
eGL_STATIC_DRAW);
}
if(HasExt[ARB_geometry_shader4])
{
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer);
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_trisize_frag), shaderType, glslBaseVer);
gs = GenerateGLSLShader(GetEmbeddedResource(glsl_trisize_geom), shaderType, glslBaseVer);
// create the shaders
GLuint vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
GLuint trifsShad = CreateShader(eGL_FRAGMENT_SHADER, fs);
GLuint gsShad = CreateShader(eGL_GEOMETRY_SHADER, gs);
DebugData.trisizeProg = CreateMeshProgram(vsShad, trifsShad, gsShad);
// bind trisize-unique viewport size UBO
BindUBO(DebugData.trisizeProg, "ViewportSizeUBO", 2);
GL.glDeleteShader(trifsShad);
GL.glDeleteShader(gsShad);
// we have two fragment shaders, one that reads from the vs outputs and one that reads from the
// gs outputs
rdcstr vsfs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_frag), shaderType, glslBaseVer,
"#define SECONDARY_NAME vsout_secondary\n"
"#define NORM_NAME vsout_norm\n");
rdcstr gsfs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_frag), shaderType, glslBaseVer,
"#define SECONDARY_NAME gsout_secondary\n"
"#define NORM_NAME gsout_norm\n");
gs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_geom), shaderType, glslBaseVer);
// recreate the shaders
GLuint vsfsShad = CreateShader(eGL_FRAGMENT_SHADER, vsfs);
GLuint gsfsShad = CreateShader(eGL_FRAGMENT_SHADER, gsfs);
gsShad = CreateShader(eGL_GEOMETRY_SHADER, gs);
DebugData.meshProg[0] = CreateMeshProgram(vsShad, vsfsShad);
DebugData.meshgsProg[0] = CreateMeshProgram(vsShad, gsfsShad, gsShad);
if(HasExt[ARB_gpu_shader_fp64] && HasExt[ARB_vertex_attrib_64bit])
{
rdcstr extensions =
"#extension GL_ARB_gpu_shader_fp64 : require\n"
"#extension GL_ARB_vertex_attrib_64bit : require\n";
// position only dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions + "#define POSITION_TYPE dvec4\n");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[1] = CreateMeshProgram(vsShad, vsfsShad);
DebugData.meshgsProg[1] = CreateMeshProgram(vsShad, gsfsShad, gsShad);
// secondary only dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions + "#define SECONDARY_TYPE dvec4\n");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[2] = CreateMeshProgram(vsShad, vsfsShad);
DebugData.meshgsProg[2] = CreateMeshProgram(vsShad, gsfsShad, gsShad);
// both dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions +
"#define POSITION_TYPE dvec4\n"
"#define SECONDARY_TYPE dvec4\n");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[3] = CreateMeshProgram(vsShad, vsfsShad);
DebugData.meshgsProg[3] = CreateMeshProgram(vsShad, gsfsShad, gsShad);
}
else
{
// we don't warn about the lack of double support, assuming that if the driver doesn't support
// it then it's highly unlikely that the capture uses it.
DebugData.meshProg[1] = DebugData.meshProg[2] = DebugData.meshProg[3] = 0;
DebugData.meshgsProg[1] = DebugData.meshgsProg[2] = DebugData.meshgsProg[3] = 0;
}
GL.glDeleteShader(vsShad);
GL.glDeleteShader(vsfsShad);
GL.glDeleteShader(gsfsShad);
GL.glDeleteShader(gsShad);
}
else
{
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer);
// without a geometry shader, the fragment shader always reads from vs outputs
fs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_frag), shaderType, glslBaseVer,
"#define SECONDARY_NAME vsout_secondary\n"
"#define NORM_NAME vsout_norm\n");
// create the shaders
GLuint vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
GLuint fsShad = CreateShader(eGL_FRAGMENT_SHADER, fs);
DebugData.meshProg[0] = CreateMeshProgram(vsShad, fsShad);
RDCEraseEl(DebugData.meshgsProg);
DebugData.trisizeProg = 0;
const char *warning_msg =
"GL_ARB_geometry_shader4/GL_EXT_geometry_shader not supported, disabling triangle size and "
"lit solid shading feature.";
RDCWARN(warning_msg);
m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium,
MessageSource::RuntimeWarning, warning_msg);
if(HasExt[ARB_gpu_shader_fp64] && HasExt[ARB_vertex_attrib_64bit])
{
rdcstr extensions =
"#extension GL_ARB_gpu_shader_fp64 : require\n"
"#extension GL_ARB_vertex_attrib_64bit : require\n";
// position only dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions + "#define POSITION_TYPE dvec4");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[1] = CreateMeshProgram(vsShad, fsShad);
// secondary only dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions + "#define SECONDARY_TYPE dvec4");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[2] = CreateMeshProgram(vsShad, fsShad);
// both dvec4
vs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_vert), shaderType, glslBaseVer,
extensions +
"#define POSITION_TYPE dvec4\n"
"#define SECONDARY_TYPE dvec4");
// delete old shader and recreate with new source
GL.glDeleteShader(vsShad);
vsShad = CreateShader(eGL_VERTEX_SHADER, vs);
DebugData.meshProg[3] = CreateMeshProgram(vsShad, fsShad);
}
else
{
// we don't warn about the lack of double support, assuming that if the driver doesn't support
// it then it's highly unlikely that the capture uses it.
DebugData.meshProg[1] = DebugData.meshProg[2] = DebugData.meshProg[3] = 0;
}
GL.glDeleteShader(vsShad);
GL.glDeleteShader(fsShad);
}
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.4f);
drv.glGenBuffers(ARRAY_COUNT(DebugData.UBOs), DebugData.UBOs);
for(size_t i = 0; i < ARRAY_COUNT(DebugData.UBOs); i++)
{
drv.glBindBuffer(eGL_UNIFORM_BUFFER, DebugData.UBOs[i]);
drv.glNamedBufferDataEXT(DebugData.UBOs[i], 2048, NULL, eGL_DYNAMIC_DRAW);
RDCCOMPILE_ASSERT(sizeof(TexDisplayUBOData) <= 2048, "UBO too small");
RDCCOMPILE_ASSERT(sizeof(FontUBOData) <= 2048, "UBO too small");
RDCCOMPILE_ASSERT(sizeof(HistogramUBOData) <= 2048, "UBO too small");
}
DebugData.overlayTexWidth = DebugData.overlayTexHeight = DebugData.overlayTexSamples = 0;
DebugData.overlayTex = DebugData.overlayFBO = 0;
DebugData.overlayProg = 0;
drv.glGenFramebuffers(1, &DebugData.customFBO);
drv.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.customFBO);
DebugData.customTex = 0;
drv.glGenFramebuffers(1, &DebugData.pickPixelFBO);
drv.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.pickPixelFBO);
if(HasExt[ARB_texture_buffer_object])
{
drv.glGenBuffers(1, &DebugData.dummyTexBufferStore);
drv.glBindBuffer(eGL_TEXTURE_BUFFER, DebugData.dummyTexBufferStore);
drv.glNamedBufferDataEXT(DebugData.dummyTexBufferStore, 32, NULL, eGL_STATIC_DRAW);
drv.glBindBuffer(eGL_TEXTURE_BUFFER, 0);
drv.glGenTextures(1, &DebugData.dummyTexBuffer);
drv.glBindTexture(eGL_TEXTURE_BUFFER, DebugData.dummyTexBuffer);
drv.glTextureBufferEXT(DebugData.dummyTexBuffer, eGL_TEXTURE_BUFFER, eGL_RGBA32F,
DebugData.dummyTexBufferStore);
drv.glBindTexture(eGL_TEXTURE_BUFFER, 0);
}
else
{
DebugData.dummyTexBuffer = DebugData.dummyTexBufferStore = 0;
}
drv.glGenTextures(1, &DebugData.pickPixelTex);
drv.glBindTexture(eGL_TEXTURE_2D, DebugData.pickPixelTex);
drv.glTextureImage2DEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, 0, eGL_RGBA32F, 1, 1, 0, eGL_RGBA,
eGL_FLOAT, NULL);
drv.glTextureParameteriEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, eGL_TEXTURE_MAX_LEVEL, 0);
drv.glTextureParameteriEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER,
eGL_NEAREST);
drv.glTextureParameteriEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER,
eGL_NEAREST);
drv.glTextureParameteriEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S,
eGL_CLAMP_TO_EDGE);
drv.glTextureParameteriEXT(DebugData.pickPixelTex, eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T,
eGL_CLAMP_TO_EDGE);
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, eGL_TEXTURE_2D,
DebugData.pickPixelTex, 0);
drv.glGenVertexArrays(1, &DebugData.emptyVAO);
drv.glBindVertexArray(DebugData.emptyVAO);
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.6f);
// histogram/minmax data
{
RDCEraseEl(DebugData.minmaxTileProgram);
RDCEraseEl(DebugData.histogramProgram);
RDCEraseEl(DebugData.minmaxResultProgram);
RDCCOMPILE_ASSERT(
ARRAY_COUNT(DebugData.minmaxTileProgram) >= (TEXDISPLAY_SINT_TEX | TEXDISPLAY_TYPEMASK) + 1,
"not enough programs");
if(HasExt[ARB_compute_shader] && HasExt[ARB_shader_storage_buffer_object] &&
HasExt[ARB_shading_language_420pack])
{
for(int t = 1; t <= RESTYPE_TEXTYPEMAX; t++)
{
// float, uint, sint
for(int i = 0; i < 3; i++)
{
int idx = t;
if(i == 1)
idx |= TEXDISPLAY_UINT_TEX;
if(i == 2)
idx |= TEXDISPLAY_SINT_TEX;
{
rdcstr defines;
defines += rdcstr("#define SHADER_RESTYPE ") + ToStr(t) + "\n";
defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(i) + "\n";
defines += texSampleDefines;
cs = GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxtile_comp), shaderType,
glslCSVer, defines);
DebugData.minmaxTileProgram[idx] = CreateCShaderProgram(cs);
BindUBO(DebugData.minmaxTileProgram[idx], "HistogramUBOData", 2);
ConfigureTexDisplayProgramBindings(DebugData.minmaxTileProgram[idx]);
}
{
rdcstr defines;
defines += rdcstr("#define SHADER_RESTYPE ") + ToStr(t) + "\n";
defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(i) + "\n";
defines += texSampleDefines;
cs = GenerateGLSLShader(GetEmbeddedResource(glsl_histogram_comp), shaderType, glslCSVer,
defines);
DebugData.histogramProgram[idx] = CreateCShaderProgram(cs);
BindUBO(DebugData.histogramProgram[idx], "HistogramUBOData", 2);
ConfigureTexDisplayProgramBindings(DebugData.histogramProgram[idx]);
}
if(t == 1)
{
rdcstr defines;
defines += rdcstr("#define SHADER_RESTYPE ") + ToStr(t) + "\n";
defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(i) + "\n";
cs = GenerateGLSLShader(GetEmbeddedResource(glsl_minmaxresult_comp), shaderType,
glslCSVer, defines);
DebugData.minmaxResultProgram[i] = CreateCShaderProgram(cs);
BindUBO(DebugData.minmaxResultProgram[i], "HistogramUBOData", 2);
ConfigureTexDisplayProgramBindings(DebugData.minmaxResultProgram[i]);
}
}
}
}
else
{
RDCWARN(
"GL_ARB_compute_shader or ARB_shader_storage_buffer_object not supported, disabling "
"min/max and histogram features.");
m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium,
MessageSource::RuntimeWarning,
"GL_ARB_compute_shader or ARB_shader_storage_buffer_object not "
"supported, disabling min/max and histogram features.");
}
drv.glGenBuffers(1, &DebugData.minmaxTileResult);
drv.glGenBuffers(1, &DebugData.minmaxResult);
drv.glGenBuffers(1, &DebugData.histogramBuf);
const uint32_t maxTexDim = 16384;
const uint32_t blockPixSize = HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK;
const uint32_t maxBlocksNeeded = (maxTexDim * maxTexDim) / (blockPixSize * blockPixSize);
const size_t byteSize =
2 * sizeof(Vec4f) * HGRAM_TILES_PER_BLOCK * HGRAM_TILES_PER_BLOCK * maxBlocksNeeded;
drv.glNamedBufferDataEXT(DebugData.minmaxTileResult, byteSize, NULL, eGL_DYNAMIC_DRAW);
drv.glNamedBufferDataEXT(DebugData.minmaxResult, sizeof(Vec4f) * 2, NULL, eGL_DYNAMIC_READ);
drv.glNamedBufferDataEXT(DebugData.histogramBuf, sizeof(uint32_t) * HGRAM_NUM_BUCKETS, NULL,
eGL_DYNAMIC_READ);
}
if(HasExt[ARB_compute_shader] && HasExt[ARB_shading_language_420pack])
{
cs = GenerateGLSLShader(GetEmbeddedResource(glsl_mesh_comp), shaderType, glslCSVer);
DebugData.meshPickProgram = CreateCShaderProgram(cs);
BindUBO(DebugData.meshPickProgram, "MeshPickUBOData", 0);
}
else
{
DebugData.meshPickProgram = 0;
RDCWARN("GL_ARB_compute_shader not supported, disabling mesh picking.");
m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium,
MessageSource::RuntimeWarning,
"GL_ARB_compute_shader not supported, disabling mesh picking.");
}
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.8f);
DebugData.pickResultBuf = 0;
if(DebugData.meshPickProgram)
{
drv.glGenBuffers(1, &DebugData.pickResultBuf);
drv.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickResultBuf);
drv.glNamedBufferDataEXT(DebugData.pickResultBuf,
sizeof(Vec4f) * DebugRenderData::maxMeshPicks + sizeof(uint32_t) * 4,
NULL, eGL_DYNAMIC_READ);
// sized/created on demand
DebugData.pickVBBuf = DebugData.pickIBBuf = 0;
DebugData.pickVBSize = DebugData.pickIBSize = 0;
}
drv.glGenVertexArrays(1, &DebugData.meshVAO);
drv.glBindVertexArray(DebugData.meshVAO);
drv.glGenBuffers(1, &DebugData.axisFrustumBuffer);
drv.glBindBuffer(eGL_ARRAY_BUFFER, DebugData.axisFrustumBuffer);
Vec3f TLN = Vec3f(-1.0f, 1.0f, 0.0f); // TopLeftNear, etc...
Vec3f TRN = Vec3f(1.0f, 1.0f, 0.0f);
Vec3f BLN = Vec3f(-1.0f, -1.0f, 0.0f);
Vec3f BRN = Vec3f(1.0f, -1.0f, 0.0f);
Vec3f TLF = Vec3f(-1.0f, 1.0f, 1.0f);
Vec3f TRF = Vec3f(1.0f, 1.0f, 1.0f);
Vec3f BLF = Vec3f(-1.0f, -1.0f, 1.0f);
Vec3f BRF = Vec3f(1.0f, -1.0f, 1.0f);
Vec3f axisFrustum[] = {
// axis marker vertices
Vec3f(0.0f, 0.0f, 0.0f),
Vec3f(1.0f, 0.0f, 0.0f),
Vec3f(0.0f, 0.0f, 0.0f),
Vec3f(0.0f, 1.0f, 0.0f),
Vec3f(0.0f, 0.0f, 0.0f),
Vec3f(0.0f, 0.0f, 1.0f),
// frustum vertices
TLN,
TRN,
TRN,
BRN,
BRN,
BLN,
BLN,
TLN,
TLN,
TLF,
TRN,
TRF,
BLN,
BLF,
BRN,
BRF,
TLF,
TRF,
TRF,
BRF,
BRF,
BLF,
BLF,
TLF,
};
drv.glNamedBufferDataEXT(DebugData.axisFrustumBuffer, sizeof(axisFrustum), axisFrustum,
eGL_STATIC_DRAW);
drv.glGenVertexArrays(1, &DebugData.axisVAO);
drv.glBindVertexArray(DebugData.axisVAO);
drv.glVertexAttribPointer(0, 3, eGL_FLOAT, GL_FALSE, sizeof(Vec3f), NULL);
drv.glEnableVertexAttribArray(0);
drv.glGenVertexArrays(1, &DebugData.frustumVAO);
drv.glBindVertexArray(DebugData.frustumVAO);
drv.glVertexAttribPointer(0, 3, eGL_FLOAT, GL_FALSE, sizeof(Vec3f),
(const void *)(sizeof(Vec3f) * 6));
drv.glEnableVertexAttribArray(0);
drv.glGenVertexArrays(1, &DebugData.triHighlightVAO);
drv.glBindVertexArray(DebugData.triHighlightVAO);
drv.glGenBuffers(1, &DebugData.triHighlightBuffer);
drv.glBindBuffer(eGL_ARRAY_BUFFER, DebugData.triHighlightBuffer);
drv.glNamedBufferDataEXT(DebugData.triHighlightBuffer, sizeof(Vec4f) * 24, NULL, eGL_DYNAMIC_DRAW);
drv.glVertexAttribPointer(0, 4, eGL_FLOAT, GL_FALSE, sizeof(Vec4f), NULL);
drv.glEnableVertexAttribArray(0);
MakeCurrentReplayContext(&m_ReplayCtx);
// try to identify the GPU we're running on.
{
RDCEraseEl(m_DriverInfo);
const char *vendor = (const char *)drv.glGetString(eGL_VENDOR);
const char *renderer = (const char *)drv.glGetString(eGL_RENDERER);
const char *version = (const char *)drv.glGetString(eGL_VERSION);
// we're just doing substring searches, so combine both for ease.
rdcstr combined = (vendor ? vendor : "");
combined += " ";
combined += (renderer ? renderer : "");
// make lowercase, for case-insensitive matching, and add preceding/trailing space for easier
// 'word' matching
combined = " " + strlower(combined) + " ";
RDCDEBUG("Identifying vendor from '%s'", combined.c_str());
struct pattern
{
const char *search;
GPUVendor vendor;
} patterns[] = {
{" arm ", GPUVendor::ARM},
{" mali ", GPUVendor::ARM},
{" mali-", GPUVendor::ARM},
{" amd ", GPUVendor::AMD},
{"advanced micro devices", GPUVendor::AMD},
{"ati technologies", GPUVendor::AMD},
{"radeon", GPUVendor::AMD},
{"broadcom", GPUVendor::Broadcom},
{"imagination", GPUVendor::Imagination},
{"powervr", GPUVendor::Imagination},
{"intel", GPUVendor::Intel},
{"geforce", GPUVendor::nVidia},
{"quadro", GPUVendor::nVidia},
{"nouveau", GPUVendor::nVidia},
{"nvidia", GPUVendor::nVidia},
{"adreno", GPUVendor::Qualcomm},
{"qualcomm", GPUVendor::Qualcomm},
{"vivante", GPUVendor::Verisilicon},
{"llvmpipe", GPUVendor::Software},
{"softpipe", GPUVendor::Software},
{"bluestacks", GPUVendor::Software},
};
for(const pattern &p : patterns)
{
if(combined.contains(p.search))
{
if(m_DriverInfo.vendor == GPUVendor::Unknown)
{
m_DriverInfo.vendor = p.vendor;
}
else
{
// either we already found this with another pattern, or we've identified two patterns and
// it's ambiguous. Keep the first one we found, arbitrarily, but print a warning.
if(m_DriverInfo.vendor != p.vendor)
{
RDCWARN("Already identified '%s' as %s, but now identified as %s", combined.c_str(),
ToStr(m_DriverInfo.vendor).c_str(), ToStr(p.vendor).c_str());
}
}
}
}
RDCDEBUG("Identified GPU vendor '%s'", ToStr(m_DriverInfo.vendor).c_str());
rdcstr versionString = version;
versionString += " / ";
versionString += renderer ? renderer : "";
versionString += " / ";
versionString += vendor ? vendor : "";
versionString.resize(RDCMIN(versionString.size(), ARRAY_COUNT(m_DriverInfo.version) - 1));
memcpy(m_DriverInfo.version, versionString.c_str(), versionString.size());
}
// these below need to be made on the replay context, as they are context-specific (not shared)
// and will be used on the replay context.
if(HasExt[ARB_transform_feedback2])
drv.glGenTransformFeedbacks(1, &DebugData.feedbackObj);
drv.glGenBuffers(1, &DebugData.feedbackBuffer);
DebugData.feedbackQueries.push_back(0);
drv.glGenQueries(1, &DebugData.feedbackQueries[0]);
if(HasExt[ARB_transform_feedback2])
drv.glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, DebugData.feedbackObj);
drv.glBindBuffer(eGL_TRANSFORM_FEEDBACK_BUFFER, DebugData.feedbackBuffer);
drv.glNamedBufferDataEXT(DebugData.feedbackBuffer, (GLsizeiptr)DebugData.feedbackBufferSize, NULL,
eGL_DYNAMIC_READ);
drv.glBindBufferBase(eGL_TRANSFORM_FEEDBACK_BUFFER, 0, DebugData.feedbackBuffer);
if(HasExt[ARB_transform_feedback2])
drv.glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, 0);
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 1.0f);
if(!HasExt[ARB_gpu_shader5])
{
RDCWARN(
"ARB_gpu_shader5 not supported, pixel picking and saving of integer textures may be "
"inaccurate.");
m_pDriver->AddDebugMessage(MessageCategory::Portability, MessageSeverity::Medium,
MessageSource::RuntimeWarning,
"ARB_gpu_shader5 not supported, pixel picking and saving of integer "
"textures may be inaccurate.");
m_Degraded = true;
}
if(!HasExt[ARB_stencil_texturing])
{
RDCWARN("ARB_stencil_texturing not supported, stencil values will not be displayed or picked.");
m_pDriver->AddDebugMessage(
MessageCategory::Portability, MessageSeverity::Medium, MessageSource::RuntimeWarning,
"ARB_stencil_texturing not supported, stencil values will not be displayed or picked.");
m_Degraded = true;
}
if(!HasExt[ARB_shader_image_load_store] || !HasExt[ARB_compute_shader] ||
!HasExt[ARB_shading_language_420pack])
{
RDCWARN(
"Don't have shader image load/store or compute shaders, functionality will be degraded.");
m_Degraded = true;
}
#if ENABLED(RDOC_APPLE)
// temporary hack - just never consider apple degraded, since there's never going to be an
// improvement so there's no point warning users.
m_Degraded = false;
#endif
m_pDriver->PopInternalShader();
}