gl_rasterizer.cpp 49 KB

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