gl_rasterizer.cpp 45 KB

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