gl_rasterizer.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  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. Tegra::MaxwellDeviceMemoryManager& device_memory_,
  63. const Device& device_, ScreenInfo& screen_info_,
  64. ProgramManager& program_manager_, StateTracker& state_tracker_)
  65. : gpu(gpu_), device_memory(device_memory_), 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, device_memory_),
  69. buffer_cache_runtime(device, staging_buffer_pool),
  70. buffer_cache(device_memory_, buffer_cache_runtime),
  71. shader_cache(device_memory_, emu_window_, device, texture_cache, buffer_cache,
  72. program_manager, state_tracker, gpu.ShaderNotify()),
  73. query_cache(*this, device_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. if (params.is_byte_count) {
  269. const GPUVAddr tfb_object_base_addr = params.indirect_start_address - 4U;
  270. const GLuint tfb_object =
  271. buffer_cache_runtime.GetTransformFeedbackObject(tfb_object_base_addr);
  272. glDrawTransformFeedback(primitive_mode, tfb_object);
  273. return;
  274. }
  275. const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
  276. const GLvoid* const gl_offset =
  277. reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset));
  278. glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle());
  279. if (params.include_count) {
  280. const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount();
  281. glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle());
  282. if (params.is_indexed) {
  283. const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
  284. glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset,
  285. static_cast<GLintptr>(offset_base),
  286. static_cast<GLsizei>(params.max_draw_counts),
  287. static_cast<GLsizei>(params.stride));
  288. } else {
  289. glMultiDrawArraysIndirectCount(primitive_mode, gl_offset,
  290. static_cast<GLintptr>(offset_base),
  291. static_cast<GLsizei>(params.max_draw_counts),
  292. static_cast<GLsizei>(params.stride));
  293. }
  294. return;
  295. }
  296. if (params.is_indexed) {
  297. const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
  298. glMultiDrawElementsIndirect(primitive_mode, format, gl_offset,
  299. static_cast<GLsizei>(params.max_draw_counts),
  300. static_cast<GLsizei>(params.stride));
  301. } else {
  302. glMultiDrawArraysIndirect(primitive_mode, gl_offset,
  303. static_cast<GLsizei>(params.max_draw_counts),
  304. static_cast<GLsizei>(params.stride));
  305. }
  306. });
  307. buffer_cache.SetDrawIndirect(nullptr);
  308. }
  309. void RasterizerOpenGL::DrawTexture() {
  310. MICROPROFILE_SCOPE(OpenGL_Drawing);
  311. SCOPE_EXIT({ gpu.TickWork(); });
  312. texture_cache.SynchronizeGraphicsDescriptors();
  313. texture_cache.UpdateRenderTargets(false);
  314. SyncState();
  315. const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
  316. const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
  317. const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
  318. if (device.HasDrawTexture()) {
  319. state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
  320. glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(), draw_texture_state.dst_x0,
  321. draw_texture_state.dst_y0, draw_texture_state.dst_x1,
  322. draw_texture_state.dst_y1, 0,
  323. draw_texture_state.src_x0 / static_cast<float>(texture.size.width),
  324. draw_texture_state.src_y0 / static_cast<float>(texture.size.height),
  325. draw_texture_state.src_x1 / static_cast<float>(texture.size.width),
  326. draw_texture_state.src_y1 / static_cast<float>(texture.size.height));
  327. } else {
  328. Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0),
  329. .y = static_cast<s32>(draw_texture_state.dst_y0)},
  330. Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1),
  331. .y = static_cast<s32>(draw_texture_state.dst_y1)}};
  332. Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0),
  333. .y = static_cast<s32>(draw_texture_state.src_y0)},
  334. Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1),
  335. .y = static_cast<s32>(draw_texture_state.src_y1)}};
  336. blit_image.BlitColor(texture_cache.GetFramebuffer()->Handle(), texture.DefaultHandle(),
  337. sampler->Handle(), dst_region, src_region, texture.size);
  338. state_tracker.InvalidateState();
  339. }
  340. ++num_queued_commands;
  341. }
  342. void RasterizerOpenGL::DispatchCompute() {
  343. gpu_memory->FlushCaching();
  344. ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
  345. if (!pipeline) {
  346. return;
  347. }
  348. if (pipeline->UsesLocalMemory()) {
  349. program_manager.LocalMemoryWarmup();
  350. }
  351. pipeline->SetEngine(kepler_compute, gpu_memory);
  352. pipeline->Configure();
  353. const auto& qmd{kepler_compute->launch_description};
  354. auto indirect_address = kepler_compute->GetIndirectComputeAddress();
  355. if (indirect_address) {
  356. // DispatchIndirect
  357. static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
  358. const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
  359. const auto [buffer, offset] =
  360. buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
  361. glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->Handle());
  362. glDispatchComputeIndirect(static_cast<GLintptr>(offset));
  363. return;
  364. }
  365. glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
  366. ++num_queued_commands;
  367. has_written_global_memory |= pipeline->WritesGlobalMemory();
  368. }
  369. void RasterizerOpenGL::ResetCounter(VideoCommon::QueryType type) {
  370. const auto query_cache_type = MaxwellToVideoCoreQuery(type);
  371. if (!query_cache_type.has_value()) {
  372. UNIMPLEMENTED_IF_MSG(type != VideoCommon::QueryType::Payload, "Reset query type: {}", type);
  373. return;
  374. }
  375. query_cache.ResetCounter(*query_cache_type);
  376. }
  377. void RasterizerOpenGL::Query(GPUVAddr gpu_addr, VideoCommon::QueryType type,
  378. VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport) {
  379. const auto query_cache_type = MaxwellToVideoCoreQuery(type);
  380. if (!query_cache_type.has_value()) {
  381. return QueryFallback(gpu_addr, type, flags, payload, subreport);
  382. }
  383. const bool has_timeout = True(flags & VideoCommon::QueryPropertiesFlags::HasTimeout);
  384. const auto timestamp = has_timeout ? std::optional<u64>{gpu.GetTicks()} : std::nullopt;
  385. query_cache.Query(gpu_addr, *query_cache_type, timestamp);
  386. }
  387. void RasterizerOpenGL::QueryFallback(GPUVAddr gpu_addr, VideoCommon::QueryType type,
  388. VideoCommon::QueryPropertiesFlags flags, u32 payload,
  389. u32 subreport) {
  390. if (type != VideoCommon::QueryType::Payload) {
  391. payload = 1u;
  392. }
  393. std::function<void()> func([this, gpu_addr, flags, memory_manager = gpu_memory, payload]() {
  394. if (True(flags & VideoCommon::QueryPropertiesFlags::HasTimeout)) {
  395. u64 ticks = gpu.GetTicks();
  396. memory_manager->Write<u64>(gpu_addr + 8, ticks);
  397. memory_manager->Write<u64>(gpu_addr, static_cast<u64>(payload));
  398. } else {
  399. memory_manager->Write<u32>(gpu_addr, payload);
  400. }
  401. });
  402. if (True(flags & VideoCommon::QueryPropertiesFlags::IsAFence)) {
  403. SignalFence(std::move(func));
  404. return;
  405. }
  406. func();
  407. }
  408. void RasterizerOpenGL::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
  409. u32 size) {
  410. std::scoped_lock lock{buffer_cache.mutex};
  411. buffer_cache.BindGraphicsUniformBuffer(stage, index, gpu_addr, size);
  412. }
  413. void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
  414. buffer_cache.DisableGraphicsUniformBuffer(stage, index);
  415. }
  416. void RasterizerOpenGL::FlushAll() {}
  417. void RasterizerOpenGL::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
  418. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  419. if (addr == 0 || size == 0) {
  420. return;
  421. }
  422. if (True(which & VideoCommon::CacheType::TextureCache)) {
  423. std::scoped_lock lock{texture_cache.mutex};
  424. texture_cache.DownloadMemory(addr, size);
  425. }
  426. if ((True(which & VideoCommon::CacheType::BufferCache))) {
  427. std::scoped_lock lock{buffer_cache.mutex};
  428. buffer_cache.DownloadMemory(addr, size);
  429. }
  430. if ((True(which & VideoCommon::CacheType::QueryCache))) {
  431. query_cache.FlushRegion(addr, size);
  432. }
  433. }
  434. bool RasterizerOpenGL::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
  435. if ((True(which & VideoCommon::CacheType::BufferCache))) {
  436. std::scoped_lock lock{buffer_cache.mutex};
  437. if (buffer_cache.IsRegionGpuModified(addr, size)) {
  438. return true;
  439. }
  440. }
  441. if (!Settings::IsGPULevelHigh()) {
  442. return false;
  443. }
  444. if (True(which & VideoCommon::CacheType::TextureCache)) {
  445. std::scoped_lock lock{texture_cache.mutex};
  446. return texture_cache.IsRegionGpuModified(addr, size);
  447. }
  448. return false;
  449. }
  450. VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(DAddr addr, u64 size) {
  451. {
  452. std::scoped_lock lock{texture_cache.mutex};
  453. auto area = texture_cache.GetFlushArea(addr, size);
  454. if (area) {
  455. return *area;
  456. }
  457. }
  458. {
  459. std::scoped_lock lock{buffer_cache.mutex};
  460. auto area = buffer_cache.GetFlushArea(addr, size);
  461. if (area) {
  462. return *area;
  463. }
  464. }
  465. VideoCore::RasterizerDownloadArea new_area{
  466. .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE),
  467. .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE),
  468. .preemtive = true,
  469. };
  470. return new_area;
  471. }
  472. void RasterizerOpenGL::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
  473. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  474. if (addr == 0 || size == 0) {
  475. return;
  476. }
  477. if (True(which & VideoCommon::CacheType::TextureCache)) {
  478. std::scoped_lock lock{texture_cache.mutex};
  479. texture_cache.WriteMemory(addr, size);
  480. }
  481. if (True(which & VideoCommon::CacheType::BufferCache)) {
  482. std::scoped_lock lock{buffer_cache.mutex};
  483. buffer_cache.WriteMemory(addr, size);
  484. }
  485. if (True(which & VideoCommon::CacheType::ShaderCache)) {
  486. shader_cache.InvalidateRegion(addr, size);
  487. }
  488. if (True(which & VideoCommon::CacheType::QueryCache)) {
  489. query_cache.InvalidateRegion(addr, size);
  490. }
  491. }
  492. bool RasterizerOpenGL::OnCPUWrite(DAddr addr, u64 size) {
  493. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  494. if (addr == 0 || size == 0) {
  495. return false;
  496. }
  497. {
  498. std::scoped_lock lock{buffer_cache.mutex};
  499. if (buffer_cache.OnCPUWrite(addr, size)) {
  500. return true;
  501. }
  502. }
  503. {
  504. std::scoped_lock lock{texture_cache.mutex};
  505. texture_cache.WriteMemory(addr, size);
  506. }
  507. shader_cache.InvalidateRegion(addr, size);
  508. return false;
  509. }
  510. void RasterizerOpenGL::OnCacheInvalidation(DAddr addr, u64 size) {
  511. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  512. if (addr == 0 || size == 0) {
  513. return;
  514. }
  515. {
  516. std::scoped_lock lock{texture_cache.mutex};
  517. texture_cache.WriteMemory(addr, size);
  518. }
  519. {
  520. std::scoped_lock lock{buffer_cache.mutex};
  521. buffer_cache.WriteMemory(addr, size);
  522. }
  523. shader_cache.InvalidateRegion(addr, size);
  524. }
  525. void RasterizerOpenGL::InvalidateGPUCache() {
  526. gpu.InvalidateGPUCache();
  527. }
  528. void RasterizerOpenGL::UnmapMemory(DAddr addr, u64 size) {
  529. {
  530. std::scoped_lock lock{texture_cache.mutex};
  531. texture_cache.UnmapMemory(addr, size);
  532. }
  533. {
  534. std::scoped_lock lock{buffer_cache.mutex};
  535. buffer_cache.WriteMemory(addr, size);
  536. }
  537. shader_cache.OnCacheInvalidation(addr, size);
  538. }
  539. void RasterizerOpenGL::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {
  540. {
  541. std::scoped_lock lock{texture_cache.mutex};
  542. texture_cache.UnmapGPUMemory(as_id, addr, size);
  543. }
  544. }
  545. void RasterizerOpenGL::SignalFence(std::function<void()>&& func) {
  546. fence_manager.SignalFence(std::move(func));
  547. }
  548. void RasterizerOpenGL::SyncOperation(std::function<void()>&& func) {
  549. fence_manager.SyncOperation(std::move(func));
  550. }
  551. void RasterizerOpenGL::SignalSyncPoint(u32 value) {
  552. fence_manager.SignalSyncPoint(value);
  553. }
  554. void RasterizerOpenGL::SignalReference() {
  555. fence_manager.SignalOrdering();
  556. }
  557. void RasterizerOpenGL::ReleaseFences(bool force) {
  558. fence_manager.WaitPendingFences(force);
  559. }
  560. void RasterizerOpenGL::FlushAndInvalidateRegion(DAddr addr, u64 size,
  561. VideoCommon::CacheType which) {
  562. if (Settings::IsGPULevelExtreme()) {
  563. FlushRegion(addr, size, which);
  564. }
  565. InvalidateRegion(addr, size, which);
  566. }
  567. void RasterizerOpenGL::WaitForIdle() {
  568. glMemoryBarrier(GL_ALL_BARRIER_BITS);
  569. SignalReference();
  570. }
  571. void RasterizerOpenGL::FragmentBarrier() {
  572. glTextureBarrier();
  573. glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
  574. }
  575. void RasterizerOpenGL::TiledCacheBarrier() {
  576. glTextureBarrier();
  577. }
  578. void RasterizerOpenGL::FlushCommands() {
  579. // Only flush when we have commands queued to OpenGL.
  580. if (num_queued_commands == 0) {
  581. return;
  582. }
  583. num_queued_commands = 0;
  584. // Make sure memory stored from the previous GL command stream is visible
  585. // This is only needed on assembly shaders where we write to GPU memory with raw pointers
  586. if (has_written_global_memory) {
  587. has_written_global_memory = false;
  588. glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
  589. }
  590. glFlush();
  591. }
  592. void RasterizerOpenGL::TickFrame() {
  593. // Ticking a frame means that buffers will be swapped, calling glFlush implicitly.
  594. num_queued_commands = 0;
  595. fence_manager.TickFrame();
  596. {
  597. std::scoped_lock lock{texture_cache.mutex};
  598. texture_cache.TickFrame();
  599. }
  600. {
  601. std::scoped_lock lock{buffer_cache.mutex};
  602. buffer_cache.TickFrame();
  603. }
  604. }
  605. bool RasterizerOpenGL::AccelerateConditionalRendering() {
  606. gpu_memory->FlushCaching();
  607. if (Settings::IsGPULevelHigh()) {
  608. // Reimplement Host conditional rendering.
  609. return false;
  610. }
  611. // Medium / Low Hack: stub any checks on queries written into the buffer cache.
  612. const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()};
  613. Maxwell::ReportSemaphore::Compare cmp;
  614. if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp),
  615. VideoCommon::CacheType::BufferCache)) {
  616. return true;
  617. }
  618. return false;
  619. }
  620. bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
  621. const Tegra::Engines::Fermi2D::Surface& dst,
  622. const Tegra::Engines::Fermi2D::Config& copy_config) {
  623. MICROPROFILE_SCOPE(OpenGL_Blits);
  624. std::scoped_lock lock{texture_cache.mutex};
  625. return texture_cache.BlitImage(dst, src, copy_config);
  626. }
  627. Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA() {
  628. return accelerate_dma;
  629. }
  630. void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
  631. std::span<const u8> memory) {
  632. auto cpu_addr = gpu_memory->GpuToCpuAddress(address);
  633. if (!cpu_addr) [[unlikely]] {
  634. gpu_memory->WriteBlock(address, memory.data(), copy_size);
  635. return;
  636. }
  637. gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size);
  638. {
  639. std::unique_lock<std::recursive_mutex> lock{buffer_cache.mutex};
  640. if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
  641. buffer_cache.WriteMemory(*cpu_addr, copy_size);
  642. }
  643. }
  644. {
  645. std::scoped_lock lock_texture{texture_cache.mutex};
  646. texture_cache.WriteMemory(*cpu_addr, copy_size);
  647. }
  648. shader_cache.InvalidateRegion(*cpu_addr, copy_size);
  649. query_cache.InvalidateRegion(*cpu_addr, copy_size);
  650. }
  651. bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
  652. DAddr framebuffer_addr, u32 pixel_stride) {
  653. if (framebuffer_addr == 0) {
  654. return false;
  655. }
  656. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  657. std::scoped_lock lock{texture_cache.mutex};
  658. ImageView* const image_view{
  659. texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
  660. if (!image_view) {
  661. return false;
  662. }
  663. // Verify that the cached surface is the same size and format as the requested framebuffer
  664. // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
  665. // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
  666. screen_info.texture.width = image_view->size.width;
  667. screen_info.texture.height = image_view->size.height;
  668. screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
  669. return true;
  670. }
  671. void RasterizerOpenGL::SyncState() {
  672. SyncViewport();
  673. SyncRasterizeEnable();
  674. SyncPolygonModes();
  675. SyncColorMask();
  676. SyncFragmentColorClampState();
  677. SyncMultiSampleState();
  678. SyncDepthTestState();
  679. SyncDepthClamp();
  680. SyncStencilTestState();
  681. SyncBlendState();
  682. SyncLogicOpState();
  683. SyncCullMode();
  684. SyncPrimitiveRestart();
  685. SyncScissorTest();
  686. SyncPointState();
  687. SyncLineState();
  688. SyncPolygonOffset();
  689. SyncAlphaTest();
  690. SyncFramebufferSRGB();
  691. SyncVertexFormats();
  692. SyncVertexInstances();
  693. }
  694. void RasterizerOpenGL::SyncViewport() {
  695. auto& flags = maxwell3d->dirty.flags;
  696. const auto& regs = maxwell3d->regs;
  697. const bool rescale_viewports = flags[VideoCommon::Dirty::RescaleViewports];
  698. const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports;
  699. const bool dirty_clip_control = flags[Dirty::ClipControl];
  700. if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) {
  701. flags[Dirty::FrontFace] = false;
  702. GLenum mode = MaxwellToGL::FrontFace(regs.gl_front_face);
  703. bool flip_faces = true;
  704. if (regs.window_origin.flip_y != 0) {
  705. flip_faces = !flip_faces;
  706. }
  707. if (regs.viewport_transform[0].scale_y < 0.0f) {
  708. flip_faces = !flip_faces;
  709. }
  710. if (flip_faces) {
  711. switch (mode) {
  712. case GL_CW:
  713. mode = GL_CCW;
  714. break;
  715. case GL_CCW:
  716. mode = GL_CW;
  717. break;
  718. }
  719. }
  720. glFrontFace(mode);
  721. }
  722. if (dirty_viewport || dirty_clip_control) {
  723. flags[Dirty::ClipControl] = false;
  724. bool flip_y = false;
  725. if (regs.viewport_transform[0].scale_y < 0.0f) {
  726. flip_y = !flip_y;
  727. }
  728. const bool lower_left{regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft};
  729. if (lower_left) {
  730. flip_y = !flip_y;
  731. }
  732. const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
  733. const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
  734. const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
  735. state_tracker.ClipControl(origin, depth);
  736. state_tracker.SetYNegate(lower_left);
  737. }
  738. const bool is_rescaling{texture_cache.IsRescaling()};
  739. const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
  740. const auto conv = [scale](float value) -> GLfloat {
  741. float new_value = value * scale;
  742. if (scale < 1.0f) {
  743. const bool sign = std::signbit(value);
  744. new_value = std::round(std::abs(new_value));
  745. new_value = sign ? -new_value : new_value;
  746. }
  747. return static_cast<GLfloat>(new_value);
  748. };
  749. if (dirty_viewport) {
  750. flags[Dirty::Viewports] = false;
  751. const bool force = flags[Dirty::ViewportTransform] || rescale_viewports;
  752. flags[Dirty::ViewportTransform] = false;
  753. flags[VideoCommon::Dirty::RescaleViewports] = false;
  754. for (size_t index = 0; index < Maxwell::NumViewports; ++index) {
  755. if (!force && !flags[Dirty::Viewport0 + index]) {
  756. continue;
  757. }
  758. flags[Dirty::Viewport0 + index] = false;
  759. if (!regs.viewport_scale_offset_enabled) {
  760. const auto x = static_cast<GLfloat>(regs.surface_clip.x);
  761. const auto y = static_cast<GLfloat>(regs.surface_clip.y);
  762. const auto width = static_cast<GLfloat>(regs.surface_clip.width);
  763. const auto height = static_cast<GLfloat>(regs.surface_clip.height);
  764. glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
  765. height != 0.0f ? height : 1.0f);
  766. continue;
  767. }
  768. const auto& src = regs.viewport_transform[index];
  769. GLfloat x = conv(src.translate_x - src.scale_x);
  770. GLfloat y = conv(src.translate_y - src.scale_y);
  771. GLfloat width = conv(src.scale_x * 2.0f);
  772. GLfloat height = conv(src.scale_y * 2.0f);
  773. if (height < 0) {
  774. y += height;
  775. height = -height;
  776. }
  777. glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
  778. height != 0.0f ? height : 1.0f);
  779. const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
  780. const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
  781. const GLdouble far_depth = src.translate_z + src.scale_z;
  782. if (device.HasDepthBufferFloat()) {
  783. glDepthRangeIndexeddNV(static_cast<GLuint>(index), near_depth, far_depth);
  784. } else {
  785. glDepthRangeIndexed(static_cast<GLuint>(index), near_depth, far_depth);
  786. }
  787. if (!GLAD_GL_NV_viewport_swizzle) {
  788. continue;
  789. }
  790. glViewportSwizzleNV(static_cast<GLuint>(index),
  791. MaxwellToGL::ViewportSwizzle(src.swizzle.x),
  792. MaxwellToGL::ViewportSwizzle(src.swizzle.y),
  793. MaxwellToGL::ViewportSwizzle(src.swizzle.z),
  794. MaxwellToGL::ViewportSwizzle(src.swizzle.w));
  795. }
  796. }
  797. }
  798. void RasterizerOpenGL::SyncDepthClamp() {
  799. auto& flags = maxwell3d->dirty.flags;
  800. if (!flags[Dirty::DepthClampEnabled]) {
  801. return;
  802. }
  803. flags[Dirty::DepthClampEnabled] = false;
  804. bool depth_clamp_disabled{maxwell3d->regs.viewport_clip_control.geometry_clip ==
  805. Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
  806. maxwell3d->regs.viewport_clip_control.geometry_clip ==
  807. Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
  808. maxwell3d->regs.viewport_clip_control.geometry_clip ==
  809. Maxwell::ViewportClipControl::GeometryClip::FrustumZ};
  810. oglEnable(GL_DEPTH_CLAMP, !depth_clamp_disabled);
  811. }
  812. void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
  813. auto& flags = maxwell3d->dirty.flags;
  814. if (!flags[Dirty::ClipDistances] && !flags[VideoCommon::Dirty::Shaders]) {
  815. return;
  816. }
  817. flags[Dirty::ClipDistances] = false;
  818. clip_mask &= maxwell3d->regs.user_clip_enable.raw;
  819. if (clip_mask == last_clip_distance_mask) {
  820. return;
  821. }
  822. last_clip_distance_mask = clip_mask;
  823. for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) {
  824. oglEnable(static_cast<GLenum>(GL_CLIP_DISTANCE0 + i), (clip_mask >> i) & 1);
  825. }
  826. }
  827. void RasterizerOpenGL::SyncClipCoef() {
  828. UNIMPLEMENTED();
  829. }
  830. void RasterizerOpenGL::SyncCullMode() {
  831. auto& flags = maxwell3d->dirty.flags;
  832. const auto& regs = maxwell3d->regs;
  833. if (flags[Dirty::CullTest]) {
  834. flags[Dirty::CullTest] = false;
  835. if (regs.gl_cull_test_enabled) {
  836. glEnable(GL_CULL_FACE);
  837. glCullFace(MaxwellToGL::CullFace(regs.gl_cull_face));
  838. } else {
  839. glDisable(GL_CULL_FACE);
  840. }
  841. }
  842. }
  843. void RasterizerOpenGL::SyncPrimitiveRestart() {
  844. auto& flags = maxwell3d->dirty.flags;
  845. if (!flags[Dirty::PrimitiveRestart]) {
  846. return;
  847. }
  848. flags[Dirty::PrimitiveRestart] = false;
  849. if (maxwell3d->regs.primitive_restart.enabled) {
  850. glEnable(GL_PRIMITIVE_RESTART);
  851. glPrimitiveRestartIndex(maxwell3d->regs.primitive_restart.index);
  852. } else {
  853. glDisable(GL_PRIMITIVE_RESTART);
  854. }
  855. }
  856. void RasterizerOpenGL::SyncDepthTestState() {
  857. auto& flags = maxwell3d->dirty.flags;
  858. const auto& regs = maxwell3d->regs;
  859. if (flags[Dirty::DepthMask]) {
  860. flags[Dirty::DepthMask] = false;
  861. glDepthMask(regs.depth_write_enabled ? GL_TRUE : GL_FALSE);
  862. }
  863. if (flags[Dirty::DepthTest]) {
  864. flags[Dirty::DepthTest] = false;
  865. if (regs.depth_test_enable) {
  866. glEnable(GL_DEPTH_TEST);
  867. glDepthFunc(MaxwellToGL::ComparisonOp(regs.depth_test_func));
  868. } else {
  869. glDisable(GL_DEPTH_TEST);
  870. }
  871. }
  872. }
  873. void RasterizerOpenGL::SyncStencilTestState() {
  874. auto& flags = maxwell3d->dirty.flags;
  875. if (!flags[Dirty::StencilTest]) {
  876. return;
  877. }
  878. flags[Dirty::StencilTest] = false;
  879. const auto& regs = maxwell3d->regs;
  880. oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
  881. glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
  882. regs.stencil_front_ref, regs.stencil_front_func_mask);
  883. glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op.fail),
  884. MaxwellToGL::StencilOp(regs.stencil_front_op.zfail),
  885. MaxwellToGL::StencilOp(regs.stencil_front_op.zpass));
  886. glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
  887. if (regs.stencil_two_side_enable) {
  888. glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.func),
  889. regs.stencil_back_ref, regs.stencil_back_func_mask);
  890. glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op.fail),
  891. MaxwellToGL::StencilOp(regs.stencil_back_op.zfail),
  892. MaxwellToGL::StencilOp(regs.stencil_back_op.zpass));
  893. glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
  894. } else {
  895. glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
  896. glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
  897. glStencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
  898. }
  899. }
  900. void RasterizerOpenGL::SyncRasterizeEnable() {
  901. auto& flags = maxwell3d->dirty.flags;
  902. if (!flags[Dirty::RasterizeEnable]) {
  903. return;
  904. }
  905. flags[Dirty::RasterizeEnable] = false;
  906. oglEnable(GL_RASTERIZER_DISCARD, maxwell3d->regs.rasterize_enable == 0);
  907. }
  908. void RasterizerOpenGL::SyncPolygonModes() {
  909. auto& flags = maxwell3d->dirty.flags;
  910. if (!flags[Dirty::PolygonModes]) {
  911. return;
  912. }
  913. flags[Dirty::PolygonModes] = false;
  914. const auto& regs = maxwell3d->regs;
  915. if (regs.fill_via_triangle_mode != Maxwell::FillViaTriangleMode::Disabled) {
  916. if (!GLAD_GL_NV_fill_rectangle) {
  917. LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
  918. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  919. return;
  920. }
  921. flags[Dirty::PolygonModeFront] = true;
  922. flags[Dirty::PolygonModeBack] = true;
  923. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
  924. return;
  925. }
  926. if (regs.polygon_mode_front == regs.polygon_mode_back) {
  927. flags[Dirty::PolygonModeFront] = false;
  928. flags[Dirty::PolygonModeBack] = false;
  929. glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  930. return;
  931. }
  932. if (flags[Dirty::PolygonModeFront]) {
  933. flags[Dirty::PolygonModeFront] = false;
  934. glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  935. }
  936. if (flags[Dirty::PolygonModeBack]) {
  937. flags[Dirty::PolygonModeBack] = false;
  938. glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_back));
  939. }
  940. }
  941. void RasterizerOpenGL::SyncColorMask() {
  942. auto& flags = maxwell3d->dirty.flags;
  943. if (!flags[Dirty::ColorMasks]) {
  944. return;
  945. }
  946. flags[Dirty::ColorMasks] = false;
  947. const bool force = flags[Dirty::ColorMaskCommon];
  948. flags[Dirty::ColorMaskCommon] = false;
  949. const auto& regs = maxwell3d->regs;
  950. if (regs.color_mask_common) {
  951. if (!force && !flags[Dirty::ColorMask0]) {
  952. return;
  953. }
  954. flags[Dirty::ColorMask0] = false;
  955. auto& mask = regs.color_mask[0];
  956. glColorMask(mask.R != 0, mask.B != 0, mask.G != 0, mask.A != 0);
  957. return;
  958. }
  959. // Path without color_mask_common set
  960. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  961. if (!force && !flags[Dirty::ColorMask0 + i]) {
  962. continue;
  963. }
  964. flags[Dirty::ColorMask0 + i] = false;
  965. const auto& mask = regs.color_mask[i];
  966. glColorMaski(static_cast<GLuint>(i), mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0);
  967. }
  968. }
  969. void RasterizerOpenGL::SyncMultiSampleState() {
  970. auto& flags = maxwell3d->dirty.flags;
  971. if (!flags[Dirty::MultisampleControl]) {
  972. return;
  973. }
  974. flags[Dirty::MultisampleControl] = false;
  975. const auto& regs = maxwell3d->regs;
  976. oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.anti_alias_alpha_control.alpha_to_coverage);
  977. oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.anti_alias_alpha_control.alpha_to_one);
  978. }
  979. void RasterizerOpenGL::SyncFragmentColorClampState() {
  980. auto& flags = maxwell3d->dirty.flags;
  981. if (!flags[Dirty::FragmentClampColor]) {
  982. return;
  983. }
  984. flags[Dirty::FragmentClampColor] = false;
  985. glClampColor(GL_CLAMP_FRAGMENT_COLOR,
  986. maxwell3d->regs.frag_color_clamp.AnyEnabled() ? GL_TRUE : GL_FALSE);
  987. }
  988. void RasterizerOpenGL::SyncBlendState() {
  989. auto& flags = maxwell3d->dirty.flags;
  990. const auto& regs = maxwell3d->regs;
  991. if (flags[Dirty::BlendColor]) {
  992. flags[Dirty::BlendColor] = false;
  993. glBlendColor(regs.blend_color.r, regs.blend_color.g, regs.blend_color.b,
  994. regs.blend_color.a);
  995. }
  996. // TODO(Rodrigo): Revisit blending, there are several registers we are not reading
  997. if (!flags[Dirty::BlendStates]) {
  998. return;
  999. }
  1000. flags[Dirty::BlendStates] = false;
  1001. if (!regs.blend_per_target_enabled) {
  1002. if (!regs.blend.enable[0]) {
  1003. glDisable(GL_BLEND);
  1004. return;
  1005. }
  1006. glEnable(GL_BLEND);
  1007. glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.color_source),
  1008. MaxwellToGL::BlendFunc(regs.blend.color_dest),
  1009. MaxwellToGL::BlendFunc(regs.blend.alpha_source),
  1010. MaxwellToGL::BlendFunc(regs.blend.alpha_dest));
  1011. glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.color_op),
  1012. MaxwellToGL::BlendEquation(regs.blend.alpha_op));
  1013. return;
  1014. }
  1015. const bool force = flags[Dirty::BlendIndependentEnabled];
  1016. flags[Dirty::BlendIndependentEnabled] = false;
  1017. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  1018. if (!force && !flags[Dirty::BlendState0 + i]) {
  1019. continue;
  1020. }
  1021. flags[Dirty::BlendState0 + i] = false;
  1022. if (!regs.blend.enable[i]) {
  1023. glDisablei(GL_BLEND, static_cast<GLuint>(i));
  1024. continue;
  1025. }
  1026. glEnablei(GL_BLEND, static_cast<GLuint>(i));
  1027. const auto& src = regs.blend_per_target[i];
  1028. glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.color_source),
  1029. MaxwellToGL::BlendFunc(src.color_dest),
  1030. MaxwellToGL::BlendFunc(src.alpha_source),
  1031. MaxwellToGL::BlendFunc(src.alpha_dest));
  1032. glBlendEquationSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendEquation(src.color_op),
  1033. MaxwellToGL::BlendEquation(src.alpha_op));
  1034. }
  1035. }
  1036. void RasterizerOpenGL::SyncLogicOpState() {
  1037. auto& flags = maxwell3d->dirty.flags;
  1038. if (!flags[Dirty::LogicOp]) {
  1039. return;
  1040. }
  1041. flags[Dirty::LogicOp] = false;
  1042. const auto& regs = maxwell3d->regs;
  1043. if (regs.logic_op.enable) {
  1044. glEnable(GL_COLOR_LOGIC_OP);
  1045. glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.op));
  1046. } else {
  1047. glDisable(GL_COLOR_LOGIC_OP);
  1048. }
  1049. }
  1050. void RasterizerOpenGL::SyncScissorTest() {
  1051. auto& flags = maxwell3d->dirty.flags;
  1052. if (!flags[Dirty::Scissors] && !flags[VideoCommon::Dirty::RescaleScissors]) {
  1053. return;
  1054. }
  1055. flags[Dirty::Scissors] = false;
  1056. const bool force = flags[VideoCommon::Dirty::RescaleScissors];
  1057. flags[VideoCommon::Dirty::RescaleScissors] = false;
  1058. const auto& regs = maxwell3d->regs;
  1059. const auto& resolution = Settings::values.resolution_info;
  1060. const bool is_rescaling{texture_cache.IsRescaling()};
  1061. const u32 up_scale = is_rescaling ? resolution.up_scale : 1U;
  1062. const u32 down_shift = is_rescaling ? resolution.down_shift : 0U;
  1063. const auto scale_up = [up_scale, down_shift](u32 value) -> u32 {
  1064. if (value == 0) {
  1065. return 0U;
  1066. }
  1067. const u32 upset = value * up_scale;
  1068. u32 acumm{};
  1069. if ((up_scale >> down_shift) == 0) {
  1070. acumm = upset % 2;
  1071. }
  1072. const u32 converted_value = upset >> down_shift;
  1073. return std::max<u32>(converted_value + acumm, 1U);
  1074. };
  1075. for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
  1076. if (!force && !flags[Dirty::Scissor0 + index]) {
  1077. continue;
  1078. }
  1079. flags[Dirty::Scissor0 + index] = false;
  1080. const auto& src = regs.scissor_test[index];
  1081. if (src.enable) {
  1082. glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  1083. glScissorIndexed(static_cast<GLuint>(index), scale_up(src.min_x), scale_up(src.min_y),
  1084. scale_up(src.max_x - src.min_x), scale_up(src.max_y - src.min_y));
  1085. } else {
  1086. glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  1087. }
  1088. }
  1089. }
  1090. void RasterizerOpenGL::SyncPointState() {
  1091. auto& flags = maxwell3d->dirty.flags;
  1092. if (!flags[Dirty::PointSize]) {
  1093. return;
  1094. }
  1095. flags[Dirty::PointSize] = false;
  1096. oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
  1097. oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled);
  1098. const bool is_rescaling{texture_cache.IsRescaling()};
  1099. const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
  1100. glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
  1101. }
  1102. void RasterizerOpenGL::SyncLineState() {
  1103. auto& flags = maxwell3d->dirty.flags;
  1104. if (!flags[Dirty::LineWidth]) {
  1105. return;
  1106. }
  1107. flags[Dirty::LineWidth] = false;
  1108. const auto& regs = maxwell3d->regs;
  1109. oglEnable(GL_LINE_SMOOTH, regs.line_anti_alias_enable);
  1110. glLineWidth(regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased);
  1111. }
  1112. void RasterizerOpenGL::SyncPolygonOffset() {
  1113. auto& flags = maxwell3d->dirty.flags;
  1114. if (!flags[Dirty::PolygonOffset]) {
  1115. return;
  1116. }
  1117. flags[Dirty::PolygonOffset] = false;
  1118. const auto& regs = maxwell3d->regs;
  1119. oglEnable(GL_POLYGON_OFFSET_FILL, regs.polygon_offset_fill_enable);
  1120. oglEnable(GL_POLYGON_OFFSET_LINE, regs.polygon_offset_line_enable);
  1121. oglEnable(GL_POLYGON_OFFSET_POINT, regs.polygon_offset_point_enable);
  1122. if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
  1123. regs.polygon_offset_point_enable) {
  1124. // Hardware divides polygon offset units by two
  1125. glPolygonOffsetClamp(regs.slope_scale_depth_bias, regs.depth_bias / 2.0f,
  1126. regs.depth_bias_clamp);
  1127. }
  1128. }
  1129. void RasterizerOpenGL::SyncAlphaTest() {
  1130. auto& flags = maxwell3d->dirty.flags;
  1131. if (!flags[Dirty::AlphaTest]) {
  1132. return;
  1133. }
  1134. flags[Dirty::AlphaTest] = false;
  1135. const auto& regs = maxwell3d->regs;
  1136. if (regs.alpha_test_enabled) {
  1137. glEnable(GL_ALPHA_TEST);
  1138. glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref);
  1139. } else {
  1140. glDisable(GL_ALPHA_TEST);
  1141. }
  1142. }
  1143. void RasterizerOpenGL::SyncFramebufferSRGB() {
  1144. auto& flags = maxwell3d->dirty.flags;
  1145. if (!flags[Dirty::FramebufferSRGB]) {
  1146. return;
  1147. }
  1148. flags[Dirty::FramebufferSRGB] = false;
  1149. oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d->regs.framebuffer_srgb);
  1150. }
  1151. void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
  1152. const auto& regs = maxwell3d->regs;
  1153. if (regs.transform_feedback_enabled == 0) {
  1154. return;
  1155. }
  1156. program->ConfigureTransformFeedback();
  1157. UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
  1158. regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation));
  1159. // We may have to call BeginTransformFeedbackNV here since they seem to call different
  1160. // implementations on Nvidia's driver (the pointer is different) but we are using
  1161. // ARB_transform_feedback3 features with NV_transform_feedback interactions and the ARB
  1162. // extension doesn't define BeginTransformFeedback (without NV) interactions. It just works.
  1163. glBeginTransformFeedback(primitive_mode);
  1164. }
  1165. void RasterizerOpenGL::EndTransformFeedback() {
  1166. if (maxwell3d->regs.transform_feedback_enabled != 0) {
  1167. glEndTransformFeedback();
  1168. }
  1169. }
  1170. void RasterizerOpenGL::InitializeChannel(Tegra::Control::ChannelState& channel) {
  1171. CreateChannel(channel);
  1172. {
  1173. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1174. texture_cache.CreateChannel(channel);
  1175. buffer_cache.CreateChannel(channel);
  1176. }
  1177. shader_cache.CreateChannel(channel);
  1178. query_cache.CreateChannel(channel);
  1179. state_tracker.SetupTables(channel);
  1180. }
  1181. void RasterizerOpenGL::BindChannel(Tegra::Control::ChannelState& channel) {
  1182. const s32 channel_id = channel.bind_id;
  1183. BindToChannel(channel_id);
  1184. {
  1185. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1186. texture_cache.BindToChannel(channel_id);
  1187. buffer_cache.BindToChannel(channel_id);
  1188. }
  1189. shader_cache.BindToChannel(channel_id);
  1190. query_cache.BindToChannel(channel_id);
  1191. state_tracker.ChangeChannel(channel);
  1192. state_tracker.InvalidateState();
  1193. }
  1194. void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
  1195. EraseChannel(channel_id);
  1196. {
  1197. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1198. texture_cache.EraseChannel(channel_id);
  1199. buffer_cache.EraseChannel(channel_id);
  1200. }
  1201. shader_cache.EraseChannel(channel_id);
  1202. query_cache.EraseChannel(channel_id);
  1203. }
  1204. void RasterizerOpenGL::RegisterTransformFeedback(GPUVAddr tfb_object_addr) {
  1205. buffer_cache_runtime.BindTransformFeedbackObject(tfb_object_addr);
  1206. }
  1207. AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_)
  1208. : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {}
  1209. bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
  1210. std::scoped_lock lock{buffer_cache.mutex};
  1211. return buffer_cache.DMACopy(src_address, dest_address, amount);
  1212. }
  1213. bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) {
  1214. std::scoped_lock lock{buffer_cache.mutex};
  1215. return buffer_cache.DMAClear(src_address, amount, value);
  1216. }
  1217. template <bool IS_IMAGE_UPLOAD>
  1218. bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
  1219. const Tegra::DMA::BufferOperand& buffer_operand,
  1220. const Tegra::DMA::ImageOperand& image_operand) {
  1221. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  1222. const auto image_id = texture_cache.DmaImageId(image_operand, IS_IMAGE_UPLOAD);
  1223. if (image_id == VideoCommon::NULL_IMAGE_ID) {
  1224. return false;
  1225. }
  1226. const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
  1227. static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
  1228. const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
  1229. : VideoCommon::ObtainBufferOperation::MarkAsWritten;
  1230. const auto [buffer, offset] =
  1231. buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
  1232. const auto [image, copy] = texture_cache.DmaBufferImageCopy(
  1233. copy_info, buffer_operand, image_operand, image_id, IS_IMAGE_UPLOAD);
  1234. const std::span copy_span{&copy, 1};
  1235. if constexpr (IS_IMAGE_UPLOAD) {
  1236. texture_cache.PrepareImage(image_id, true, false);
  1237. image->UploadMemory(buffer->Handle(), offset, copy_span);
  1238. } else {
  1239. if (offset % BytesPerBlock(image->info.format)) {
  1240. return false;
  1241. }
  1242. texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
  1243. buffer_operand.address, buffer_size);
  1244. }
  1245. return true;
  1246. }
  1247. bool AccelerateDMA::ImageToBuffer(const Tegra::DMA::ImageCopy& copy_info,
  1248. const Tegra::DMA::ImageOperand& image_operand,
  1249. const Tegra::DMA::BufferOperand& buffer_operand) {
  1250. return DmaBufferImageCopy<false>(copy_info, buffer_operand, image_operand);
  1251. }
  1252. bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
  1253. const Tegra::DMA::BufferOperand& buffer_operand,
  1254. const Tegra::DMA::ImageOperand& image_operand) {
  1255. return DmaBufferImageCopy<true>(copy_info, buffer_operand, image_operand);
  1256. }
  1257. } // namespace OpenGL