diff options
| author | 2020-03-16 04:03:16 -0300 | |
|---|---|---|
| committer | 2020-03-16 04:03:34 -0300 | |
| commit | 53d673a7d3ff1c7321d62b4b67c40fb42fe7425f (patch) | |
| tree | a0138f450f0cb9ae37da6b57da05f507ca8523cb | |
| parent | renderer_opengl: Detect Nvidia Nsight as a debugging tool (diff) | |
| download | yuzu-53d673a7d3ff1c7321d62b4b67c40fb42fe7425f.tar.gz yuzu-53d673a7d3ff1c7321d62b4b67c40fb42fe7425f.tar.xz yuzu-53d673a7d3ff1c7321d62b4b67c40fb42fe7425f.zip | |
renderer_opengl: Move some logic to an anonymous namespace
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 302 |
1 files changed, 151 insertions, 151 deletions
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index d8ecd090b..fca5e3ec0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -28,6 +28,76 @@ | |||
| 28 | 28 | ||
| 29 | namespace OpenGL { | 29 | namespace OpenGL { |
| 30 | 30 | ||
| 31 | namespace { | ||
| 32 | |||
| 33 | // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have | ||
| 34 | // to wait on available presentation frames. | ||
| 35 | constexpr std::size_t SWAP_CHAIN_SIZE = 3; | ||
| 36 | |||
| 37 | struct Frame { | ||
| 38 | u32 width{}; /// Width of the frame (to detect resize) | ||
| 39 | u32 height{}; /// Height of the frame | ||
| 40 | bool color_reloaded{}; /// Texture attachment was recreated (ie: resized) | ||
| 41 | OpenGL::OGLRenderbuffer color{}; /// Buffer shared between the render/present FBO | ||
| 42 | OpenGL::OGLFramebuffer render{}; /// FBO created on the render thread | ||
| 43 | OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread | ||
| 44 | GLsync render_fence{}; /// Fence created on the render thread | ||
| 45 | GLsync present_fence{}; /// Fence created on the presentation thread | ||
| 46 | bool is_srgb{}; /// Framebuffer is sRGB or RGB | ||
| 47 | }; | ||
| 48 | |||
| 49 | constexpr char VERTEX_SHADER[] = R"( | ||
| 50 | #version 430 core | ||
| 51 | |||
| 52 | out gl_PerVertex { | ||
| 53 | vec4 gl_Position; | ||
| 54 | }; | ||
| 55 | |||
| 56 | layout (location = 0) in vec2 vert_position; | ||
| 57 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 58 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 59 | |||
| 60 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 61 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 62 | // The third column performs translation. | ||
| 63 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 64 | // implicitly be [0, 0, 1] | ||
| 65 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 66 | |||
| 67 | void main() { | ||
| 68 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 69 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 70 | // to `vec3(vert_position.xy, 1.0)` | ||
| 71 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 72 | frag_tex_coord = vert_tex_coord; | ||
| 73 | } | ||
| 74 | )"; | ||
| 75 | |||
| 76 | constexpr char FRAGMENT_SHADER[] = R"( | ||
| 77 | #version 430 core | ||
| 78 | |||
| 79 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 80 | layout (location = 0) out vec4 color; | ||
| 81 | |||
| 82 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 83 | |||
| 84 | void main() { | ||
| 85 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 86 | } | ||
| 87 | )"; | ||
| 88 | |||
| 89 | constexpr GLint PositionLocation = 0; | ||
| 90 | constexpr GLint TexCoordLocation = 1; | ||
| 91 | constexpr GLint ModelViewMatrixLocation = 0; | ||
| 92 | |||
| 93 | struct ScreenRectVertex { | ||
| 94 | constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) | ||
| 95 | : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {} | ||
| 96 | |||
| 97 | std::array<GLfloat, 2> position; | ||
| 98 | std::array<GLfloat, 2> tex_coord; | ||
| 99 | }; | ||
| 100 | |||
| 31 | /// Returns true if any debug tool is attached | 101 | /// Returns true if any debug tool is attached |
| 32 | bool HasDebugTool() { | 102 | bool HasDebugTool() { |
| 33 | const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); | 103 | const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); |
| @@ -46,21 +116,88 @@ bool HasDebugTool() { | |||
| 46 | return false; | 116 | return false; |
| 47 | } | 117 | } |
| 48 | 118 | ||
| 49 | // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have | 119 | /** |
| 50 | // to wait on available presentation frames. | 120 | * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left |
| 51 | constexpr std::size_t SWAP_CHAIN_SIZE = 3; | 121 | * corner and (width, height) on the lower-bottom. |
| 122 | * | ||
| 123 | * The projection part of the matrix is trivial, hence these operations are represented | ||
| 124 | * by a 3x2 matrix. | ||
| 125 | */ | ||
| 126 | std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) { | ||
| 127 | std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order | ||
| 52 | 128 | ||
| 53 | struct Frame { | 129 | // clang-format off |
| 54 | u32 width{}; /// Width of the frame (to detect resize) | 130 | matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; |
| 55 | u32 height{}; /// Height of the frame | 131 | matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; |
| 56 | bool color_reloaded{}; /// Texture attachment was recreated (ie: resized) | 132 | // Last matrix row is implicitly assumed to be [0, 0, 1]. |
| 57 | OpenGL::OGLRenderbuffer color{}; /// Buffer shared between the render/present FBO | 133 | // clang-format on |
| 58 | OpenGL::OGLFramebuffer render{}; /// FBO created on the render thread | 134 | |
| 59 | OpenGL::OGLFramebuffer present{}; /// FBO created on the present thread | 135 | return matrix; |
| 60 | GLsync render_fence{}; /// Fence created on the render thread | 136 | } |
| 61 | GLsync present_fence{}; /// Fence created on the presentation thread | 137 | |
| 62 | bool is_srgb{}; /// Framebuffer is sRGB or RGB | 138 | const char* GetSource(GLenum source) { |
| 63 | }; | 139 | switch (source) { |
| 140 | case GL_DEBUG_SOURCE_API: | ||
| 141 | return "API"; | ||
| 142 | case GL_DEBUG_SOURCE_WINDOW_SYSTEM: | ||
| 143 | return "WINDOW_SYSTEM"; | ||
| 144 | case GL_DEBUG_SOURCE_SHADER_COMPILER: | ||
| 145 | return "SHADER_COMPILER"; | ||
| 146 | case GL_DEBUG_SOURCE_THIRD_PARTY: | ||
| 147 | return "THIRD_PARTY"; | ||
| 148 | case GL_DEBUG_SOURCE_APPLICATION: | ||
| 149 | return "APPLICATION"; | ||
| 150 | case GL_DEBUG_SOURCE_OTHER: | ||
| 151 | return "OTHER"; | ||
| 152 | default: | ||
| 153 | UNREACHABLE(); | ||
| 154 | return "Unknown source"; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | const char* GetType(GLenum type) { | ||
| 159 | switch (type) { | ||
| 160 | case GL_DEBUG_TYPE_ERROR: | ||
| 161 | return "ERROR"; | ||
| 162 | case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: | ||
| 163 | return "DEPRECATED_BEHAVIOR"; | ||
| 164 | case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: | ||
| 165 | return "UNDEFINED_BEHAVIOR"; | ||
| 166 | case GL_DEBUG_TYPE_PORTABILITY: | ||
| 167 | return "PORTABILITY"; | ||
| 168 | case GL_DEBUG_TYPE_PERFORMANCE: | ||
| 169 | return "PERFORMANCE"; | ||
| 170 | case GL_DEBUG_TYPE_OTHER: | ||
| 171 | return "OTHER"; | ||
| 172 | case GL_DEBUG_TYPE_MARKER: | ||
| 173 | return "MARKER"; | ||
| 174 | default: | ||
| 175 | UNREACHABLE(); | ||
| 176 | return "Unknown type"; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, | ||
| 181 | const GLchar* message, const void* user_param) { | ||
| 182 | const char format[] = "{} {} {}: {}"; | ||
| 183 | const char* const str_source = GetSource(source); | ||
| 184 | const char* const str_type = GetType(type); | ||
| 185 | |||
| 186 | switch (severity) { | ||
| 187 | case GL_DEBUG_SEVERITY_HIGH: | ||
| 188 | LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 189 | break; | ||
| 190 | case GL_DEBUG_SEVERITY_MEDIUM: | ||
| 191 | LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 192 | break; | ||
| 193 | case GL_DEBUG_SEVERITY_NOTIFICATION: | ||
| 194 | case GL_DEBUG_SEVERITY_LOW: | ||
| 195 | LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | } // Anonymous namespace | ||
| 64 | 201 | ||
| 65 | /** | 202 | /** |
| 66 | * For smooth Vsync rendering, we want to always present the latest frame that the core generates, | 203 | * For smooth Vsync rendering, we want to always present the latest frame that the core generates, |
| @@ -209,143 +346,6 @@ private: | |||
| 209 | } | 346 | } |
| 210 | }; | 347 | }; |
| 211 | 348 | ||
| 212 | namespace { | ||
| 213 | |||
| 214 | constexpr char VERTEX_SHADER[] = R"( | ||
| 215 | #version 430 core | ||
| 216 | |||
| 217 | out gl_PerVertex { | ||
| 218 | vec4 gl_Position; | ||
| 219 | }; | ||
| 220 | |||
| 221 | layout (location = 0) in vec2 vert_position; | ||
| 222 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 223 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 224 | |||
| 225 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 226 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 227 | // The third column performs translation. | ||
| 228 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 229 | // implicitly be [0, 0, 1] | ||
| 230 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 231 | |||
| 232 | void main() { | ||
| 233 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 234 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 235 | // to `vec3(vert_position.xy, 1.0)` | ||
| 236 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 237 | frag_tex_coord = vert_tex_coord; | ||
| 238 | } | ||
| 239 | )"; | ||
| 240 | |||
| 241 | constexpr char FRAGMENT_SHADER[] = R"( | ||
| 242 | #version 430 core | ||
| 243 | |||
| 244 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 245 | layout (location = 0) out vec4 color; | ||
| 246 | |||
| 247 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 248 | |||
| 249 | void main() { | ||
| 250 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 251 | } | ||
| 252 | )"; | ||
| 253 | |||
| 254 | constexpr GLint PositionLocation = 0; | ||
| 255 | constexpr GLint TexCoordLocation = 1; | ||
| 256 | constexpr GLint ModelViewMatrixLocation = 0; | ||
| 257 | |||
| 258 | struct ScreenRectVertex { | ||
| 259 | constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) | ||
| 260 | : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {} | ||
| 261 | |||
| 262 | std::array<GLfloat, 2> position; | ||
| 263 | std::array<GLfloat, 2> tex_coord; | ||
| 264 | }; | ||
| 265 | |||
| 266 | /** | ||
| 267 | * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left | ||
| 268 | * corner and (width, height) on the lower-bottom. | ||
| 269 | * | ||
| 270 | * The projection part of the matrix is trivial, hence these operations are represented | ||
| 271 | * by a 3x2 matrix. | ||
| 272 | */ | ||
| 273 | std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) { | ||
| 274 | std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order | ||
| 275 | |||
| 276 | // clang-format off | ||
| 277 | matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; | ||
| 278 | matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; | ||
| 279 | // Last matrix row is implicitly assumed to be [0, 0, 1]. | ||
| 280 | // clang-format on | ||
| 281 | |||
| 282 | return matrix; | ||
| 283 | } | ||
| 284 | |||
| 285 | const char* GetSource(GLenum source) { | ||
| 286 | switch (source) { | ||
| 287 | case GL_DEBUG_SOURCE_API: | ||
| 288 | return "API"; | ||
| 289 | case GL_DEBUG_SOURCE_WINDOW_SYSTEM: | ||
| 290 | return "WINDOW_SYSTEM"; | ||
| 291 | case GL_DEBUG_SOURCE_SHADER_COMPILER: | ||
| 292 | return "SHADER_COMPILER"; | ||
| 293 | case GL_DEBUG_SOURCE_THIRD_PARTY: | ||
| 294 | return "THIRD_PARTY"; | ||
| 295 | case GL_DEBUG_SOURCE_APPLICATION: | ||
| 296 | return "APPLICATION"; | ||
| 297 | case GL_DEBUG_SOURCE_OTHER: | ||
| 298 | return "OTHER"; | ||
| 299 | default: | ||
| 300 | UNREACHABLE(); | ||
| 301 | return "Unknown source"; | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | const char* GetType(GLenum type) { | ||
| 306 | switch (type) { | ||
| 307 | case GL_DEBUG_TYPE_ERROR: | ||
| 308 | return "ERROR"; | ||
| 309 | case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: | ||
| 310 | return "DEPRECATED_BEHAVIOR"; | ||
| 311 | case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: | ||
| 312 | return "UNDEFINED_BEHAVIOR"; | ||
| 313 | case GL_DEBUG_TYPE_PORTABILITY: | ||
| 314 | return "PORTABILITY"; | ||
| 315 | case GL_DEBUG_TYPE_PERFORMANCE: | ||
| 316 | return "PERFORMANCE"; | ||
| 317 | case GL_DEBUG_TYPE_OTHER: | ||
| 318 | return "OTHER"; | ||
| 319 | case GL_DEBUG_TYPE_MARKER: | ||
| 320 | return "MARKER"; | ||
| 321 | default: | ||
| 322 | UNREACHABLE(); | ||
| 323 | return "Unknown type"; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, | ||
| 328 | const GLchar* message, const void* user_param) { | ||
| 329 | const char format[] = "{} {} {}: {}"; | ||
| 330 | const char* const str_source = GetSource(source); | ||
| 331 | const char* const str_type = GetType(type); | ||
| 332 | |||
| 333 | switch (severity) { | ||
| 334 | case GL_DEBUG_SEVERITY_HIGH: | ||
| 335 | LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 336 | break; | ||
| 337 | case GL_DEBUG_SEVERITY_MEDIUM: | ||
| 338 | LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 339 | break; | ||
| 340 | case GL_DEBUG_SEVERITY_NOTIFICATION: | ||
| 341 | case GL_DEBUG_SEVERITY_LOW: | ||
| 342 | LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | } // Anonymous namespace | ||
| 348 | |||
| 349 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) | 349 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) |
| 350 | : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, | 350 | : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, |
| 351 | frame_mailbox{std::make_unique<FrameMailbox>()} {} | 351 | frame_mailbox{std::make_unique<FrameMailbox>()} {} |