renderer_opengl.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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/renderer_opengl/gl_blit_screen.h"
  17. #include "video_core/renderer_opengl/gl_rasterizer.h"
  18. #include "video_core/renderer_opengl/gl_shader_manager.h"
  19. #include "video_core/renderer_opengl/gl_shader_util.h"
  20. #include "video_core/renderer_opengl/renderer_opengl.h"
  21. #include "video_core/textures/decoders.h"
  22. namespace OpenGL {
  23. namespace {
  24. const char* GetSource(GLenum source) {
  25. switch (source) {
  26. case GL_DEBUG_SOURCE_API:
  27. return "API";
  28. case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
  29. return "WINDOW_SYSTEM";
  30. case GL_DEBUG_SOURCE_SHADER_COMPILER:
  31. return "SHADER_COMPILER";
  32. case GL_DEBUG_SOURCE_THIRD_PARTY:
  33. return "THIRD_PARTY";
  34. case GL_DEBUG_SOURCE_APPLICATION:
  35. return "APPLICATION";
  36. case GL_DEBUG_SOURCE_OTHER:
  37. return "OTHER";
  38. default:
  39. ASSERT(false);
  40. return "Unknown source";
  41. }
  42. }
  43. const char* GetType(GLenum type) {
  44. switch (type) {
  45. case GL_DEBUG_TYPE_ERROR:
  46. return "ERROR";
  47. case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
  48. return "DEPRECATED_BEHAVIOR";
  49. case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
  50. return "UNDEFINED_BEHAVIOR";
  51. case GL_DEBUG_TYPE_PORTABILITY:
  52. return "PORTABILITY";
  53. case GL_DEBUG_TYPE_PERFORMANCE:
  54. return "PERFORMANCE";
  55. case GL_DEBUG_TYPE_OTHER:
  56. return "OTHER";
  57. case GL_DEBUG_TYPE_MARKER:
  58. return "MARKER";
  59. default:
  60. ASSERT(false);
  61. return "Unknown type";
  62. }
  63. }
  64. void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
  65. const GLchar* message, const void* user_param) {
  66. const char format[] = "{} {} {}: {}";
  67. const char* const str_source = GetSource(source);
  68. const char* const str_type = GetType(type);
  69. switch (severity) {
  70. case GL_DEBUG_SEVERITY_HIGH:
  71. LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message);
  72. break;
  73. case GL_DEBUG_SEVERITY_MEDIUM:
  74. LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message);
  75. break;
  76. case GL_DEBUG_SEVERITY_NOTIFICATION:
  77. case GL_DEBUG_SEVERITY_LOW:
  78. LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
  79. break;
  80. }
  81. }
  82. } // Anonymous namespace
  83. RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
  84. Core::Frontend::EmuWindow& emu_window_,
  85. Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
  86. std::unique_ptr<Core::Frontend::GraphicsContext> context_)
  87. : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
  88. emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
  89. state_tracker{}, program_manager{device},
  90. rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) {
  91. if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
  92. glEnable(GL_DEBUG_OUTPUT);
  93. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  94. glDebugMessageCallback(DebugHandler, nullptr);
  95. }
  96. AddTelemetryFields();
  97. // Initialize default attributes to match hardware's disabled attributes
  98. GLint max_attribs{};
  99. glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attribs);
  100. for (GLint attrib = 0; attrib < max_attribs; ++attrib) {
  101. glVertexAttrib4f(attrib, 0.0f, 0.0f, 0.0f, 1.0f);
  102. }
  103. // Enable seamless cubemaps when per texture parameters are not available
  104. if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
  105. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
  106. }
  107. // Enable unified vertex attributes when the driver supports it
  108. if (device.HasVertexBufferUnifiedMemory()) {
  109. glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
  110. glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
  111. }
  112. blit_screen = std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker,
  113. program_manager, device);
  114. }
  115. RendererOpenGL::~RendererOpenGL() = default;
  116. void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
  117. if (!framebuffer) {
  118. return;
  119. }
  120. RenderScreenshot(framebuffer);
  121. state_tracker.BindFramebuffer(0);
  122. blit_screen->DrawScreen(std::span(framebuffer, 1), emu_window.GetFramebufferLayout());
  123. ++m_current_frame;
  124. gpu.RendererFrameEndNotify();
  125. rasterizer.TickFrame();
  126. context->SwapBuffers();
  127. render_window.OnFrameDisplayed();
  128. }
  129. void RendererOpenGL::AddTelemetryFields() {
  130. const char* const gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
  131. const char* const gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
  132. const char* const gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
  133. LOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
  134. LOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
  135. LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
  136. constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
  137. telemetry_session.AddField(user_system, "GPU_Vendor", std::string(gpu_vendor));
  138. telemetry_session.AddField(user_system, "GPU_Model", std::string(gpu_model));
  139. telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
  140. }
  141. void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig* framebuffer) {
  142. if (!renderer_settings.screenshot_requested) {
  143. return;
  144. }
  145. GLint old_read_fb;
  146. GLint old_draw_fb;
  147. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  148. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  149. // Draw the current frame to the screenshot framebuffer
  150. screenshot_framebuffer.Create();
  151. glBindFramebuffer(GL_FRAMEBUFFER, screenshot_framebuffer.handle);
  152. const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
  153. GLuint renderbuffer;
  154. glGenRenderbuffers(1, &renderbuffer);
  155. glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
  156. glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
  157. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
  158. blit_screen->DrawScreen(std::span(framebuffer, 1), layout);
  159. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  160. glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  161. glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
  162. renderer_settings.screenshot_bits);
  163. screenshot_framebuffer.Release();
  164. glDeleteRenderbuffers(1, &renderbuffer);
  165. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  166. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  167. renderer_settings.screenshot_complete_callback(true);
  168. renderer_settings.screenshot_requested = false;
  169. }
  170. } // namespace OpenGL