Ive got this simple shader code that I want to step through. I launch the program in RenderDoc. I select a pixel, but the option to debug is grayed out. Why? and how can I fix it?
Im assuming it may have something to do with the version of glsl not being supported?
Im using AMD Radeon RX 6650 XT on Windows 11
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
// Vertex Shader Source
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
// Fragment Shader Source
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
const int emax = 127;
int floorLog2(float x) {
if (x == 0.) return -emax;
for (int e = emax; e >= 1 - emax; --e)
if (x >= exp2(float(e))) return e;
return emax + 1;
}
int biasedExp(float x) {
return emax + floorLog2(abs(x));
}
float significand(float x) {
float expo = float(floorLog2(abs(x)));
return abs(x) / exp2(expo);
}
int part(float x, int N) {
const float byteShift = 256.;
for (int n = 0; n < N; ++n)
x *= byteShift;
float q = fract(x);
float c = floor(byteShift * q);
return int(c);
}
ivec3 significandAsIVec3(float x) {
ivec3 result;
float sig = significand(x) / 2.;
result.x = part(sig, 0);
result.y = part(sig, 1);
result.z = part(sig, 2);
return result;
}
ivec4 unpackIEEE754binary32(float x) {
int e = biasedExp(x);
int s = x < 0. ? 128 : 0;
ivec4 binary32;
binary32.yzw = significandAsIVec3(x);
if (binary32.y >= 128) {
binary32.y -= 128;
}
binary32.y += 128 * int(mod(float(e), 2.));
e /= 2;
binary32.x = e + s;
binary32.x -= 1;
binary32.y -= 1;
binary32.z -= 1;
binary32.w -= 1;
return binary32;
}
void main() {
float testValue = 3.0;
ivec4 result = unpackIEEE754binary32(testValue);
// Normalize the result to see the output
vec4 color = vec4(
float(result.x) / 255.0,
float(result.y) / 255.0,
float(result.z) / 255.0,
float(result.w) / 255.0
);
FragColor = color;
}
)";
GLFWwindow* createWindow() {
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return nullptr;
}
// Request OpenGL Debug Context
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Shader Debug", NULL, NULL);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return nullptr;
}
glfwMakeContextCurrent(window);
return window;
}
void APIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam) {
std::cerr << "OpenGL Debug Message: " << message << std::endl;
}
GLuint compileShader(const char* shaderSource, GLenum shaderType) {
GLuint shader = glCreateShader(shaderType);
// Provide the shader source code
glShaderSource(shader, 1, &shaderSource, nullptr);
// Compile the shader with debug info (if supported)
glCompileShader(shader);
// Check for compile errors
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
// Retrieve and print the error log
GLchar infoLog[1024];
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
const char* shaderTypeStr = shaderType == GL_VERTEX_SHADER ? "VERTEX" : "FRAGMENT";
std::cerr << "ERROR::SHADER_COMPILATION_ERROR of type: " << shaderTypeStr << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
return shader;
}
GLuint createShaderProgram() {
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
// Create the shader program
GLuint shaderProgram = glCreateProgram();
// Attach shaders
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// Link the program
glLinkProgram(shaderProgram);
// Check for linking errors
GLint success;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
// Retrieve and print the error log
GLchar infoLog[1024];
glGetProgramInfoLog(shaderProgram, 1024, NULL, infoLog);
std::cerr << "ERROR::PROGRAM_LINKING_ERROR\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer needed
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
int main() {
GLFWwindow* window = createWindow();
if (!window) return -1;
// Initialize GLEW with experimental features enabled
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
// Enable OpenGL debug output if available
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
std::cout << "Debug context active" << std::endl;
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(openglDebugCallback, nullptr);
}
// Vertex data for a full-screen quad
float vertices[] = {
// positions
-1.0f, 1.0f, 0.0f, // top left
-1.0f, -1.0f, 0.0f, // bottom left
1.0f, 1.0f, 0.0f, // top right
1.0f, -1.0f, 0.0f // bottom right
};
// Set up vertex data and buffers
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Bind Vertex Array Object
glBindVertexArray(VAO);
// Bind and set vertex buffer(s)
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Configure vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Create shader program
GLuint shaderProgram = createShaderProgram();
// Render loop
while (!glfwWindowShouldClose(window)) {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
// Use shader program and draw
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Swap buffers and poll IO events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Cleanup resources
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
// Terminate GLFW
glfwTerminate();
return 0;
}
According to RenderDoc's How do I debug a shader page, OpenGL shader debugging is not supported.
Shader debugging is currently only supported on D3D11, D3D12, and Vulkan.
If you hover over the Debug button, RenderDoc shows a tooltip, saying
Shader debugging not supported on this API
The good news is that even the newest GLSL version is supported by RenderDoc, you can use it with Vulkan for example. Also, if you use another API, make sure to select a draw call in the Event Browser, because RenderDoc has to know which draw call do you want to debug.