renderer_opengl.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  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/host_shaders/ffx_a_h.h"
  17. #include "video_core/host_shaders/ffx_fsr1_h.h"
  18. #include "video_core/host_shaders/full_screen_triangle_vert.h"
  19. #include "video_core/host_shaders/fxaa_frag.h"
  20. #include "video_core/host_shaders/fxaa_vert.h"
  21. #include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h"
  22. #include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h"
  23. #include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h"
  24. #include "video_core/host_shaders/opengl_present_frag.h"
  25. #include "video_core/host_shaders/opengl_present_scaleforce_frag.h"
  26. #include "video_core/host_shaders/opengl_present_vert.h"
  27. #include "video_core/host_shaders/opengl_smaa_glsl.h"
  28. #include "video_core/host_shaders/present_bicubic_frag.h"
  29. #include "video_core/host_shaders/present_gaussian_frag.h"
  30. #include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h"
  31. #include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h"
  32. #include "video_core/host_shaders/smaa_edge_detection_frag.h"
  33. #include "video_core/host_shaders/smaa_edge_detection_vert.h"
  34. #include "video_core/host_shaders/smaa_neighborhood_blending_frag.h"
  35. #include "video_core/host_shaders/smaa_neighborhood_blending_vert.h"
  36. #include "video_core/renderer_opengl/gl_fsr.h"
  37. #include "video_core/renderer_opengl/gl_rasterizer.h"
  38. #include "video_core/renderer_opengl/gl_shader_manager.h"
  39. #include "video_core/renderer_opengl/gl_shader_util.h"
  40. #include "video_core/renderer_opengl/renderer_opengl.h"
  41. #include "video_core/smaa_area_tex.h"
  42. #include "video_core/smaa_search_tex.h"
  43. #include "video_core/textures/decoders.h"
  44. namespace OpenGL {
  45. namespace {
  46. constexpr GLint PositionLocation = 0;
  47. constexpr GLint TexCoordLocation = 1;
  48. constexpr GLint ModelViewMatrixLocation = 0;
  49. struct ScreenRectVertex {
  50. constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v)
  51. : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {}
  52. std::array<GLfloat, 2> position;
  53. std::array<GLfloat, 2> tex_coord;
  54. };
  55. /**
  56. * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
  57. * corner and (width, height) on the lower-bottom.
  58. *
  59. * The projection part of the matrix is trivial, hence these operations are represented
  60. * by a 3x2 matrix.
  61. */
  62. std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
  63. std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
  64. // clang-format off
  65. matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
  66. matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
  67. // Last matrix row is implicitly assumed to be [0, 0, 1].
  68. // clang-format on
  69. return matrix;
  70. }
  71. const char* GetSource(GLenum source) {
  72. switch (source) {
  73. case GL_DEBUG_SOURCE_API:
  74. return "API";
  75. case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
  76. return "WINDOW_SYSTEM";
  77. case GL_DEBUG_SOURCE_SHADER_COMPILER:
  78. return "SHADER_COMPILER";
  79. case GL_DEBUG_SOURCE_THIRD_PARTY:
  80. return "THIRD_PARTY";
  81. case GL_DEBUG_SOURCE_APPLICATION:
  82. return "APPLICATION";
  83. case GL_DEBUG_SOURCE_OTHER:
  84. return "OTHER";
  85. default:
  86. ASSERT(false);
  87. return "Unknown source";
  88. }
  89. }
  90. const char* GetType(GLenum type) {
  91. switch (type) {
  92. case GL_DEBUG_TYPE_ERROR:
  93. return "ERROR";
  94. case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
  95. return "DEPRECATED_BEHAVIOR";
  96. case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
  97. return "UNDEFINED_BEHAVIOR";
  98. case GL_DEBUG_TYPE_PORTABILITY:
  99. return "PORTABILITY";
  100. case GL_DEBUG_TYPE_PERFORMANCE:
  101. return "PERFORMANCE";
  102. case GL_DEBUG_TYPE_OTHER:
  103. return "OTHER";
  104. case GL_DEBUG_TYPE_MARKER:
  105. return "MARKER";
  106. default:
  107. ASSERT(false);
  108. return "Unknown type";
  109. }
  110. }
  111. void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
  112. const GLchar* message, const void* user_param) {
  113. const char format[] = "{} {} {}: {}";
  114. const char* const str_source = GetSource(source);
  115. const char* const str_type = GetType(type);
  116. switch (severity) {
  117. case GL_DEBUG_SEVERITY_HIGH:
  118. LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message);
  119. break;
  120. case GL_DEBUG_SEVERITY_MEDIUM:
  121. LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message);
  122. break;
  123. case GL_DEBUG_SEVERITY_NOTIFICATION:
  124. case GL_DEBUG_SEVERITY_LOW:
  125. LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
  126. break;
  127. }
  128. }
  129. } // Anonymous namespace
  130. RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
  131. Core::Frontend::EmuWindow& emu_window_,
  132. Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
  133. std::unique_ptr<Core::Frontend::GraphicsContext> context_)
  134. : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
  135. emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
  136. state_tracker{}, program_manager{device},
  137. rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager,
  138. state_tracker) {
  139. if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
  140. glEnable(GL_DEBUG_OUTPUT);
  141. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  142. glDebugMessageCallback(DebugHandler, nullptr);
  143. }
  144. AddTelemetryFields();
  145. InitOpenGLObjects();
  146. // Initialize default attributes to match hardware's disabled attributes
  147. GLint max_attribs{};
  148. glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attribs);
  149. for (GLint attrib = 0; attrib < max_attribs; ++attrib) {
  150. glVertexAttrib4f(attrib, 0.0f, 0.0f, 0.0f, 1.0f);
  151. }
  152. // Enable seamless cubemaps when per texture parameters are not available
  153. if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
  154. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
  155. }
  156. // Enable unified vertex attributes and query vertex buffer address when the driver supports it
  157. if (device.HasVertexBufferUnifiedMemory()) {
  158. glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
  159. glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
  160. glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
  161. glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
  162. &vertex_buffer_address);
  163. }
  164. }
  165. RendererOpenGL::~RendererOpenGL() = default;
  166. void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
  167. if (!framebuffer) {
  168. return;
  169. }
  170. PrepareRendertarget(framebuffer);
  171. RenderScreenshot();
  172. state_tracker.BindFramebuffer(0);
  173. DrawScreen(emu_window.GetFramebufferLayout());
  174. ++m_current_frame;
  175. gpu.RendererFrameEndNotify();
  176. rasterizer.TickFrame();
  177. context->SwapBuffers();
  178. render_window.OnFrameDisplayed();
  179. }
  180. void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {
  181. if (!framebuffer) {
  182. return;
  183. }
  184. // If framebuffer is provided, reload it from memory to a texture
  185. if (screen_info.texture.width != static_cast<GLsizei>(framebuffer->width) ||
  186. screen_info.texture.height != static_cast<GLsizei>(framebuffer->height) ||
  187. screen_info.texture.pixel_format != framebuffer->pixel_format ||
  188. gl_framebuffer_data.empty()) {
  189. // Reallocate texture if the framebuffer size has changed.
  190. // This is expected to not happen very often and hence should not be a
  191. // performance problem.
  192. ConfigureFramebufferTexture(screen_info.texture, *framebuffer);
  193. }
  194. // Load the framebuffer from memory, draw it to the screen, and swap buffers
  195. LoadFBToScreenInfo(*framebuffer);
  196. }
  197. void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) {
  198. // Framebuffer orientation handling
  199. framebuffer_transform_flags = framebuffer.transform_flags;
  200. framebuffer_crop_rect = framebuffer.crop_rect;
  201. framebuffer_width = framebuffer.width;
  202. framebuffer_height = framebuffer.height;
  203. const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
  204. screen_info.was_accelerated =
  205. rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
  206. if (screen_info.was_accelerated) {
  207. return;
  208. }
  209. // Reset the screen info's display texture to its own permanent texture
  210. screen_info.display_texture = screen_info.texture.resource.handle;
  211. // TODO(Rodrigo): Read this from HLE
  212. constexpr u32 block_height_log2 = 4;
  213. const auto pixel_format{
  214. VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
  215. const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
  216. const u64 size_in_bytes{Tegra::Texture::CalculateSize(
  217. true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
  218. const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
  219. const std::span<const u8> input_data(host_ptr, size_in_bytes);
  220. Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
  221. framebuffer.width, framebuffer.height, 1, block_height_log2,
  222. 0);
  223. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  224. glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
  225. // Update existing texture
  226. // TODO: Test what happens on hardware when you change the framebuffer dimensions so that
  227. // they differ from the LCD resolution.
  228. // TODO: Applications could theoretically crash yuzu here by specifying too large
  229. // framebuffer sizes. We should make sure that this cannot happen.
  230. glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width,
  231. framebuffer.height, screen_info.texture.gl_format,
  232. screen_info.texture.gl_type, gl_framebuffer_data.data());
  233. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  234. }
  235. void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
  236. const TextureInfo& texture) {
  237. const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
  238. glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
  239. }
  240. void RendererOpenGL::InitOpenGLObjects() {
  241. // Create shader programs
  242. fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER);
  243. fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER);
  244. const auto replace_include = [](std::string& shader_source, std::string_view include_name,
  245. std::string_view include_content) {
  246. const std::string include_string = fmt::format("#include \"{}\"", include_name);
  247. const std::size_t pos = shader_source.find(include_string);
  248. ASSERT(pos != std::string::npos);
  249. shader_source.replace(pos, include_string.size(), include_content);
  250. };
  251. const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) {
  252. std::string shader_source{specialized_source};
  253. replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL);
  254. return CreateProgram(shader_source, stage);
  255. };
  256. smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER);
  257. smaa_edge_detection_frag =
  258. SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER);
  259. smaa_blending_weight_calculation_vert =
  260. SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER);
  261. smaa_blending_weight_calculation_frag =
  262. SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER);
  263. smaa_neighborhood_blending_vert =
  264. SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER);
  265. smaa_neighborhood_blending_frag =
  266. SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER);
  267. present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
  268. present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
  269. present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
  270. present_gaussian_fragment =
  271. CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER);
  272. present_scaleforce_fragment =
  273. CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
  274. GL_FRAGMENT_SHADER);
  275. std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG};
  276. replace_include(fsr_source, "ffx_a.h", HostShaders::FFX_A_H);
  277. replace_include(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H);
  278. std::string fsr_easu_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG};
  279. std::string fsr_rcas_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG};
  280. replace_include(fsr_easu_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
  281. replace_include(fsr_rcas_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
  282. fsr = std::make_unique<FSR>(HostShaders::FULL_SCREEN_TRIANGLE_VERT, fsr_easu_frag_source,
  283. fsr_rcas_frag_source);
  284. // Generate presentation sampler
  285. present_sampler.Create();
  286. glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  287. glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  288. glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  289. glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  290. glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  291. present_sampler_nn.Create();
  292. glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  293. glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  294. glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  295. glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  296. glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  297. // Generate VBO handle for drawing
  298. vertex_buffer.Create();
  299. // Attach vertex data to VAO
  300. glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
  301. // Allocate textures for the screen
  302. screen_info.texture.resource.Create(GL_TEXTURE_2D);
  303. const GLuint texture = screen_info.texture.resource.handle;
  304. glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
  305. screen_info.display_texture = screen_info.texture.resource.handle;
  306. // Clear screen to black
  307. LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
  308. aa_framebuffer.Create();
  309. smaa_area_tex.Create(GL_TEXTURE_2D);
  310. glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT);
  311. glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG,
  312. GL_UNSIGNED_BYTE, areaTexBytes);
  313. smaa_search_tex.Create(GL_TEXTURE_2D);
  314. glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT);
  315. glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED,
  316. GL_UNSIGNED_BYTE, searchTexBytes);
  317. }
  318. void RendererOpenGL::AddTelemetryFields() {
  319. const char* const gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
  320. const char* const gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
  321. const char* const gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
  322. LOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
  323. LOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
  324. LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
  325. constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
  326. telemetry_session.AddField(user_system, "GPU_Vendor", std::string(gpu_vendor));
  327. telemetry_session.AddField(user_system, "GPU_Model", std::string(gpu_model));
  328. telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
  329. }
  330. void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
  331. const Tegra::FramebufferConfig& framebuffer) {
  332. texture.width = framebuffer.width;
  333. texture.height = framebuffer.height;
  334. texture.pixel_format = framebuffer.pixel_format;
  335. const auto pixel_format{
  336. VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
  337. const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
  338. gl_framebuffer_data.resize(texture.width * texture.height * bytes_per_pixel);
  339. GLint internal_format;
  340. switch (framebuffer.pixel_format) {
  341. case Service::android::PixelFormat::Rgba8888:
  342. internal_format = GL_RGBA8;
  343. texture.gl_format = GL_RGBA;
  344. texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  345. break;
  346. case Service::android::PixelFormat::Rgb565:
  347. internal_format = GL_RGB565;
  348. texture.gl_format = GL_RGB;
  349. texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
  350. break;
  351. default:
  352. internal_format = GL_RGBA8;
  353. texture.gl_format = GL_RGBA;
  354. texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  355. // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
  356. // static_cast<u32>(framebuffer.pixel_format));
  357. break;
  358. }
  359. texture.resource.Release();
  360. texture.resource.Create(GL_TEXTURE_2D);
  361. glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
  362. aa_texture.Release();
  363. aa_texture.Create(GL_TEXTURE_2D);
  364. glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
  365. Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
  366. Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
  367. glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
  368. smaa_edges_tex.Release();
  369. smaa_edges_tex.Create(GL_TEXTURE_2D);
  370. glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
  371. Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
  372. Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
  373. smaa_blend_tex.Release();
  374. smaa_blend_tex.Create(GL_TEXTURE_2D);
  375. glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
  376. Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
  377. Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
  378. }
  379. void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
  380. // TODO: Signal state tracker about these changes
  381. state_tracker.NotifyScreenDrawVertexArray();
  382. state_tracker.NotifyPolygonModes();
  383. state_tracker.NotifyViewport0();
  384. state_tracker.NotifyScissor0();
  385. state_tracker.NotifyColorMask(0);
  386. state_tracker.NotifyBlend0();
  387. state_tracker.NotifyFramebuffer();
  388. state_tracker.NotifyFrontFace();
  389. state_tracker.NotifyCullTest();
  390. state_tracker.NotifyDepthTest();
  391. state_tracker.NotifyStencilTest();
  392. state_tracker.NotifyPolygonOffset();
  393. state_tracker.NotifyRasterizeEnable();
  394. state_tracker.NotifyFramebufferSRGB();
  395. state_tracker.NotifyLogicOp();
  396. state_tracker.NotifyClipControl();
  397. state_tracker.NotifyAlphaTest();
  398. state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
  399. glEnable(GL_CULL_FACE);
  400. glDisable(GL_COLOR_LOGIC_OP);
  401. glDisable(GL_DEPTH_TEST);
  402. glDisable(GL_STENCIL_TEST);
  403. glDisable(GL_POLYGON_OFFSET_FILL);
  404. glDisable(GL_RASTERIZER_DISCARD);
  405. glDisable(GL_ALPHA_TEST);
  406. glDisablei(GL_BLEND, 0);
  407. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  408. glCullFace(GL_BACK);
  409. glFrontFace(GL_CW);
  410. glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  411. glDepthRangeIndexed(0, 0.0, 0.0);
  412. glBindTextureUnit(0, screen_info.display_texture);
  413. auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
  414. if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
  415. LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing);
  416. anti_aliasing = Settings::AntiAliasing::None;
  417. Settings::values.anti_aliasing.SetValue(anti_aliasing);
  418. }
  419. if (anti_aliasing != Settings::AntiAliasing::None) {
  420. glEnablei(GL_SCISSOR_TEST, 0);
  421. auto viewport_width = screen_info.texture.width;
  422. auto scissor_width = framebuffer_crop_rect.GetWidth();
  423. if (scissor_width <= 0) {
  424. scissor_width = viewport_width;
  425. }
  426. auto viewport_height = screen_info.texture.height;
  427. auto scissor_height = framebuffer_crop_rect.GetHeight();
  428. if (scissor_height <= 0) {
  429. scissor_height = viewport_height;
  430. }
  431. if (screen_info.was_accelerated) {
  432. viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
  433. scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
  434. viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height);
  435. scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height);
  436. }
  437. glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
  438. glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
  439. static_cast<GLfloat>(viewport_height));
  440. glBindSampler(0, present_sampler.handle);
  441. GLint old_read_fb;
  442. GLint old_draw_fb;
  443. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  444. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  445. switch (anti_aliasing) {
  446. case Settings::AntiAliasing::Fxaa: {
  447. program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle);
  448. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
  449. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  450. } break;
  451. case Settings::AntiAliasing::Smaa: {
  452. glClearColor(0, 0, 0, 0);
  453. glFrontFace(GL_CCW);
  454. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
  455. glBindSampler(1, present_sampler.handle);
  456. glBindSampler(2, present_sampler.handle);
  457. glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
  458. smaa_edges_tex.handle, 0);
  459. glClear(GL_COLOR_BUFFER_BIT);
  460. program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle,
  461. smaa_edge_detection_frag.handle);
  462. glDrawArrays(GL_TRIANGLES, 0, 3);
  463. glBindTextureUnit(0, smaa_edges_tex.handle);
  464. glBindTextureUnit(1, smaa_area_tex.handle);
  465. glBindTextureUnit(2, smaa_search_tex.handle);
  466. glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
  467. smaa_blend_tex.handle, 0);
  468. glClear(GL_COLOR_BUFFER_BIT);
  469. program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle,
  470. smaa_blending_weight_calculation_frag.handle);
  471. glDrawArrays(GL_TRIANGLES, 0, 3);
  472. glBindTextureUnit(0, screen_info.display_texture);
  473. glBindTextureUnit(1, smaa_blend_tex.handle);
  474. glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
  475. aa_texture.handle, 0);
  476. program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle,
  477. smaa_neighborhood_blending_frag.handle);
  478. glDrawArrays(GL_TRIANGLES, 0, 3);
  479. glFrontFace(GL_CW);
  480. } break;
  481. default:
  482. UNREACHABLE();
  483. }
  484. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  485. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  486. glBindTextureUnit(0, aa_texture.handle);
  487. }
  488. glDisablei(GL_SCISSOR_TEST, 0);
  489. if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
  490. if (!fsr->AreBuffersInitialized()) {
  491. fsr->InitBuffers();
  492. }
  493. auto crop_rect = framebuffer_crop_rect;
  494. if (crop_rect.GetWidth() == 0) {
  495. crop_rect.right = framebuffer_width;
  496. }
  497. if (crop_rect.GetHeight() == 0) {
  498. crop_rect.bottom = framebuffer_height;
  499. }
  500. crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
  501. const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width);
  502. const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height);
  503. glBindSampler(0, present_sampler.handle);
  504. fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect);
  505. } else {
  506. if (fsr->AreBuffersInitialized()) {
  507. fsr->ReleaseBuffers();
  508. }
  509. }
  510. const std::array ortho_matrix =
  511. MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
  512. const auto fragment_handle = [this]() {
  513. switch (Settings::values.scaling_filter.GetValue()) {
  514. case Settings::ScalingFilter::NearestNeighbor:
  515. case Settings::ScalingFilter::Bilinear:
  516. return present_bilinear_fragment.handle;
  517. case Settings::ScalingFilter::Bicubic:
  518. return present_bicubic_fragment.handle;
  519. case Settings::ScalingFilter::Gaussian:
  520. return present_gaussian_fragment.handle;
  521. case Settings::ScalingFilter::ScaleForce:
  522. return present_scaleforce_fragment.handle;
  523. case Settings::ScalingFilter::Fsr:
  524. return fsr->GetPresentFragmentProgram().handle;
  525. default:
  526. return present_bilinear_fragment.handle;
  527. }
  528. }();
  529. program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
  530. glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
  531. ortho_matrix.data());
  532. const auto& texcoords = screen_info.display_texcoords;
  533. auto left = texcoords.left;
  534. auto right = texcoords.right;
  535. if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) {
  536. if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) {
  537. // Flip the framebuffer vertically
  538. left = texcoords.right;
  539. right = texcoords.left;
  540. } else {
  541. // Other transformations are unsupported
  542. LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}",
  543. framebuffer_transform_flags);
  544. UNIMPLEMENTED();
  545. }
  546. }
  547. ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented");
  548. f32 left_start{};
  549. if (framebuffer_crop_rect.Top() > 0) {
  550. left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
  551. static_cast<f32>(framebuffer_crop_rect.Bottom());
  552. }
  553. f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width);
  554. f32 scale_v =
  555. static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height);
  556. if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) {
  557. // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
  558. // (e.g. handheld mode) on a 1920x1080 framebuffer.
  559. if (framebuffer_crop_rect.GetWidth() > 0) {
  560. scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
  561. static_cast<f32>(screen_info.texture.width);
  562. }
  563. if (framebuffer_crop_rect.GetHeight() > 0) {
  564. scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
  565. static_cast<f32>(screen_info.texture.height);
  566. }
  567. }
  568. if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa &&
  569. !screen_info.was_accelerated) {
  570. scale_u /= Settings::values.resolution_info.up_factor;
  571. scale_v /= Settings::values.resolution_info.up_factor;
  572. }
  573. const auto& screen = layout.screen;
  574. const std::array vertices = {
  575. ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u,
  576. left_start + left * scale_v),
  577. ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u,
  578. left_start + left * scale_v),
  579. ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u,
  580. left_start + right * scale_v),
  581. ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u,
  582. left_start + right * scale_v),
  583. };
  584. glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
  585. glDisable(GL_FRAMEBUFFER_SRGB);
  586. glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
  587. static_cast<GLfloat>(layout.height));
  588. glEnableVertexAttribArray(PositionLocation);
  589. glEnableVertexAttribArray(TexCoordLocation);
  590. glVertexAttribDivisor(PositionLocation, 0);
  591. glVertexAttribDivisor(TexCoordLocation, 0);
  592. glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
  593. offsetof(ScreenRectVertex, position));
  594. glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
  595. offsetof(ScreenRectVertex, tex_coord));
  596. glVertexAttribBinding(PositionLocation, 0);
  597. glVertexAttribBinding(TexCoordLocation, 0);
  598. if (device.HasVertexBufferUnifiedMemory()) {
  599. glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
  600. glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
  601. sizeof(vertices));
  602. } else {
  603. glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
  604. }
  605. if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
  606. glBindSampler(0, present_sampler.handle);
  607. } else {
  608. glBindSampler(0, present_sampler_nn.handle);
  609. }
  610. // Update background color before drawing
  611. glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
  612. Settings::values.bg_green.GetValue() / 255.0f,
  613. Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
  614. glClear(GL_COLOR_BUFFER_BIT);
  615. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  616. // TODO
  617. // program_manager.RestoreGuestPipeline();
  618. }
  619. void RendererOpenGL::RenderScreenshot() {
  620. if (!renderer_settings.screenshot_requested) {
  621. return;
  622. }
  623. GLint old_read_fb;
  624. GLint old_draw_fb;
  625. glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
  626. glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
  627. // Draw the current frame to the screenshot framebuffer
  628. screenshot_framebuffer.Create();
  629. glBindFramebuffer(GL_FRAMEBUFFER, screenshot_framebuffer.handle);
  630. const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
  631. GLuint renderbuffer;
  632. glGenRenderbuffers(1, &renderbuffer);
  633. glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
  634. glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
  635. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
  636. DrawScreen(layout);
  637. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  638. glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  639. glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
  640. renderer_settings.screenshot_bits);
  641. screenshot_framebuffer.Release();
  642. glDeleteRenderbuffers(1, &renderbuffer);
  643. glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
  644. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
  645. renderer_settings.screenshot_complete_callback(true);
  646. renderer_settings.screenshot_requested = false;
  647. }
  648. } // namespace OpenGL