renderer_opengl.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-FileCopyrightText: 2014 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <cstddef>
  5. #include <cstdlib>
  6. #include <memory>
  7. #include <glad/glad.h>
  8. #include "common/assert.h"
  9. #include "common/logging/log.h"
  10. #include "common/microprofile.h"
  11. #include "common/settings.h"
  12. #include "common/telemetry.h"
  13. #include "core/core_timing.h"
  14. #include "core/frontend/emu_window.h"
  15. #include "core/telemetry_session.h"
  16. #include "video_core/capture.h"
  17. #include "video_core/present.h"
  18. #include "video_core/renderer_opengl/gl_blit_screen.h"
  19. #include "video_core/renderer_opengl/gl_rasterizer.h"
  20. #include "video_core/renderer_opengl/gl_shader_manager.h"
  21. #include "video_core/renderer_opengl/gl_shader_util.h"
  22. #include "video_core/renderer_opengl/renderer_opengl.h"
  23. #include "video_core/textures/decoders.h"
  24. namespace OpenGL {
  25. namespace {
  26. const char* GetSource(GLenum source) {
  27. switch (source) {
  28. case GL_DEBUG_SOURCE_API:
  29. return "API";
  30. case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
  31. return "WINDOW_SYSTEM";
  32. case GL_DEBUG_SOURCE_SHADER_COMPILER:
  33. return "SHADER_COMPILER";
  34. case GL_DEBUG_SOURCE_THIRD_PARTY:
  35. return "THIRD_PARTY";
  36. case GL_DEBUG_SOURCE_APPLICATION:
  37. return "APPLICATION";
  38. case GL_DEBUG_SOURCE_OTHER:
  39. return "OTHER";
  40. default:
  41. ASSERT(false);
  42. return "Unknown source";
  43. }
  44. }
  45. const char* GetType(GLenum type) {
  46. switch (type) {
  47. case GL_DEBUG_TYPE_ERROR:
  48. return "ERROR";
  49. case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
  50. return "DEPRECATED_BEHAVIOR";
  51. case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
  52. return "UNDEFINED_BEHAVIOR";
  53. case GL_DEBUG_TYPE_PORTABILITY:
  54. return "PORTABILITY";
  55. case GL_DEBUG_TYPE_PERFORMANCE:
  56. return "PERFORMANCE";
  57. case GL_DEBUG_TYPE_OTHER:
  58. return "OTHER";
  59. case GL_DEBUG_TYPE_MARKER:
  60. return "MARKER";
  61. default:
  62. ASSERT(false);
  63. return "Unknown type";
  64. }
  65. }
  66. void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
  67. const GLchar* message, const void* user_param) {
  68. const char format[] = "{} {} {}: {}";
  69. const char* const str_source = GetSource(source);
  70. const char* const str_type = GetType(type);
  71. switch (severity) {
  72. case GL_DEBUG_SEVERITY_HIGH:
  73. LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message);
  74. break;
  75. case GL_DEBUG_SEVERITY_MEDIUM:
  76. LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message);
  77. break;
  78. case GL_DEBUG_SEVERITY_NOTIFICATION:
  79. case GL_DEBUG_SEVERITY_LOW:
  80. LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
  81. break;
  82. }
  83. }
  84. } // Anonymous namespace
  85. RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
  86. Core::Frontend::EmuWindow& emu_window_,
  87. Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
  88. std::unique_ptr<Core::Frontend::GraphicsContext> context_)
  89. : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
  90. emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
  91. state_tracker{}, program_manager{device},
  92. rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) {
  93. if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
  94. glEnable(GL_DEBUG_OUTPUT);
  95. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  96. glDebugMessageCallback(DebugHandler, nullptr);
  97. }
  98. AddTelemetryFields();
  99. // Initialize default attributes to match hardware's disabled attributes
  100. GLint max_attribs{};
  101. glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attribs);
  102. for (GLint attrib = 0; attrib < max_attribs; ++attrib) {
  103. glVertexAttrib4f(attrib, 0.0f, 0.0f, 0.0f, 1.0f);
  104. }
  105. // Enable seamless cubemaps when per texture parameters are not available
  106. if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
  107. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
  108. }
  109. // Enable unified vertex attributes when the driver supports it
  110. if (device.HasVertexBufferUnifiedMemory()) {
  111. glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
  112. glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
  113. }
  114. blit_screen = std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker,
  115. program_manager, device, PresentFiltersForDisplay);
  116. blit_applet =
  117. std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker, program_manager,
  118. device, PresentFiltersForAppletCapture);
  119. capture_framebuffer.Create();
  120. capture_renderbuffer.Create();
  121. glBindRenderbuffer(GL_RENDERBUFFER, capture_renderbuffer.handle);
  122. glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, VideoCore::Capture::LinearWidth,
  123. VideoCore::Capture::LinearHeight);
  124. }
  125. RendererOpenGL::~RendererOpenGL() = default;
  126. void RendererOpenGL::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
  127. if (framebuffers.empty()) {
  128. return;
  129. }
  130. RenderAppletCaptureLayer(framebuffers);
  131. RenderScreenshot(framebuffers);
  132. state_tracker.BindFramebuffer(0);
  133. blit_screen->DrawScreen(framebuffers, emu_window.GetFramebufferLayout(), false);
  134. ++m_current_frame;
  135. gpu.RendererFrameEndNotify();
  136. rasterizer.TickFrame();
  137. context->SwapBuffers();
  138. render_window.OnFrameDisplayed();
  139. }
  140. void RendererOpenGL::AddTelemetryFields() {
  141. const char* const gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
  142. const char* const gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
  143. const char* const gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
  144. LOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
  145. LOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
  146. LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
  147. constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
  148. telemetry_session.AddField(user_system, "GPU_Vendor", std::string(gpu_vendor));
  149. telemetry_session.AddField(user_system, "GPU_Model", std::string(gpu_model));
  150. telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
  151. }
  152. void RendererOpenGL::RenderToBuffer(std::span<const Tegra::FramebufferConfig> framebuffers,
  153. const Layout::FramebufferLayout& layout, void* dst) {
  154. GLint old_read_fb;
  155. GLint old_draw_fb;
  156. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  157. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  158. // Draw the current frame to the screenshot framebuffer
  159. screenshot_framebuffer.Create();
  160. glBindFramebuffer(GL_FRAMEBUFFER, screenshot_framebuffer.handle);
  161. GLuint renderbuffer;
  162. glGenRenderbuffers(1, &renderbuffer);
  163. glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
  164. glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
  165. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
  166. blit_screen->DrawScreen(framebuffers, layout, false);
  167. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  168. glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  169. glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dst);
  170. screenshot_framebuffer.Release();
  171. glDeleteRenderbuffers(1, &renderbuffer);
  172. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  173. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  174. }
  175. void RendererOpenGL::RenderScreenshot(std::span<const Tegra::FramebufferConfig> framebuffers) {
  176. if (!renderer_settings.screenshot_requested) {
  177. return;
  178. }
  179. RenderToBuffer(framebuffers, renderer_settings.screenshot_framebuffer_layout,
  180. renderer_settings.screenshot_bits);
  181. renderer_settings.screenshot_complete_callback(true);
  182. renderer_settings.screenshot_requested = false;
  183. }
  184. void RendererOpenGL::RenderAppletCaptureLayer(
  185. std::span<const Tegra::FramebufferConfig> framebuffers) {
  186. GLint old_read_fb;
  187. GLint old_draw_fb;
  188. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  189. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  190. glBindFramebuffer(GL_FRAMEBUFFER, capture_framebuffer.handle);
  191. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
  192. capture_renderbuffer.handle);
  193. blit_applet->DrawScreen(framebuffers, VideoCore::Capture::Layout, true);
  194. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  195. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  196. }
  197. std::vector<u8> RendererOpenGL::GetAppletCaptureBuffer() {
  198. using namespace VideoCore::Capture;
  199. std::vector<u8> linear(TiledSize);
  200. std::vector<u8> out(TiledSize);
  201. GLint old_read_fb;
  202. GLint old_draw_fb;
  203. GLint old_pixel_pack_buffer;
  204. GLint old_pack_row_length;
  205. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  206. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  207. glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &old_pixel_pack_buffer);
  208. glGetIntegerv(GL_PACK_ROW_LENGTH, &old_pack_row_length);
  209. glBindFramebuffer(GL_FRAMEBUFFER, capture_framebuffer.handle);
  210. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
  211. capture_renderbuffer.handle);
  212. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  213. glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  214. glReadPixels(0, 0, LinearWidth, LinearHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
  215. linear.data());
  216. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  217. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  218. glBindBuffer(GL_PIXEL_PACK_BUFFER, old_pixel_pack_buffer);
  219. glPixelStorei(GL_PACK_ROW_LENGTH, old_pack_row_length);
  220. Tegra::Texture::SwizzleTexture(out, linear, BytesPerPixel, LinearWidth, LinearHeight,
  221. LinearDepth, BlockHeight, BlockDepth);
  222. return out;
  223. }
  224. } // namespace OpenGL