gl_rasterizer.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. // SPDX-FileCopyrightText: 2015 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <array>
  5. #include <bitset>
  6. #include <memory>
  7. #include <string_view>
  8. #include <utility>
  9. #include <glad/glad.h>
  10. #include "common/assert.h"
  11. #include "common/logging/log.h"
  12. #include "common/math_util.h"
  13. #include "common/microprofile.h"
  14. #include "common/scope_exit.h"
  15. #include "common/settings.h"
  16. #include "video_core/control/channel_state.h"
  17. #include "video_core/engines/kepler_compute.h"
  18. #include "video_core/engines/maxwell_3d.h"
  19. #include "video_core/memory_manager.h"
  20. #include "video_core/renderer_opengl/gl_device.h"
  21. #include "video_core/renderer_opengl/gl_query_cache.h"
  22. #include "video_core/renderer_opengl/gl_rasterizer.h"
  23. #include "video_core/renderer_opengl/gl_shader_cache.h"
  24. #include "video_core/renderer_opengl/gl_staging_buffer_pool.h"
  25. #include "video_core/renderer_opengl/gl_texture_cache.h"
  26. #include "video_core/renderer_opengl/maxwell_to_gl.h"
  27. #include "video_core/renderer_opengl/renderer_opengl.h"
  28. #include "video_core/shader_cache.h"
  29. #include "video_core/texture_cache/texture_cache_base.h"
  30. namespace OpenGL {
  31. using Maxwell = Tegra::Engines::Maxwell3D::Regs;
  32. using GLvec4 = std::array<GLfloat, 4>;
  33. using VideoCore::Surface::PixelFormat;
  34. using VideoCore::Surface::SurfaceTarget;
  35. using VideoCore::Surface::SurfaceType;
  36. MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
  37. MICROPROFILE_DEFINE(OpenGL_Clears, "OpenGL", "Clears", MP_RGB(128, 128, 192));
  38. MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(128, 128, 192));
  39. MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB(100, 255, 100));
  40. namespace {
  41. constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16;
  42. void oglEnable(GLenum cap, bool state) {
  43. (state ? glEnable : glDisable)(cap);
  44. }
  45. std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryType type) {
  46. switch (type) {
  47. case VideoCommon::QueryType::PrimitivesGenerated:
  48. case VideoCommon::QueryType::VtgPrimitivesOut:
  49. return VideoCore::QueryType::PrimitivesGenerated;
  50. case VideoCommon::QueryType::ZPassPixelCount64:
  51. return VideoCore::QueryType::SamplesPassed;
  52. case VideoCommon::QueryType::StreamingPrimitivesSucceeded:
  53. // case VideoCommon::QueryType::StreamingByteCount:
  54. // TODO: StreamingByteCount = StreamingPrimitivesSucceeded * num_verts * vert_stride
  55. return VideoCore::QueryType::TfbPrimitivesWritten;
  56. default:
  57. return std::nullopt;
  58. }
  59. }
  60. } // Anonymous namespace
  61. RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
  62. Core::Memory::Memory& cpu_memory_, const Device& device_,
  63. ScreenInfo& screen_info_, ProgramManager& program_manager_,
  64. StateTracker& state_tracker_)
  65. : RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_), screen_info(screen_info_),
  66. program_manager(program_manager_), state_tracker(state_tracker_),
  67. texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
  68. texture_cache(texture_cache_runtime, *this),
  69. buffer_cache_runtime(device, staging_buffer_pool),
  70. buffer_cache(*this, cpu_memory_, buffer_cache_runtime),
  71. shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager,
  72. state_tracker, gpu.ShaderNotify()),
  73. query_cache(*this, cpu_memory_), accelerate_dma(buffer_cache, texture_cache),
  74. fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache),
  75. blit_image(program_manager_) {}
  76. RasterizerOpenGL::~RasterizerOpenGL() = default;
  77. void RasterizerOpenGL::SyncVertexFormats() {
  78. auto& flags = maxwell3d->dirty.flags;
  79. if (!flags[Dirty::VertexFormats]) {
  80. return;
  81. }
  82. flags[Dirty::VertexFormats] = false;
  83. // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. Enables
  84. // the first 16 vertex attributes always, as we don't know which ones are actually used until
  85. // shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now to
  86. // avoid OpenGL errors.
  87. // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
  88. // assume every shader uses them all.
  89. for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) {
  90. if (!flags[Dirty::VertexFormat0 + index]) {
  91. continue;
  92. }
  93. flags[Dirty::VertexFormat0 + index] = false;
  94. const auto& attrib = maxwell3d->regs.vertex_attrib_format[index];
  95. const auto gl_index = static_cast<GLuint>(index);
  96. // Disable constant attributes.
  97. if (attrib.constant) {
  98. glDisableVertexAttribArray(gl_index);
  99. continue;
  100. }
  101. glEnableVertexAttribArray(gl_index);
  102. if (attrib.type == Maxwell::VertexAttribute::Type::SInt ||
  103. attrib.type == Maxwell::VertexAttribute::Type::UInt) {
  104. glVertexAttribIFormat(gl_index, attrib.ComponentCount(),
  105. MaxwellToGL::VertexFormat(attrib), attrib.offset);
  106. } else {
  107. glVertexAttribFormat(gl_index, attrib.ComponentCount(),
  108. MaxwellToGL::VertexFormat(attrib),
  109. attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
  110. }
  111. glVertexAttribBinding(gl_index, attrib.buffer);
  112. }
  113. }
  114. void RasterizerOpenGL::SyncVertexInstances() {
  115. auto& flags = maxwell3d->dirty.flags;
  116. if (!flags[Dirty::VertexInstances]) {
  117. return;
  118. }
  119. flags[Dirty::VertexInstances] = false;
  120. const auto& regs = maxwell3d->regs;
  121. for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) {
  122. if (!flags[Dirty::VertexInstance0 + index]) {
  123. continue;
  124. }
  125. flags[Dirty::VertexInstance0 + index] = false;
  126. const auto gl_index = static_cast<GLuint>(index);
  127. const bool instancing_enabled = regs.vertex_stream_instances.IsInstancingEnabled(gl_index);
  128. const GLuint divisor = instancing_enabled ? regs.vertex_streams[index].frequency : 0;
  129. glVertexBindingDivisor(gl_index, divisor);
  130. }
  131. }
  132. void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
  133. const VideoCore::DiskResourceLoadCallback& callback) {
  134. shader_cache.LoadDiskResources(title_id, stop_loading, callback);
  135. }
  136. void RasterizerOpenGL::Clear(u32 layer_count) {
  137. MICROPROFILE_SCOPE(OpenGL_Clears);
  138. gpu_memory->FlushCaching();
  139. const auto& regs = maxwell3d->regs;
  140. bool use_color{};
  141. bool use_depth{};
  142. bool use_stencil{};
  143. if (regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
  144. regs.clear_surface.A) {
  145. use_color = true;
  146. const GLuint index = regs.clear_surface.RT;
  147. state_tracker.NotifyColorMask(index);
  148. glColorMaski(index, regs.clear_surface.R != 0, regs.clear_surface.G != 0,
  149. regs.clear_surface.B != 0, regs.clear_surface.A != 0);
  150. // TODO(Rodrigo): Determine if clamping is used on clears
  151. SyncFragmentColorClampState();
  152. SyncFramebufferSRGB();
  153. }
  154. if (regs.clear_surface.Z) {
  155. if (regs.zeta_enable != 0) {
  156. LOG_DEBUG(Render_OpenGL, "Tried to clear Z but buffer is not enabled!");
  157. }
  158. use_depth = true;
  159. state_tracker.NotifyDepthMask();
  160. glDepthMask(GL_TRUE);
  161. }
  162. if (regs.clear_surface.S) {
  163. if (regs.zeta_enable) {
  164. LOG_DEBUG(Render_OpenGL, "Tried to clear stencil but buffer is not enabled!");
  165. }
  166. use_stencil = true;
  167. }
  168. if (!use_color && !use_depth && !use_stencil) {
  169. // No color surface nor depth/stencil surface are enabled
  170. return;
  171. }
  172. SyncRasterizeEnable();
  173. SyncStencilTestState();
  174. std::scoped_lock lock{texture_cache.mutex};
  175. texture_cache.UpdateRenderTargets(true);
  176. state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
  177. SyncViewport();
  178. if (regs.clear_control.use_scissor) {
  179. SyncScissorTest();
  180. } else {
  181. state_tracker.NotifyScissor0();
  182. glDisablei(GL_SCISSOR_TEST, 0);
  183. }
  184. UNIMPLEMENTED_IF(regs.clear_control.use_viewport_clip0);
  185. if (use_color) {
  186. glClearBufferfv(GL_COLOR, regs.clear_surface.RT, regs.clear_color.data());
  187. }
  188. if (use_depth && use_stencil) {
  189. glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
  190. } else if (use_depth) {
  191. glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
  192. } else if (use_stencil) {
  193. glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
  194. }
  195. ++num_queued_commands;
  196. }
  197. template <typename Func>
  198. void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
  199. MICROPROFILE_SCOPE(OpenGL_Drawing);
  200. SCOPE_EXIT({ gpu.TickWork(); });
  201. gpu_memory->FlushCaching();
  202. GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()};
  203. if (!pipeline) {
  204. return;
  205. }
  206. gpu.TickWork();
  207. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  208. if (pipeline->UsesLocalMemory()) {
  209. program_manager.LocalMemoryWarmup();
  210. }
  211. pipeline->SetEngine(maxwell3d, gpu_memory);
  212. pipeline->Configure(is_indexed);
  213. SyncState();
  214. const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
  215. const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology);
  216. BeginTransformFeedback(pipeline, primitive_mode);
  217. draw_func(primitive_mode);
  218. EndTransformFeedback();
  219. ++num_queued_commands;
  220. has_written_global_memory |= pipeline->WritesGlobalMemory();
  221. }
  222. void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
  223. PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) {
  224. const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
  225. const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance);
  226. const GLsizei num_instances = static_cast<GLsizei>(instance_count);
  227. if (is_indexed) {
  228. const GLint base_vertex = static_cast<GLint>(draw_state.base_index);
  229. const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count);
  230. const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
  231. const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format);
  232. if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
  233. glDrawElements(primitive_mode, num_vertices, format, offset);
  234. } else if (num_instances == 1 && base_instance == 0) {
  235. glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex);
  236. } else if (base_vertex == 0 && base_instance == 0) {
  237. glDrawElementsInstanced(primitive_mode, num_vertices, format, offset,
  238. num_instances);
  239. } else if (base_vertex == 0) {
  240. glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset,
  241. num_instances, base_instance);
  242. } else if (base_instance == 0) {
  243. glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset,
  244. num_instances, base_vertex);
  245. } else {
  246. glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format,
  247. offset, num_instances, base_vertex,
  248. base_instance);
  249. }
  250. } else {
  251. const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first);
  252. const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count);
  253. if (num_instances == 1 && base_instance == 0) {
  254. glDrawArrays(primitive_mode, base_vertex, num_vertices);
  255. } else if (base_instance == 0) {
  256. glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances);
  257. } else {
  258. glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices,
  259. num_instances, base_instance);
  260. }
  261. }
  262. });
  263. }
  264. void RasterizerOpenGL::DrawIndirect() {
  265. const auto& params = maxwell3d->draw_manager->GetIndirectParams();
  266. buffer_cache.SetDrawIndirect(&params);
  267. PrepareDraw(params.is_indexed, [this, &params](GLenum primitive_mode) {
  268. const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
  269. const GLvoid* const gl_offset =
  270. reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset));
  271. glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle());
  272. if (params.include_count) {
  273. const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount();
  274. glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle());
  275. if (params.is_indexed) {
  276. const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
  277. glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset,
  278. static_cast<GLintptr>(offset_base),
  279. static_cast<GLsizei>(params.max_draw_counts),
  280. static_cast<GLsizei>(params.stride));
  281. } else {
  282. glMultiDrawArraysIndirectCount(primitive_mode, gl_offset,
  283. static_cast<GLintptr>(offset_base),
  284. static_cast<GLsizei>(params.max_draw_counts),
  285. static_cast<GLsizei>(params.stride));
  286. }
  287. return;
  288. }
  289. if (params.is_indexed) {
  290. const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
  291. glMultiDrawElementsIndirect(primitive_mode, format, gl_offset,
  292. static_cast<GLsizei>(params.max_draw_counts),
  293. static_cast<GLsizei>(params.stride));
  294. } else {
  295. glMultiDrawArraysIndirect(primitive_mode, gl_offset,
  296. static_cast<GLsizei>(params.max_draw_counts),
  297. static_cast<GLsizei>(params.stride));
  298. }
  299. });
  300. buffer_cache.SetDrawIndirect(nullptr);
  301. }
  302. void RasterizerOpenGL::DrawTexture() {
  303. MICROPROFILE_SCOPE(OpenGL_Drawing);
  304. SCOPE_EXIT({ gpu.TickWork(); });
  305. texture_cache.SynchronizeGraphicsDescriptors();
  306. texture_cache.UpdateRenderTargets(false);
  307. SyncState();
  308. const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
  309. const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
  310. const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
  311. if (device.HasDrawTexture()) {
  312. state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
  313. glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(), draw_texture_state.dst_x0,
  314. draw_texture_state.dst_y0, draw_texture_state.dst_x1,
  315. draw_texture_state.dst_y1, 0,
  316. draw_texture_state.src_x0 / static_cast<float>(texture.size.width),
  317. draw_texture_state.src_y0 / static_cast<float>(texture.size.height),
  318. draw_texture_state.src_x1 / static_cast<float>(texture.size.width),
  319. draw_texture_state.src_y1 / static_cast<float>(texture.size.height));
  320. } else {
  321. Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0),
  322. .y = static_cast<s32>(draw_texture_state.dst_y0)},
  323. Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1),
  324. .y = static_cast<s32>(draw_texture_state.dst_y1)}};
  325. Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0),
  326. .y = static_cast<s32>(draw_texture_state.src_y0)},
  327. Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1),
  328. .y = static_cast<s32>(draw_texture_state.src_y1)}};
  329. blit_image.BlitColor(texture_cache.GetFramebuffer()->Handle(), texture.DefaultHandle(),
  330. sampler->Handle(), dst_region, src_region, texture.size);
  331. state_tracker.InvalidateState();
  332. }
  333. ++num_queued_commands;
  334. }
  335. void RasterizerOpenGL::DispatchCompute() {
  336. gpu_memory->FlushCaching();
  337. ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
  338. if (!pipeline) {
  339. return;
  340. }
  341. if (pipeline->UsesLocalMemory()) {
  342. program_manager.LocalMemoryWarmup();
  343. }
  344. pipeline->SetEngine(kepler_compute, gpu_memory);
  345. pipeline->Configure();
  346. const auto& qmd{kepler_compute->launch_description};
  347. auto indirect_address = kepler_compute->GetIndirectComputeAddress();
  348. if (indirect_address) {
  349. // DispatchIndirect
  350. static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
  351. const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
  352. const auto [buffer, offset] =
  353. buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
  354. glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->Handle());
  355. glDispatchComputeIndirect(static_cast<GLintptr>(offset));
  356. return;
  357. }
  358. glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
  359. ++num_queued_commands;
  360. has_written_global_memory |= pipeline->WritesGlobalMemory();
  361. }
  362. void RasterizerOpenGL::ResetCounter(VideoCommon::QueryType type) {
  363. const auto query_cache_type = MaxwellToVideoCoreQuery(type);
  364. if (!query_cache_type.has_value()) {
  365. UNIMPLEMENTED_IF_MSG(type != VideoCommon::QueryType::Payload, "Reset query type: {}", type);
  366. return;
  367. }
  368. query_cache.ResetCounter(*query_cache_type);
  369. }
  370. void RasterizerOpenGL::Query(GPUVAddr gpu_addr, VideoCommon::QueryType type,
  371. VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport) {
  372. const auto query_cache_type = MaxwellToVideoCoreQuery(type);
  373. if (!query_cache_type.has_value()) {
  374. return QueryFallback(gpu_addr, type, flags, payload, subreport);
  375. }
  376. const bool has_timeout = True(flags & VideoCommon::QueryPropertiesFlags::HasTimeout);
  377. const auto timestamp = has_timeout ? std::optional<u64>{gpu.GetTicks()} : std::nullopt;
  378. query_cache.Query(gpu_addr, *query_cache_type, timestamp);
  379. }
  380. void RasterizerOpenGL::QueryFallback(GPUVAddr gpu_addr, VideoCommon::QueryType type,
  381. VideoCommon::QueryPropertiesFlags flags, u32 payload,
  382. u32 subreport) {
  383. if (type != VideoCommon::QueryType::Payload) {
  384. payload = 1u;
  385. }
  386. std::function<void()> func([this, gpu_addr, flags, memory_manager = gpu_memory, payload]() {
  387. if (True(flags & VideoCommon::QueryPropertiesFlags::HasTimeout)) {
  388. u64 ticks = gpu.GetTicks();
  389. memory_manager->Write<u64>(gpu_addr + 8, ticks);
  390. memory_manager->Write<u64>(gpu_addr, static_cast<u64>(payload));
  391. } else {
  392. memory_manager->Write<u32>(gpu_addr, payload);
  393. }
  394. });
  395. if (True(flags & VideoCommon::QueryPropertiesFlags::IsAFence)) {
  396. SignalFence(std::move(func));
  397. return;
  398. }
  399. func();
  400. }
  401. void RasterizerOpenGL::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
  402. u32 size) {
  403. std::scoped_lock lock{buffer_cache.mutex};
  404. buffer_cache.BindGraphicsUniformBuffer(stage, index, gpu_addr, size);
  405. }
  406. void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
  407. buffer_cache.DisableGraphicsUniformBuffer(stage, index);
  408. }
  409. void RasterizerOpenGL::FlushAll() {}
  410. void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) {
  411. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  412. if (addr == 0 || size == 0) {
  413. return;
  414. }
  415. if (True(which & VideoCommon::CacheType::TextureCache)) {
  416. std::scoped_lock lock{texture_cache.mutex};
  417. texture_cache.DownloadMemory(addr, size);
  418. }
  419. if ((True(which & VideoCommon::CacheType::BufferCache))) {
  420. std::scoped_lock lock{buffer_cache.mutex};
  421. buffer_cache.DownloadMemory(addr, size);
  422. }
  423. if ((True(which & VideoCommon::CacheType::QueryCache))) {
  424. query_cache.FlushRegion(addr, size);
  425. }
  426. }
  427. bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) {
  428. if ((True(which & VideoCommon::CacheType::BufferCache))) {
  429. std::scoped_lock lock{buffer_cache.mutex};
  430. if (buffer_cache.IsRegionGpuModified(addr, size)) {
  431. return true;
  432. }
  433. }
  434. if (!Settings::IsGPULevelHigh()) {
  435. return false;
  436. }
  437. if (True(which & VideoCommon::CacheType::TextureCache)) {
  438. std::scoped_lock lock{texture_cache.mutex};
  439. return texture_cache.IsRegionGpuModified(addr, size);
  440. }
  441. return false;
  442. }
  443. VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(VAddr addr, u64 size) {
  444. {
  445. std::scoped_lock lock{texture_cache.mutex};
  446. auto area = texture_cache.GetFlushArea(addr, size);
  447. if (area) {
  448. return *area;
  449. }
  450. }
  451. {
  452. std::scoped_lock lock{buffer_cache.mutex};
  453. auto area = buffer_cache.GetFlushArea(addr, size);
  454. if (area) {
  455. return *area;
  456. }
  457. }
  458. VideoCore::RasterizerDownloadArea new_area{
  459. .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE),
  460. .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE),
  461. .preemtive = true,
  462. };
  463. return new_area;
  464. }
  465. void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) {
  466. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  467. if (addr == 0 || size == 0) {
  468. return;
  469. }
  470. if (True(which & VideoCommon::CacheType::TextureCache)) {
  471. std::scoped_lock lock{texture_cache.mutex};
  472. texture_cache.WriteMemory(addr, size);
  473. }
  474. if (True(which & VideoCommon::CacheType::BufferCache)) {
  475. std::scoped_lock lock{buffer_cache.mutex};
  476. buffer_cache.WriteMemory(addr, size);
  477. }
  478. if (True(which & VideoCommon::CacheType::ShaderCache)) {
  479. shader_cache.InvalidateRegion(addr, size);
  480. }
  481. if (True(which & VideoCommon::CacheType::QueryCache)) {
  482. query_cache.InvalidateRegion(addr, size);
  483. }
  484. }
  485. bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
  486. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  487. if (addr == 0 || size == 0) {
  488. return false;
  489. }
  490. {
  491. std::scoped_lock lock{buffer_cache.mutex};
  492. if (buffer_cache.OnCPUWrite(addr, size)) {
  493. return true;
  494. }
  495. }
  496. {
  497. std::scoped_lock lock{texture_cache.mutex};
  498. texture_cache.WriteMemory(addr, size);
  499. }
  500. shader_cache.InvalidateRegion(addr, size);
  501. return false;
  502. }
  503. void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) {
  504. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  505. if (addr == 0 || size == 0) {
  506. return;
  507. }
  508. {
  509. std::scoped_lock lock{texture_cache.mutex};
  510. texture_cache.WriteMemory(addr, size);
  511. }
  512. {
  513. std::scoped_lock lock{buffer_cache.mutex};
  514. buffer_cache.WriteMemory(addr, size);
  515. }
  516. shader_cache.InvalidateRegion(addr, size);
  517. }
  518. void RasterizerOpenGL::InvalidateGPUCache() {
  519. gpu.InvalidateGPUCache();
  520. }
  521. void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) {
  522. {
  523. std::scoped_lock lock{texture_cache.mutex};
  524. texture_cache.UnmapMemory(addr, size);
  525. }
  526. {
  527. std::scoped_lock lock{buffer_cache.mutex};
  528. buffer_cache.WriteMemory(addr, size);
  529. }
  530. shader_cache.OnCacheInvalidation(addr, size);
  531. }
  532. void RasterizerOpenGL::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {
  533. {
  534. std::scoped_lock lock{texture_cache.mutex};
  535. texture_cache.UnmapGPUMemory(as_id, addr, size);
  536. }
  537. }
  538. void RasterizerOpenGL::SignalFence(std::function<void()>&& func) {
  539. fence_manager.SignalFence(std::move(func));
  540. }
  541. void RasterizerOpenGL::SyncOperation(std::function<void()>&& func) {
  542. fence_manager.SyncOperation(std::move(func));
  543. }
  544. void RasterizerOpenGL::SignalSyncPoint(u32 value) {
  545. fence_manager.SignalSyncPoint(value);
  546. }
  547. void RasterizerOpenGL::SignalReference() {
  548. fence_manager.SignalOrdering();
  549. }
  550. void RasterizerOpenGL::ReleaseFences(bool force) {
  551. fence_manager.WaitPendingFences(force);
  552. }
  553. void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size,
  554. VideoCommon::CacheType which) {
  555. if (Settings::IsGPULevelExtreme()) {
  556. FlushRegion(addr, size, which);
  557. }
  558. InvalidateRegion(addr, size, which);
  559. }
  560. void RasterizerOpenGL::WaitForIdle() {
  561. glMemoryBarrier(GL_ALL_BARRIER_BITS);
  562. SignalReference();
  563. }
  564. void RasterizerOpenGL::FragmentBarrier() {
  565. glTextureBarrier();
  566. glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
  567. }
  568. void RasterizerOpenGL::TiledCacheBarrier() {
  569. glTextureBarrier();
  570. }
  571. void RasterizerOpenGL::FlushCommands() {
  572. // Only flush when we have commands queued to OpenGL.
  573. if (num_queued_commands == 0) {
  574. return;
  575. }
  576. num_queued_commands = 0;
  577. // Make sure memory stored from the previous GL command stream is visible
  578. // This is only needed on assembly shaders where we write to GPU memory with raw pointers
  579. if (has_written_global_memory) {
  580. has_written_global_memory = false;
  581. glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
  582. }
  583. glFlush();
  584. }
  585. void RasterizerOpenGL::TickFrame() {
  586. // Ticking a frame means that buffers will be swapped, calling glFlush implicitly.
  587. num_queued_commands = 0;
  588. fence_manager.TickFrame();
  589. {
  590. std::scoped_lock lock{texture_cache.mutex};
  591. texture_cache.TickFrame();
  592. }
  593. {
  594. std::scoped_lock lock{buffer_cache.mutex};
  595. buffer_cache.TickFrame();
  596. }
  597. }
  598. bool RasterizerOpenGL::AccelerateConditionalRendering() {
  599. gpu_memory->FlushCaching();
  600. if (Settings::IsGPULevelHigh()) {
  601. // Reimplement Host conditional rendering.
  602. return false;
  603. }
  604. // Medium / Low Hack: stub any checks on queries written into the buffer cache.
  605. const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()};
  606. Maxwell::ReportSemaphore::Compare cmp;
  607. if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp),
  608. VideoCommon::CacheType::BufferCache)) {
  609. return true;
  610. }
  611. return false;
  612. }
  613. bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
  614. const Tegra::Engines::Fermi2D::Surface& dst,
  615. const Tegra::Engines::Fermi2D::Config& copy_config) {
  616. MICROPROFILE_SCOPE(OpenGL_Blits);
  617. std::scoped_lock lock{texture_cache.mutex};
  618. return texture_cache.BlitImage(dst, src, copy_config);
  619. }
  620. Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA() {
  621. return accelerate_dma;
  622. }
  623. void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
  624. std::span<const u8> memory) {
  625. auto cpu_addr = gpu_memory->GpuToCpuAddress(address);
  626. if (!cpu_addr) [[unlikely]] {
  627. gpu_memory->WriteBlock(address, memory.data(), copy_size);
  628. return;
  629. }
  630. gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size);
  631. {
  632. std::unique_lock<std::recursive_mutex> lock{buffer_cache.mutex};
  633. if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
  634. buffer_cache.WriteMemory(*cpu_addr, copy_size);
  635. }
  636. }
  637. {
  638. std::scoped_lock lock_texture{texture_cache.mutex};
  639. texture_cache.WriteMemory(*cpu_addr, copy_size);
  640. }
  641. shader_cache.InvalidateRegion(*cpu_addr, copy_size);
  642. query_cache.InvalidateRegion(*cpu_addr, copy_size);
  643. }
  644. bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
  645. VAddr framebuffer_addr, u32 pixel_stride) {
  646. if (framebuffer_addr == 0) {
  647. return false;
  648. }
  649. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  650. std::scoped_lock lock{texture_cache.mutex};
  651. ImageView* const image_view{
  652. texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
  653. if (!image_view) {
  654. return false;
  655. }
  656. // Verify that the cached surface is the same size and format as the requested framebuffer
  657. // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
  658. // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
  659. screen_info.texture.width = image_view->size.width;
  660. screen_info.texture.height = image_view->size.height;
  661. screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
  662. return true;
  663. }
  664. void RasterizerOpenGL::SyncState() {
  665. SyncViewport();
  666. SyncRasterizeEnable();
  667. SyncPolygonModes();
  668. SyncColorMask();
  669. SyncFragmentColorClampState();
  670. SyncMultiSampleState();
  671. SyncDepthTestState();
  672. SyncDepthClamp();
  673. SyncStencilTestState();
  674. SyncBlendState();
  675. SyncLogicOpState();
  676. SyncCullMode();
  677. SyncPrimitiveRestart();
  678. SyncScissorTest();
  679. SyncPointState();
  680. SyncLineState();
  681. SyncPolygonOffset();
  682. SyncAlphaTest();
  683. SyncFramebufferSRGB();
  684. SyncVertexFormats();
  685. SyncVertexInstances();
  686. }
  687. void RasterizerOpenGL::SyncViewport() {
  688. auto& flags = maxwell3d->dirty.flags;
  689. const auto& regs = maxwell3d->regs;
  690. const bool rescale_viewports = flags[VideoCommon::Dirty::RescaleViewports];
  691. const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports;
  692. const bool dirty_clip_control = flags[Dirty::ClipControl];
  693. if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) {
  694. flags[Dirty::FrontFace] = false;
  695. GLenum mode = MaxwellToGL::FrontFace(regs.gl_front_face);
  696. bool flip_faces = true;
  697. if (regs.window_origin.flip_y != 0) {
  698. flip_faces = !flip_faces;
  699. }
  700. if (regs.viewport_transform[0].scale_y < 0.0f) {
  701. flip_faces = !flip_faces;
  702. }
  703. if (flip_faces) {
  704. switch (mode) {
  705. case GL_CW:
  706. mode = GL_CCW;
  707. break;
  708. case GL_CCW:
  709. mode = GL_CW;
  710. break;
  711. }
  712. }
  713. glFrontFace(mode);
  714. }
  715. if (dirty_viewport || dirty_clip_control) {
  716. flags[Dirty::ClipControl] = false;
  717. bool flip_y = false;
  718. if (regs.viewport_transform[0].scale_y < 0.0f) {
  719. flip_y = !flip_y;
  720. }
  721. const bool lower_left{regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft};
  722. if (lower_left) {
  723. flip_y = !flip_y;
  724. }
  725. const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
  726. const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
  727. const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
  728. state_tracker.ClipControl(origin, depth);
  729. state_tracker.SetYNegate(lower_left);
  730. }
  731. const bool is_rescaling{texture_cache.IsRescaling()};
  732. const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
  733. const auto conv = [scale](float value) -> GLfloat {
  734. float new_value = value * scale;
  735. if (scale < 1.0f) {
  736. const bool sign = std::signbit(value);
  737. new_value = std::round(std::abs(new_value));
  738. new_value = sign ? -new_value : new_value;
  739. }
  740. return static_cast<GLfloat>(new_value);
  741. };
  742. if (dirty_viewport) {
  743. flags[Dirty::Viewports] = false;
  744. const bool force = flags[Dirty::ViewportTransform] || rescale_viewports;
  745. flags[Dirty::ViewportTransform] = false;
  746. flags[VideoCommon::Dirty::RescaleViewports] = false;
  747. for (size_t index = 0; index < Maxwell::NumViewports; ++index) {
  748. if (!force && !flags[Dirty::Viewport0 + index]) {
  749. continue;
  750. }
  751. flags[Dirty::Viewport0 + index] = false;
  752. if (!regs.viewport_scale_offset_enabled) {
  753. const auto x = static_cast<GLfloat>(regs.surface_clip.x);
  754. const auto y = static_cast<GLfloat>(regs.surface_clip.y);
  755. const auto width = static_cast<GLfloat>(regs.surface_clip.width);
  756. const auto height = static_cast<GLfloat>(regs.surface_clip.height);
  757. glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
  758. height != 0.0f ? height : 1.0f);
  759. continue;
  760. }
  761. const auto& src = regs.viewport_transform[index];
  762. GLfloat x = conv(src.translate_x - src.scale_x);
  763. GLfloat y = conv(src.translate_y - src.scale_y);
  764. GLfloat width = conv(src.scale_x * 2.0f);
  765. GLfloat height = conv(src.scale_y * 2.0f);
  766. if (height < 0) {
  767. y += height;
  768. height = -height;
  769. }
  770. glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
  771. height != 0.0f ? height : 1.0f);
  772. const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
  773. const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
  774. const GLdouble far_depth = src.translate_z + src.scale_z;
  775. if (device.HasDepthBufferFloat()) {
  776. glDepthRangeIndexeddNV(static_cast<GLuint>(index), near_depth, far_depth);
  777. } else {
  778. glDepthRangeIndexed(static_cast<GLuint>(index), near_depth, far_depth);
  779. }
  780. if (!GLAD_GL_NV_viewport_swizzle) {
  781. continue;
  782. }
  783. glViewportSwizzleNV(static_cast<GLuint>(index),
  784. MaxwellToGL::ViewportSwizzle(src.swizzle.x),
  785. MaxwellToGL::ViewportSwizzle(src.swizzle.y),
  786. MaxwellToGL::ViewportSwizzle(src.swizzle.z),
  787. MaxwellToGL::ViewportSwizzle(src.swizzle.w));
  788. }
  789. }
  790. }
  791. void RasterizerOpenGL::SyncDepthClamp() {
  792. auto& flags = maxwell3d->dirty.flags;
  793. if (!flags[Dirty::DepthClampEnabled]) {
  794. return;
  795. }
  796. flags[Dirty::DepthClampEnabled] = false;
  797. bool depth_clamp_disabled{maxwell3d->regs.viewport_clip_control.geometry_clip ==
  798. Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
  799. maxwell3d->regs.viewport_clip_control.geometry_clip ==
  800. Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
  801. maxwell3d->regs.viewport_clip_control.geometry_clip ==
  802. Maxwell::ViewportClipControl::GeometryClip::FrustumZ};
  803. oglEnable(GL_DEPTH_CLAMP, !depth_clamp_disabled);
  804. }
  805. void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
  806. auto& flags = maxwell3d->dirty.flags;
  807. if (!flags[Dirty::ClipDistances] && !flags[VideoCommon::Dirty::Shaders]) {
  808. return;
  809. }
  810. flags[Dirty::ClipDistances] = false;
  811. clip_mask &= maxwell3d->regs.user_clip_enable.raw;
  812. if (clip_mask == last_clip_distance_mask) {
  813. return;
  814. }
  815. last_clip_distance_mask = clip_mask;
  816. for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) {
  817. oglEnable(static_cast<GLenum>(GL_CLIP_DISTANCE0 + i), (clip_mask >> i) & 1);
  818. }
  819. }
  820. void RasterizerOpenGL::SyncClipCoef() {
  821. UNIMPLEMENTED();
  822. }
  823. void RasterizerOpenGL::SyncCullMode() {
  824. auto& flags = maxwell3d->dirty.flags;
  825. const auto& regs = maxwell3d->regs;
  826. if (flags[Dirty::CullTest]) {
  827. flags[Dirty::CullTest] = false;
  828. if (regs.gl_cull_test_enabled) {
  829. glEnable(GL_CULL_FACE);
  830. glCullFace(MaxwellToGL::CullFace(regs.gl_cull_face));
  831. } else {
  832. glDisable(GL_CULL_FACE);
  833. }
  834. }
  835. }
  836. void RasterizerOpenGL::SyncPrimitiveRestart() {
  837. auto& flags = maxwell3d->dirty.flags;
  838. if (!flags[Dirty::PrimitiveRestart]) {
  839. return;
  840. }
  841. flags[Dirty::PrimitiveRestart] = false;
  842. if (maxwell3d->regs.primitive_restart.enabled) {
  843. glEnable(GL_PRIMITIVE_RESTART);
  844. glPrimitiveRestartIndex(maxwell3d->regs.primitive_restart.index);
  845. } else {
  846. glDisable(GL_PRIMITIVE_RESTART);
  847. }
  848. }
  849. void RasterizerOpenGL::SyncDepthTestState() {
  850. auto& flags = maxwell3d->dirty.flags;
  851. const auto& regs = maxwell3d->regs;
  852. if (flags[Dirty::DepthMask]) {
  853. flags[Dirty::DepthMask] = false;
  854. glDepthMask(regs.depth_write_enabled ? GL_TRUE : GL_FALSE);
  855. }
  856. if (flags[Dirty::DepthTest]) {
  857. flags[Dirty::DepthTest] = false;
  858. if (regs.depth_test_enable) {
  859. glEnable(GL_DEPTH_TEST);
  860. glDepthFunc(MaxwellToGL::ComparisonOp(regs.depth_test_func));
  861. } else {
  862. glDisable(GL_DEPTH_TEST);
  863. }
  864. }
  865. }
  866. void RasterizerOpenGL::SyncStencilTestState() {
  867. auto& flags = maxwell3d->dirty.flags;
  868. if (!flags[Dirty::StencilTest]) {
  869. return;
  870. }
  871. flags[Dirty::StencilTest] = false;
  872. const auto& regs = maxwell3d->regs;
  873. oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
  874. glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
  875. regs.stencil_front_ref, regs.stencil_front_func_mask);
  876. glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op.fail),
  877. MaxwellToGL::StencilOp(regs.stencil_front_op.zfail),
  878. MaxwellToGL::StencilOp(regs.stencil_front_op.zpass));
  879. glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
  880. if (regs.stencil_two_side_enable) {
  881. glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.func),
  882. regs.stencil_back_ref, regs.stencil_back_func_mask);
  883. glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op.fail),
  884. MaxwellToGL::StencilOp(regs.stencil_back_op.zfail),
  885. MaxwellToGL::StencilOp(regs.stencil_back_op.zpass));
  886. glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
  887. } else {
  888. glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
  889. glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
  890. glStencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
  891. }
  892. }
  893. void RasterizerOpenGL::SyncRasterizeEnable() {
  894. auto& flags = maxwell3d->dirty.flags;
  895. if (!flags[Dirty::RasterizeEnable]) {
  896. return;
  897. }
  898. flags[Dirty::RasterizeEnable] = false;
  899. oglEnable(GL_RASTERIZER_DISCARD, maxwell3d->regs.rasterize_enable == 0);
  900. }
  901. void RasterizerOpenGL::SyncPolygonModes() {
  902. auto& flags = maxwell3d->dirty.flags;
  903. if (!flags[Dirty::PolygonModes]) {
  904. return;
  905. }
  906. flags[Dirty::PolygonModes] = false;
  907. const auto& regs = maxwell3d->regs;
  908. if (regs.fill_via_triangle_mode != Maxwell::FillViaTriangleMode::Disabled) {
  909. if (!GLAD_GL_NV_fill_rectangle) {
  910. LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
  911. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  912. return;
  913. }
  914. flags[Dirty::PolygonModeFront] = true;
  915. flags[Dirty::PolygonModeBack] = true;
  916. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
  917. return;
  918. }
  919. if (regs.polygon_mode_front == regs.polygon_mode_back) {
  920. flags[Dirty::PolygonModeFront] = false;
  921. flags[Dirty::PolygonModeBack] = false;
  922. glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  923. return;
  924. }
  925. if (flags[Dirty::PolygonModeFront]) {
  926. flags[Dirty::PolygonModeFront] = false;
  927. glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  928. }
  929. if (flags[Dirty::PolygonModeBack]) {
  930. flags[Dirty::PolygonModeBack] = false;
  931. glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_back));
  932. }
  933. }
  934. void RasterizerOpenGL::SyncColorMask() {
  935. auto& flags = maxwell3d->dirty.flags;
  936. if (!flags[Dirty::ColorMasks]) {
  937. return;
  938. }
  939. flags[Dirty::ColorMasks] = false;
  940. const bool force = flags[Dirty::ColorMaskCommon];
  941. flags[Dirty::ColorMaskCommon] = false;
  942. const auto& regs = maxwell3d->regs;
  943. if (regs.color_mask_common) {
  944. if (!force && !flags[Dirty::ColorMask0]) {
  945. return;
  946. }
  947. flags[Dirty::ColorMask0] = false;
  948. auto& mask = regs.color_mask[0];
  949. glColorMask(mask.R != 0, mask.B != 0, mask.G != 0, mask.A != 0);
  950. return;
  951. }
  952. // Path without color_mask_common set
  953. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  954. if (!force && !flags[Dirty::ColorMask0 + i]) {
  955. continue;
  956. }
  957. flags[Dirty::ColorMask0 + i] = false;
  958. const auto& mask = regs.color_mask[i];
  959. glColorMaski(static_cast<GLuint>(i), mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0);
  960. }
  961. }
  962. void RasterizerOpenGL::SyncMultiSampleState() {
  963. auto& flags = maxwell3d->dirty.flags;
  964. if (!flags[Dirty::MultisampleControl]) {
  965. return;
  966. }
  967. flags[Dirty::MultisampleControl] = false;
  968. const auto& regs = maxwell3d->regs;
  969. oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.anti_alias_alpha_control.alpha_to_coverage);
  970. oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.anti_alias_alpha_control.alpha_to_one);
  971. }
  972. void RasterizerOpenGL::SyncFragmentColorClampState() {
  973. auto& flags = maxwell3d->dirty.flags;
  974. if (!flags[Dirty::FragmentClampColor]) {
  975. return;
  976. }
  977. flags[Dirty::FragmentClampColor] = false;
  978. glClampColor(GL_CLAMP_FRAGMENT_COLOR,
  979. maxwell3d->regs.frag_color_clamp.AnyEnabled() ? GL_TRUE : GL_FALSE);
  980. }
  981. void RasterizerOpenGL::SyncBlendState() {
  982. auto& flags = maxwell3d->dirty.flags;
  983. const auto& regs = maxwell3d->regs;
  984. if (flags[Dirty::BlendColor]) {
  985. flags[Dirty::BlendColor] = false;
  986. glBlendColor(regs.blend_color.r, regs.blend_color.g, regs.blend_color.b,
  987. regs.blend_color.a);
  988. }
  989. // TODO(Rodrigo): Revisit blending, there are several registers we are not reading
  990. if (!flags[Dirty::BlendStates]) {
  991. return;
  992. }
  993. flags[Dirty::BlendStates] = false;
  994. if (!regs.blend_per_target_enabled) {
  995. if (!regs.blend.enable[0]) {
  996. glDisable(GL_BLEND);
  997. return;
  998. }
  999. glEnable(GL_BLEND);
  1000. glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.color_source),
  1001. MaxwellToGL::BlendFunc(regs.blend.color_dest),
  1002. MaxwellToGL::BlendFunc(regs.blend.alpha_source),
  1003. MaxwellToGL::BlendFunc(regs.blend.alpha_dest));
  1004. glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.color_op),
  1005. MaxwellToGL::BlendEquation(regs.blend.alpha_op));
  1006. return;
  1007. }
  1008. const bool force = flags[Dirty::BlendIndependentEnabled];
  1009. flags[Dirty::BlendIndependentEnabled] = false;
  1010. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  1011. if (!force && !flags[Dirty::BlendState0 + i]) {
  1012. continue;
  1013. }
  1014. flags[Dirty::BlendState0 + i] = false;
  1015. if (!regs.blend.enable[i]) {
  1016. glDisablei(GL_BLEND, static_cast<GLuint>(i));
  1017. continue;
  1018. }
  1019. glEnablei(GL_BLEND, static_cast<GLuint>(i));
  1020. const auto& src = regs.blend_per_target[i];
  1021. glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.color_source),
  1022. MaxwellToGL::BlendFunc(src.color_dest),
  1023. MaxwellToGL::BlendFunc(src.alpha_source),
  1024. MaxwellToGL::BlendFunc(src.alpha_dest));
  1025. glBlendEquationSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendEquation(src.color_op),
  1026. MaxwellToGL::BlendEquation(src.alpha_op));
  1027. }
  1028. }
  1029. void RasterizerOpenGL::SyncLogicOpState() {
  1030. auto& flags = maxwell3d->dirty.flags;
  1031. if (!flags[Dirty::LogicOp]) {
  1032. return;
  1033. }
  1034. flags[Dirty::LogicOp] = false;
  1035. const auto& regs = maxwell3d->regs;
  1036. if (regs.logic_op.enable) {
  1037. glEnable(GL_COLOR_LOGIC_OP);
  1038. glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.op));
  1039. } else {
  1040. glDisable(GL_COLOR_LOGIC_OP);
  1041. }
  1042. }
  1043. void RasterizerOpenGL::SyncScissorTest() {
  1044. auto& flags = maxwell3d->dirty.flags;
  1045. if (!flags[Dirty::Scissors] && !flags[VideoCommon::Dirty::RescaleScissors]) {
  1046. return;
  1047. }
  1048. flags[Dirty::Scissors] = false;
  1049. const bool force = flags[VideoCommon::Dirty::RescaleScissors];
  1050. flags[VideoCommon::Dirty::RescaleScissors] = false;
  1051. const auto& regs = maxwell3d->regs;
  1052. const auto& resolution = Settings::values.resolution_info;
  1053. const bool is_rescaling{texture_cache.IsRescaling()};
  1054. const u32 up_scale = is_rescaling ? resolution.up_scale : 1U;
  1055. const u32 down_shift = is_rescaling ? resolution.down_shift : 0U;
  1056. const auto scale_up = [up_scale, down_shift](u32 value) -> u32 {
  1057. if (value == 0) {
  1058. return 0U;
  1059. }
  1060. const u32 upset = value * up_scale;
  1061. u32 acumm{};
  1062. if ((up_scale >> down_shift) == 0) {
  1063. acumm = upset % 2;
  1064. }
  1065. const u32 converted_value = upset >> down_shift;
  1066. return std::max<u32>(converted_value + acumm, 1U);
  1067. };
  1068. for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
  1069. if (!force && !flags[Dirty::Scissor0 + index]) {
  1070. continue;
  1071. }
  1072. flags[Dirty::Scissor0 + index] = false;
  1073. const auto& src = regs.scissor_test[index];
  1074. if (src.enable) {
  1075. glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  1076. glScissorIndexed(static_cast<GLuint>(index), scale_up(src.min_x), scale_up(src.min_y),
  1077. scale_up(src.max_x - src.min_x), scale_up(src.max_y - src.min_y));
  1078. } else {
  1079. glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  1080. }
  1081. }
  1082. }
  1083. void RasterizerOpenGL::SyncPointState() {
  1084. auto& flags = maxwell3d->dirty.flags;
  1085. if (!flags[Dirty::PointSize]) {
  1086. return;
  1087. }
  1088. flags[Dirty::PointSize] = false;
  1089. oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
  1090. oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled);
  1091. const bool is_rescaling{texture_cache.IsRescaling()};
  1092. const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
  1093. glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
  1094. }
  1095. void RasterizerOpenGL::SyncLineState() {
  1096. auto& flags = maxwell3d->dirty.flags;
  1097. if (!flags[Dirty::LineWidth]) {
  1098. return;
  1099. }
  1100. flags[Dirty::LineWidth] = false;
  1101. const auto& regs = maxwell3d->regs;
  1102. oglEnable(GL_LINE_SMOOTH, regs.line_anti_alias_enable);
  1103. glLineWidth(regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased);
  1104. }
  1105. void RasterizerOpenGL::SyncPolygonOffset() {
  1106. auto& flags = maxwell3d->dirty.flags;
  1107. if (!flags[Dirty::PolygonOffset]) {
  1108. return;
  1109. }
  1110. flags[Dirty::PolygonOffset] = false;
  1111. const auto& regs = maxwell3d->regs;
  1112. oglEnable(GL_POLYGON_OFFSET_FILL, regs.polygon_offset_fill_enable);
  1113. oglEnable(GL_POLYGON_OFFSET_LINE, regs.polygon_offset_line_enable);
  1114. oglEnable(GL_POLYGON_OFFSET_POINT, regs.polygon_offset_point_enable);
  1115. if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
  1116. regs.polygon_offset_point_enable) {
  1117. // Hardware divides polygon offset units by two
  1118. glPolygonOffsetClamp(regs.slope_scale_depth_bias, regs.depth_bias / 2.0f,
  1119. regs.depth_bias_clamp);
  1120. }
  1121. }
  1122. void RasterizerOpenGL::SyncAlphaTest() {
  1123. auto& flags = maxwell3d->dirty.flags;
  1124. if (!flags[Dirty::AlphaTest]) {
  1125. return;
  1126. }
  1127. flags[Dirty::AlphaTest] = false;
  1128. const auto& regs = maxwell3d->regs;
  1129. if (regs.alpha_test_enabled) {
  1130. glEnable(GL_ALPHA_TEST);
  1131. glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref);
  1132. } else {
  1133. glDisable(GL_ALPHA_TEST);
  1134. }
  1135. }
  1136. void RasterizerOpenGL::SyncFramebufferSRGB() {
  1137. auto& flags = maxwell3d->dirty.flags;
  1138. if (!flags[Dirty::FramebufferSRGB]) {
  1139. return;
  1140. }
  1141. flags[Dirty::FramebufferSRGB] = false;
  1142. oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d->regs.framebuffer_srgb);
  1143. }
  1144. void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
  1145. const auto& regs = maxwell3d->regs;
  1146. if (regs.transform_feedback_enabled == 0) {
  1147. return;
  1148. }
  1149. program->ConfigureTransformFeedback();
  1150. UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
  1151. regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation));
  1152. // We may have to call BeginTransformFeedbackNV here since they seem to call different
  1153. // implementations on Nvidia's driver (the pointer is different) but we are using
  1154. // ARB_transform_feedback3 features with NV_transform_feedback interactions and the ARB
  1155. // extension doesn't define BeginTransformFeedback (without NV) interactions. It just works.
  1156. glBeginTransformFeedback(primitive_mode);
  1157. }
  1158. void RasterizerOpenGL::EndTransformFeedback() {
  1159. if (maxwell3d->regs.transform_feedback_enabled != 0) {
  1160. glEndTransformFeedback();
  1161. }
  1162. }
  1163. void RasterizerOpenGL::InitializeChannel(Tegra::Control::ChannelState& channel) {
  1164. CreateChannel(channel);
  1165. {
  1166. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1167. texture_cache.CreateChannel(channel);
  1168. buffer_cache.CreateChannel(channel);
  1169. }
  1170. shader_cache.CreateChannel(channel);
  1171. query_cache.CreateChannel(channel);
  1172. state_tracker.SetupTables(channel);
  1173. }
  1174. void RasterizerOpenGL::BindChannel(Tegra::Control::ChannelState& channel) {
  1175. const s32 channel_id = channel.bind_id;
  1176. BindToChannel(channel_id);
  1177. {
  1178. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1179. texture_cache.BindToChannel(channel_id);
  1180. buffer_cache.BindToChannel(channel_id);
  1181. }
  1182. shader_cache.BindToChannel(channel_id);
  1183. query_cache.BindToChannel(channel_id);
  1184. state_tracker.ChangeChannel(channel);
  1185. state_tracker.InvalidateState();
  1186. }
  1187. void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
  1188. EraseChannel(channel_id);
  1189. {
  1190. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1191. texture_cache.EraseChannel(channel_id);
  1192. buffer_cache.EraseChannel(channel_id);
  1193. }
  1194. shader_cache.EraseChannel(channel_id);
  1195. query_cache.EraseChannel(channel_id);
  1196. }
  1197. AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_)
  1198. : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {}
  1199. bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
  1200. std::scoped_lock lock{buffer_cache.mutex};
  1201. return buffer_cache.DMACopy(src_address, dest_address, amount);
  1202. }
  1203. bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) {
  1204. std::scoped_lock lock{buffer_cache.mutex};
  1205. return buffer_cache.DMAClear(src_address, amount, value);
  1206. }
  1207. template <bool IS_IMAGE_UPLOAD>
  1208. bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
  1209. const Tegra::DMA::BufferOperand& buffer_operand,
  1210. const Tegra::DMA::ImageOperand& image_operand) {
  1211. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1212. const auto image_id = texture_cache.DmaImageId(image_operand, IS_IMAGE_UPLOAD);
  1213. if (image_id == VideoCommon::NULL_IMAGE_ID) {
  1214. return false;
  1215. }
  1216. const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
  1217. static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
  1218. const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
  1219. : VideoCommon::ObtainBufferOperation::MarkAsWritten;
  1220. const auto [buffer, offset] =
  1221. buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
  1222. const auto [image, copy] = texture_cache.DmaBufferImageCopy(
  1223. copy_info, buffer_operand, image_operand, image_id, IS_IMAGE_UPLOAD);
  1224. const std::span copy_span{&copy, 1};
  1225. if constexpr (IS_IMAGE_UPLOAD) {
  1226. texture_cache.PrepareImage(image_id, true, false);
  1227. image->UploadMemory(buffer->Handle(), offset, copy_span);
  1228. } else {
  1229. if (offset % BytesPerBlock(image->info.format)) {
  1230. return false;
  1231. }
  1232. texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
  1233. buffer_operand.address, buffer_size);
  1234. }
  1235. return true;
  1236. }
  1237. bool AccelerateDMA::ImageToBuffer(const Tegra::DMA::ImageCopy& copy_info,
  1238. const Tegra::DMA::ImageOperand& image_operand,
  1239. const Tegra::DMA::BufferOperand& buffer_operand) {
  1240. return DmaBufferImageCopy<false>(copy_info, buffer_operand, image_operand);
  1241. }
  1242. bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
  1243. const Tegra::DMA::BufferOperand& buffer_operand,
  1244. const Tegra::DMA::ImageOperand& image_operand) {
  1245. return DmaBufferImageCopy<true>(copy_info, buffer_operand, image_operand);
  1246. }
  1247. } // namespace OpenGL