summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp297
3 files changed, 159 insertions, 144 deletions
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index e824e216d..1a2e2a9f7 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -157,7 +157,6 @@ Device::Device() : base_bindings{BuildBaseBindings()} {
157 has_precise_bug = TestPreciseBug(); 157 has_precise_bug = TestPreciseBug();
158 has_broken_compute = is_intel_proprietary; 158 has_broken_compute = is_intel_proprietary;
159 has_fast_buffer_sub_data = is_nvidia; 159 has_fast_buffer_sub_data = is_nvidia;
160 has_debug_tool = HasExtension(extensions, "GL_EXT_debug_tool");
161 160
162 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); 161 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
163 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); 162 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 7aaa3a077..d73b099d0 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -84,10 +84,6 @@ public:
84 return has_fast_buffer_sub_data; 84 return has_fast_buffer_sub_data;
85 } 85 }
86 86
87 bool HasDebugTool() const {
88 return has_debug_tool;
89 }
90
91private: 87private:
92 static bool TestVariableAoffi(); 88 static bool TestVariableAoffi();
93 static bool TestPreciseBug(); 89 static bool TestPreciseBug();
@@ -106,7 +102,6 @@ private:
106 bool has_precise_bug{}; 102 bool has_precise_bug{};
107 bool has_broken_compute{}; 103 bool has_broken_compute{};
108 bool has_fast_buffer_sub_data{}; 104 bool has_fast_buffer_sub_data{};
109 bool has_debug_tool{};
110}; 105};
111 106
112} // namespace OpenGL 107} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index c91658cd1..fca5e3ec0 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -5,8 +5,11 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstddef> 6#include <cstddef>
7#include <cstdlib> 7#include <cstdlib>
8#include <cstring>
8#include <memory> 9#include <memory>
10
9#include <glad/glad.h> 11#include <glad/glad.h>
12
10#include "common/assert.h" 13#include "common/assert.h"
11#include "common/logging/log.h" 14#include "common/logging/log.h"
12#include "common/microprofile.h" 15#include "common/microprofile.h"
@@ -25,6 +28,8 @@
25 28
26namespace OpenGL { 29namespace OpenGL {
27 30
31namespace {
32
28// If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have 33// If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
29// to wait on available presentation frames. 34// to wait on available presentation frames.
30constexpr std::size_t SWAP_CHAIN_SIZE = 3; 35constexpr std::size_t SWAP_CHAIN_SIZE = 3;
@@ -41,6 +46,159 @@ struct Frame {
41 bool is_srgb{}; /// Framebuffer is sRGB or RGB 46 bool is_srgb{}; /// Framebuffer is sRGB or RGB
42}; 47};
43 48
49constexpr char VERTEX_SHADER[] = R"(
50#version 430 core
51
52out gl_PerVertex {
53 vec4 gl_Position;
54};
55
56layout (location = 0) in vec2 vert_position;
57layout (location = 1) in vec2 vert_tex_coord;
58layout (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]
65layout (location = 0) uniform mat3x2 modelview_matrix;
66
67void 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
76constexpr char FRAGMENT_SHADER[] = R"(
77#version 430 core
78
79layout (location = 0) in vec2 frag_tex_coord;
80layout (location = 0) out vec4 color;
81
82layout (binding = 0) uniform sampler2D color_texture;
83
84void main() {
85 color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f);
86}
87)";
88
89constexpr GLint PositionLocation = 0;
90constexpr GLint TexCoordLocation = 1;
91constexpr GLint ModelViewMatrixLocation = 0;
92
93struct 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
101/// Returns true if any debug tool is attached
102bool HasDebugTool() {
103 const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
104 if (nsight) {
105 return true;
106 }
107
108 GLint num_extensions;
109 glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
110 for (GLuint index = 0; index < static_cast<GLuint>(num_extensions); ++index) {
111 const auto name = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, index));
112 if (!std::strcmp(name, "GL_EXT_debug_tool")) {
113 return true;
114 }
115 }
116 return false;
117}
118
119/**
120 * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
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 */
126std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
127 std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
128
129 // clang-format off
130 matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
131 matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
132 // Last matrix row is implicitly assumed to be [0, 0, 1].
133 // clang-format on
134
135 return matrix;
136}
137
138const char* GetSource(GLenum source) {
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
158const 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
180void 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
201
44/** 202/**
45 * 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,
46 * but also make sure that rendering happens at the pace that the frontend dictates. This is a 204 * but also make sure that rendering happens at the pace that the frontend dictates. This is a
@@ -56,7 +214,7 @@ public:
56 std::deque<Frame*> present_queue; 214 std::deque<Frame*> present_queue;
57 Frame* previous_frame{}; 215 Frame* previous_frame{};
58 216
59 FrameMailbox() : has_debug_tool{Device().HasDebugTool()} { 217 FrameMailbox() : has_debug_tool{HasDebugTool()} {
60 for (auto& frame : swap_chain) { 218 for (auto& frame : swap_chain) {
61 free_queue.push(&frame); 219 free_queue.push(&frame);
62 } 220 }
@@ -188,143 +346,6 @@ private:
188 } 346 }
189}; 347};
190 348
191namespace {
192
193constexpr char VERTEX_SHADER[] = R"(
194#version 430 core
195
196out gl_PerVertex {
197 vec4 gl_Position;
198};
199
200layout (location = 0) in vec2 vert_position;
201layout (location = 1) in vec2 vert_tex_coord;
202layout (location = 0) out vec2 frag_tex_coord;
203
204// This is a truncated 3x3 matrix for 2D transformations:
205// The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
206// The third column performs translation.
207// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
208// implicitly be [0, 0, 1]
209layout (location = 0) uniform mat3x2 modelview_matrix;
210
211void main() {
212 // Multiply input position by the rotscale part of the matrix and then manually translate by
213 // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
214 // to `vec3(vert_position.xy, 1.0)`
215 gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
216 frag_tex_coord = vert_tex_coord;
217}
218)";
219
220constexpr char FRAGMENT_SHADER[] = R"(
221#version 430 core
222
223layout (location = 0) in vec2 frag_tex_coord;
224layout (location = 0) out vec4 color;
225
226layout (binding = 0) uniform sampler2D color_texture;
227
228void main() {
229 color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f);
230}
231)";
232
233constexpr GLint PositionLocation = 0;
234constexpr GLint TexCoordLocation = 1;
235constexpr GLint ModelViewMatrixLocation = 0;
236
237struct ScreenRectVertex {
238 constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v)
239 : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {}
240
241 std::array<GLfloat, 2> position;
242 std::array<GLfloat, 2> tex_coord;
243};
244
245/**
246 * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
247 * corner and (width, height) on the lower-bottom.
248 *
249 * The projection part of the matrix is trivial, hence these operations are represented
250 * by a 3x2 matrix.
251 */
252std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
253 std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
254
255 // clang-format off
256 matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
257 matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
258 // Last matrix row is implicitly assumed to be [0, 0, 1].
259 // clang-format on
260
261 return matrix;
262}
263
264const char* GetSource(GLenum source) {
265 switch (source) {
266 case GL_DEBUG_SOURCE_API:
267 return "API";
268 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
269 return "WINDOW_SYSTEM";
270 case GL_DEBUG_SOURCE_SHADER_COMPILER:
271 return "SHADER_COMPILER";
272 case GL_DEBUG_SOURCE_THIRD_PARTY:
273 return "THIRD_PARTY";
274 case GL_DEBUG_SOURCE_APPLICATION:
275 return "APPLICATION";
276 case GL_DEBUG_SOURCE_OTHER:
277 return "OTHER";
278 default:
279 UNREACHABLE();
280 return "Unknown source";
281 }
282}
283
284const char* GetType(GLenum type) {
285 switch (type) {
286 case GL_DEBUG_TYPE_ERROR:
287 return "ERROR";
288 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
289 return "DEPRECATED_BEHAVIOR";
290 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
291 return "UNDEFINED_BEHAVIOR";
292 case GL_DEBUG_TYPE_PORTABILITY:
293 return "PORTABILITY";
294 case GL_DEBUG_TYPE_PERFORMANCE:
295 return "PERFORMANCE";
296 case GL_DEBUG_TYPE_OTHER:
297 return "OTHER";
298 case GL_DEBUG_TYPE_MARKER:
299 return "MARKER";
300 default:
301 UNREACHABLE();
302 return "Unknown type";
303 }
304}
305
306void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
307 const GLchar* message, const void* user_param) {
308 const char format[] = "{} {} {}: {}";
309 const char* const str_source = GetSource(source);
310 const char* const str_type = GetType(type);
311
312 switch (severity) {
313 case GL_DEBUG_SEVERITY_HIGH:
314 LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message);
315 break;
316 case GL_DEBUG_SEVERITY_MEDIUM:
317 LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message);
318 break;
319 case GL_DEBUG_SEVERITY_NOTIFICATION:
320 case GL_DEBUG_SEVERITY_LOW:
321 LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
322 break;
323 }
324}
325
326} // Anonymous namespace
327
328RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) 349RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system)
329 : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, 350 : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system},
330 frame_mailbox{std::make_unique<FrameMailbox>()} {} 351 frame_mailbox{std::make_unique<FrameMailbox>()} {}