Merge pull request #3521 from ReinUsesLisp/nsight-debug
renderer_opengl: Detect Nvidia Nsight as a debugging tool
This commit is contained in:
		
						commit
						e8ded20d24
					
				| @ -157,7 +157,6 @@ Device::Device() : base_bindings{BuildBaseBindings()} { | ||||
|     has_precise_bug = TestPreciseBug(); | ||||
|     has_broken_compute = is_intel_proprietary; | ||||
|     has_fast_buffer_sub_data = is_nvidia; | ||||
|     has_debug_tool = HasExtension(extensions, "GL_EXT_debug_tool"); | ||||
| 
 | ||||
|     LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | ||||
|     LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); | ||||
|  | ||||
| @ -84,10 +84,6 @@ public: | ||||
|         return has_fast_buffer_sub_data; | ||||
|     } | ||||
| 
 | ||||
|     bool HasDebugTool() const { | ||||
|         return has_debug_tool; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     static bool TestVariableAoffi(); | ||||
|     static bool TestPreciseBug(); | ||||
| @ -106,7 +102,6 @@ private: | ||||
|     bool has_precise_bug{}; | ||||
|     bool has_broken_compute{}; | ||||
|     bool has_fast_buffer_sub_data{}; | ||||
|     bool has_debug_tool{}; | ||||
| }; | ||||
| 
 | ||||
| } // namespace OpenGL
 | ||||
|  | ||||
| @ -5,8 +5,11 @@ | ||||
| #include <algorithm> | ||||
| #include <cstddef> | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include <memory> | ||||
| 
 | ||||
| #include <glad/glad.h> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| @ -25,6 +28,8 @@ | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
 | ||||
| // to wait on available presentation frames.
 | ||||
| constexpr std::size_t SWAP_CHAIN_SIZE = 3; | ||||
| @ -41,6 +46,159 @@ struct Frame { | ||||
|     bool is_srgb{};                   /// Framebuffer is sRGB or RGB
 | ||||
| }; | ||||
| 
 | ||||
| constexpr char VERTEX_SHADER[] = R"( | ||||
| #version 430 core | ||||
| 
 | ||||
| out gl_PerVertex { | ||||
|     vec4 gl_Position; | ||||
| }; | ||||
| 
 | ||||
| layout (location = 0) in vec2 vert_position; | ||||
| layout (location = 1) in vec2 vert_tex_coord; | ||||
| layout (location = 0) out vec2 frag_tex_coord; | ||||
| 
 | ||||
| // This is a truncated 3x3 matrix for 2D transformations:
 | ||||
| // The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
 | ||||
| // The third column performs translation.
 | ||||
| // The third row could be used for projection, which we don't need in 2D. It hence is assumed to
 | ||||
| // implicitly be [0, 0, 1]
 | ||||
| layout (location = 0) uniform mat3x2 modelview_matrix; | ||||
| 
 | ||||
| void main() { | ||||
|     // Multiply input position by the rotscale part of the matrix and then manually translate by
 | ||||
|     // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
 | ||||
|     // to `vec3(vert_position.xy, 1.0)`
 | ||||
|     gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||||
|     frag_tex_coord = vert_tex_coord; | ||||
| } | ||||
| )"; | ||||
| 
 | ||||
| constexpr char FRAGMENT_SHADER[] = R"( | ||||
| #version 430 core | ||||
| 
 | ||||
| layout (location = 0) in vec2 frag_tex_coord; | ||||
| layout (location = 0) out vec4 color; | ||||
| 
 | ||||
| layout (binding = 0) uniform sampler2D color_texture; | ||||
| 
 | ||||
| void main() { | ||||
|     color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||||
| } | ||||
| )"; | ||||
| 
 | ||||
| constexpr GLint PositionLocation = 0; | ||||
| constexpr GLint TexCoordLocation = 1; | ||||
| constexpr GLint ModelViewMatrixLocation = 0; | ||||
| 
 | ||||
| struct ScreenRectVertex { | ||||
|     constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) | ||||
|         : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {} | ||||
| 
 | ||||
|     std::array<GLfloat, 2> position; | ||||
|     std::array<GLfloat, 2> tex_coord; | ||||
| }; | ||||
| 
 | ||||
| /// Returns true if any debug tool is attached
 | ||||
| bool HasDebugTool() { | ||||
|     const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); | ||||
|     if (nsight) { | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     GLint num_extensions; | ||||
|     glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); | ||||
|     for (GLuint index = 0; index < static_cast<GLuint>(num_extensions); ++index) { | ||||
|         const auto name = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, index)); | ||||
|         if (!std::strcmp(name, "GL_EXT_debug_tool")) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left | ||||
|  * corner and (width, height) on the lower-bottom. | ||||
|  * | ||||
|  * The projection part of the matrix is trivial, hence these operations are represented | ||||
|  * by a 3x2 matrix. | ||||
|  */ | ||||
| std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) { | ||||
|     std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
 | ||||
| 
 | ||||
|     // clang-format off
 | ||||
|     matrix[0] = 2.f / width; matrix[2] =  0.f;          matrix[4] = -1.f; | ||||
|     matrix[1] = 0.f;         matrix[3] = -2.f / height; matrix[5] =  1.f; | ||||
|     // Last matrix row is implicitly assumed to be [0, 0, 1].
 | ||||
|     // clang-format on
 | ||||
| 
 | ||||
|     return matrix; | ||||
| } | ||||
| 
 | ||||
| const char* GetSource(GLenum source) { | ||||
|     switch (source) { | ||||
|     case GL_DEBUG_SOURCE_API: | ||||
|         return "API"; | ||||
|     case GL_DEBUG_SOURCE_WINDOW_SYSTEM: | ||||
|         return "WINDOW_SYSTEM"; | ||||
|     case GL_DEBUG_SOURCE_SHADER_COMPILER: | ||||
|         return "SHADER_COMPILER"; | ||||
|     case GL_DEBUG_SOURCE_THIRD_PARTY: | ||||
|         return "THIRD_PARTY"; | ||||
|     case GL_DEBUG_SOURCE_APPLICATION: | ||||
|         return "APPLICATION"; | ||||
|     case GL_DEBUG_SOURCE_OTHER: | ||||
|         return "OTHER"; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|         return "Unknown source"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const char* GetType(GLenum type) { | ||||
|     switch (type) { | ||||
|     case GL_DEBUG_TYPE_ERROR: | ||||
|         return "ERROR"; | ||||
|     case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: | ||||
|         return "DEPRECATED_BEHAVIOR"; | ||||
|     case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: | ||||
|         return "UNDEFINED_BEHAVIOR"; | ||||
|     case GL_DEBUG_TYPE_PORTABILITY: | ||||
|         return "PORTABILITY"; | ||||
|     case GL_DEBUG_TYPE_PERFORMANCE: | ||||
|         return "PERFORMANCE"; | ||||
|     case GL_DEBUG_TYPE_OTHER: | ||||
|         return "OTHER"; | ||||
|     case GL_DEBUG_TYPE_MARKER: | ||||
|         return "MARKER"; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|         return "Unknown type"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, | ||||
|                            const GLchar* message, const void* user_param) { | ||||
|     const char format[] = "{} {} {}: {}"; | ||||
|     const char* const str_source = GetSource(source); | ||||
|     const char* const str_type = GetType(type); | ||||
| 
 | ||||
|     switch (severity) { | ||||
|     case GL_DEBUG_SEVERITY_HIGH: | ||||
|         LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     case GL_DEBUG_SEVERITY_MEDIUM: | ||||
|         LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     case GL_DEBUG_SEVERITY_NOTIFICATION: | ||||
|     case GL_DEBUG_SEVERITY_LOW: | ||||
|         LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| /**
 | ||||
|  * For smooth Vsync rendering, we want to always present the latest frame that the core generates, | ||||
|  * but also make sure that rendering happens at the pace that the frontend dictates. This is a | ||||
| @ -56,7 +214,7 @@ public: | ||||
|     std::deque<Frame*> present_queue; | ||||
|     Frame* previous_frame{}; | ||||
| 
 | ||||
|     FrameMailbox() : has_debug_tool{Device().HasDebugTool()} { | ||||
|     FrameMailbox() : has_debug_tool{HasDebugTool()} { | ||||
|         for (auto& frame : swap_chain) { | ||||
|             free_queue.push(&frame); | ||||
|         } | ||||
| @ -188,143 +346,6 @@ private: | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| constexpr char VERTEX_SHADER[] = R"( | ||||
| #version 430 core | ||||
| 
 | ||||
| out gl_PerVertex { | ||||
|     vec4 gl_Position; | ||||
| }; | ||||
| 
 | ||||
| layout (location = 0) in vec2 vert_position; | ||||
| layout (location = 1) in vec2 vert_tex_coord; | ||||
| layout (location = 0) out vec2 frag_tex_coord; | ||||
| 
 | ||||
| // This is a truncated 3x3 matrix for 2D transformations:
 | ||||
| // The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
 | ||||
| // The third column performs translation.
 | ||||
| // The third row could be used for projection, which we don't need in 2D. It hence is assumed to
 | ||||
| // implicitly be [0, 0, 1]
 | ||||
| layout (location = 0) uniform mat3x2 modelview_matrix; | ||||
| 
 | ||||
| void main() { | ||||
|     // Multiply input position by the rotscale part of the matrix and then manually translate by
 | ||||
|     // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
 | ||||
|     // to `vec3(vert_position.xy, 1.0)`
 | ||||
|     gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||||
|     frag_tex_coord = vert_tex_coord; | ||||
| } | ||||
| )"; | ||||
| 
 | ||||
| constexpr char FRAGMENT_SHADER[] = R"( | ||||
| #version 430 core | ||||
| 
 | ||||
| layout (location = 0) in vec2 frag_tex_coord; | ||||
| layout (location = 0) out vec4 color; | ||||
| 
 | ||||
| layout (binding = 0) uniform sampler2D color_texture; | ||||
| 
 | ||||
| void main() { | ||||
|     color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||||
| } | ||||
| )"; | ||||
| 
 | ||||
| constexpr GLint PositionLocation = 0; | ||||
| constexpr GLint TexCoordLocation = 1; | ||||
| constexpr GLint ModelViewMatrixLocation = 0; | ||||
| 
 | ||||
| struct ScreenRectVertex { | ||||
|     constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) | ||||
|         : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {} | ||||
| 
 | ||||
|     std::array<GLfloat, 2> position; | ||||
|     std::array<GLfloat, 2> tex_coord; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left | ||||
|  * corner and (width, height) on the lower-bottom. | ||||
|  * | ||||
|  * The projection part of the matrix is trivial, hence these operations are represented | ||||
|  * by a 3x2 matrix. | ||||
|  */ | ||||
| std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) { | ||||
|     std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
 | ||||
| 
 | ||||
|     // clang-format off
 | ||||
|     matrix[0] = 2.f / width; matrix[2] =  0.f;          matrix[4] = -1.f; | ||||
|     matrix[1] = 0.f;         matrix[3] = -2.f / height; matrix[5] =  1.f; | ||||
|     // Last matrix row is implicitly assumed to be [0, 0, 1].
 | ||||
|     // clang-format on
 | ||||
| 
 | ||||
|     return matrix; | ||||
| } | ||||
| 
 | ||||
| const char* GetSource(GLenum source) { | ||||
|     switch (source) { | ||||
|     case GL_DEBUG_SOURCE_API: | ||||
|         return "API"; | ||||
|     case GL_DEBUG_SOURCE_WINDOW_SYSTEM: | ||||
|         return "WINDOW_SYSTEM"; | ||||
|     case GL_DEBUG_SOURCE_SHADER_COMPILER: | ||||
|         return "SHADER_COMPILER"; | ||||
|     case GL_DEBUG_SOURCE_THIRD_PARTY: | ||||
|         return "THIRD_PARTY"; | ||||
|     case GL_DEBUG_SOURCE_APPLICATION: | ||||
|         return "APPLICATION"; | ||||
|     case GL_DEBUG_SOURCE_OTHER: | ||||
|         return "OTHER"; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|         return "Unknown source"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const char* GetType(GLenum type) { | ||||
|     switch (type) { | ||||
|     case GL_DEBUG_TYPE_ERROR: | ||||
|         return "ERROR"; | ||||
|     case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: | ||||
|         return "DEPRECATED_BEHAVIOR"; | ||||
|     case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: | ||||
|         return "UNDEFINED_BEHAVIOR"; | ||||
|     case GL_DEBUG_TYPE_PORTABILITY: | ||||
|         return "PORTABILITY"; | ||||
|     case GL_DEBUG_TYPE_PERFORMANCE: | ||||
|         return "PERFORMANCE"; | ||||
|     case GL_DEBUG_TYPE_OTHER: | ||||
|         return "OTHER"; | ||||
|     case GL_DEBUG_TYPE_MARKER: | ||||
|         return "MARKER"; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|         return "Unknown type"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, | ||||
|                            const GLchar* message, const void* user_param) { | ||||
|     const char format[] = "{} {} {}: {}"; | ||||
|     const char* const str_source = GetSource(source); | ||||
|     const char* const str_type = GetType(type); | ||||
| 
 | ||||
|     switch (severity) { | ||||
|     case GL_DEBUG_SEVERITY_HIGH: | ||||
|         LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     case GL_DEBUG_SEVERITY_MEDIUM: | ||||
|         LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     case GL_DEBUG_SEVERITY_NOTIFICATION: | ||||
|     case GL_DEBUG_SEVERITY_LOW: | ||||
|         LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) | ||||
|     : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, | ||||
|       frame_mailbox{std::make_unique<FrameMailbox>()} {} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei