gl_rasterizer.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <bitset>
  7. #include <memory>
  8. #include <string>
  9. #include <string_view>
  10. #include <tuple>
  11. #include <utility>
  12. #include <glad/glad.h>
  13. #include "common/alignment.h"
  14. #include "common/assert.h"
  15. #include "common/logging/log.h"
  16. #include "common/math_util.h"
  17. #include "common/microprofile.h"
  18. #include "common/scope_exit.h"
  19. #include "common/settings.h"
  20. #include "core/core.h"
  21. #include "core/hle/kernel/k_process.h"
  22. #include "core/memory.h"
  23. #include "video_core/engines/kepler_compute.h"
  24. #include "video_core/engines/maxwell_3d.h"
  25. #include "video_core/memory_manager.h"
  26. #include "video_core/renderer_opengl/gl_device.h"
  27. #include "video_core/renderer_opengl/gl_query_cache.h"
  28. #include "video_core/renderer_opengl/gl_rasterizer.h"
  29. #include "video_core/renderer_opengl/gl_shader_cache.h"
  30. #include "video_core/renderer_opengl/gl_texture_cache.h"
  31. #include "video_core/renderer_opengl/maxwell_to_gl.h"
  32. #include "video_core/renderer_opengl/renderer_opengl.h"
  33. #include "video_core/shader_cache.h"
  34. #include "video_core/texture_cache/texture_cache.h"
  35. namespace OpenGL {
  36. using Maxwell = Tegra::Engines::Maxwell3D::Regs;
  37. using GLvec4 = std::array<GLfloat, 4>;
  38. using VideoCore::Surface::PixelFormat;
  39. using VideoCore::Surface::SurfaceTarget;
  40. using VideoCore::Surface::SurfaceType;
  41. MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
  42. MICROPROFILE_DEFINE(OpenGL_Clears, "OpenGL", "Clears", MP_RGB(128, 128, 192));
  43. MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(128, 128, 192));
  44. MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB(100, 255, 100));
  45. namespace {
  46. constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16;
  47. void oglEnable(GLenum cap, bool state) {
  48. (state ? glEnable : glDisable)(cap);
  49. }
  50. } // Anonymous namespace
  51. RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
  52. Core::Memory::Memory& cpu_memory_, const Device& device_,
  53. ScreenInfo& screen_info_, ProgramManager& program_manager_,
  54. StateTracker& state_tracker_)
  55. : RasterizerAccelerated(cpu_memory_), gpu(gpu_), maxwell3d(gpu.Maxwell3D()),
  56. kepler_compute(gpu.KeplerCompute()), gpu_memory(gpu.MemoryManager()), device(device_),
  57. screen_info(screen_info_), program_manager(program_manager_), state_tracker(state_tracker_),
  58. texture_cache_runtime(device, program_manager, state_tracker),
  59. texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory),
  60. buffer_cache_runtime(device),
  61. buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime),
  62. shader_cache(*this, emu_window_, maxwell3d, kepler_compute, gpu_memory, device, texture_cache,
  63. buffer_cache, program_manager, state_tracker, gpu.ShaderNotify()),
  64. query_cache(*this, maxwell3d, gpu_memory), accelerate_dma(buffer_cache),
  65. fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache) {}
  66. RasterizerOpenGL::~RasterizerOpenGL() = default;
  67. void RasterizerOpenGL::SyncVertexFormats() {
  68. auto& flags = maxwell3d.dirty.flags;
  69. if (!flags[Dirty::VertexFormats]) {
  70. return;
  71. }
  72. flags[Dirty::VertexFormats] = false;
  73. // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. Enables
  74. // the first 16 vertex attributes always, as we don't know which ones are actually used until
  75. // shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now to
  76. // avoid OpenGL errors.
  77. // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
  78. // assume every shader uses them all.
  79. for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) {
  80. if (!flags[Dirty::VertexFormat0 + index]) {
  81. continue;
  82. }
  83. flags[Dirty::VertexFormat0 + index] = false;
  84. const auto attrib = maxwell3d.regs.vertex_attrib_format[index];
  85. const auto gl_index = static_cast<GLuint>(index);
  86. // Disable constant attributes.
  87. if (attrib.constant) {
  88. glDisableVertexAttribArray(gl_index);
  89. continue;
  90. }
  91. glEnableVertexAttribArray(gl_index);
  92. if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
  93. attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
  94. glVertexAttribIFormat(gl_index, attrib.ComponentCount(),
  95. MaxwellToGL::VertexFormat(attrib), attrib.offset);
  96. } else {
  97. glVertexAttribFormat(gl_index, attrib.ComponentCount(),
  98. MaxwellToGL::VertexFormat(attrib),
  99. attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
  100. }
  101. glVertexAttribBinding(gl_index, attrib.buffer);
  102. }
  103. }
  104. void RasterizerOpenGL::SyncVertexInstances() {
  105. auto& flags = maxwell3d.dirty.flags;
  106. if (!flags[Dirty::VertexInstances]) {
  107. return;
  108. }
  109. flags[Dirty::VertexInstances] = false;
  110. const auto& regs = maxwell3d.regs;
  111. for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) {
  112. if (!flags[Dirty::VertexInstance0 + index]) {
  113. continue;
  114. }
  115. flags[Dirty::VertexInstance0 + index] = false;
  116. const auto gl_index = static_cast<GLuint>(index);
  117. const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index);
  118. const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0;
  119. glVertexBindingDivisor(gl_index, divisor);
  120. }
  121. }
  122. void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
  123. const VideoCore::DiskResourceLoadCallback& callback) {
  124. shader_cache.LoadDiskResources(title_id, stop_loading, callback);
  125. }
  126. void RasterizerOpenGL::Clear() {
  127. MICROPROFILE_SCOPE(OpenGL_Clears);
  128. if (!maxwell3d.ShouldExecute()) {
  129. return;
  130. }
  131. const auto& regs = maxwell3d.regs;
  132. bool use_color{};
  133. bool use_depth{};
  134. bool use_stencil{};
  135. if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
  136. regs.clear_buffers.A) {
  137. use_color = true;
  138. const GLuint index = regs.clear_buffers.RT;
  139. state_tracker.NotifyColorMask(index);
  140. glColorMaski(index, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
  141. regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
  142. // TODO(Rodrigo): Determine if clamping is used on clears
  143. SyncFragmentColorClampState();
  144. SyncFramebufferSRGB();
  145. }
  146. if (regs.clear_buffers.Z) {
  147. ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
  148. use_depth = true;
  149. state_tracker.NotifyDepthMask();
  150. glDepthMask(GL_TRUE);
  151. }
  152. if (regs.clear_buffers.S) {
  153. ASSERT_MSG(regs.zeta_enable, "Tried to clear stencil but buffer is not enabled!");
  154. use_stencil = true;
  155. }
  156. if (!use_color && !use_depth && !use_stencil) {
  157. // No color surface nor depth/stencil surface are enabled
  158. return;
  159. }
  160. SyncRasterizeEnable();
  161. SyncStencilTestState();
  162. if (regs.clear_flags.scissor) {
  163. SyncScissorTest();
  164. } else {
  165. state_tracker.NotifyScissor0();
  166. glDisablei(GL_SCISSOR_TEST, 0);
  167. }
  168. UNIMPLEMENTED_IF(regs.clear_flags.viewport);
  169. std::scoped_lock lock{texture_cache.mutex};
  170. texture_cache.UpdateRenderTargets(true);
  171. state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
  172. if (use_color) {
  173. glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
  174. }
  175. if (use_depth && use_stencil) {
  176. glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
  177. } else if (use_depth) {
  178. glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
  179. } else if (use_stencil) {
  180. glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
  181. }
  182. ++num_queued_commands;
  183. }
  184. void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
  185. MICROPROFILE_SCOPE(OpenGL_Drawing);
  186. query_cache.UpdateCounters();
  187. SyncState();
  188. GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()};
  189. if (!pipeline) {
  190. return;
  191. }
  192. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  193. pipeline->Configure(is_indexed);
  194. const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d.regs.draw.topology);
  195. BeginTransformFeedback(pipeline, primitive_mode);
  196. const GLuint base_instance = static_cast<GLuint>(maxwell3d.regs.vb_base_instance);
  197. const GLsizei num_instances =
  198. static_cast<GLsizei>(is_instanced ? maxwell3d.mme_draw.instance_count : 1);
  199. if (is_indexed) {
  200. const GLint base_vertex = static_cast<GLint>(maxwell3d.regs.vb_element_base);
  201. const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d.regs.index_array.count);
  202. const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
  203. const GLenum format = MaxwellToGL::IndexFormat(maxwell3d.regs.index_array.format);
  204. if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
  205. glDrawElements(primitive_mode, num_vertices, format, offset);
  206. } else if (num_instances == 1 && base_instance == 0) {
  207. glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex);
  208. } else if (base_vertex == 0 && base_instance == 0) {
  209. glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, num_instances);
  210. } else if (base_vertex == 0) {
  211. glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset,
  212. num_instances, base_instance);
  213. } else if (base_instance == 0) {
  214. glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset,
  215. num_instances, base_vertex);
  216. } else {
  217. glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format,
  218. offset, num_instances, base_vertex,
  219. base_instance);
  220. }
  221. } else {
  222. const GLint base_vertex = static_cast<GLint>(maxwell3d.regs.vertex_buffer.first);
  223. const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d.regs.vertex_buffer.count);
  224. if (num_instances == 1 && base_instance == 0) {
  225. glDrawArrays(primitive_mode, base_vertex, num_vertices);
  226. } else if (base_instance == 0) {
  227. glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances);
  228. } else {
  229. glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices,
  230. num_instances, base_instance);
  231. }
  232. }
  233. EndTransformFeedback();
  234. ++num_queued_commands;
  235. has_written_global_memory |= pipeline->WritesGlobalMemory();
  236. gpu.TickWork();
  237. }
  238. void RasterizerOpenGL::DispatchCompute() {
  239. ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
  240. if (!pipeline) {
  241. return;
  242. }
  243. pipeline->Configure();
  244. const auto& qmd{kepler_compute.launch_description};
  245. glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
  246. ++num_queued_commands;
  247. has_written_global_memory |= pipeline->WritesGlobalMemory();
  248. }
  249. void RasterizerOpenGL::ResetCounter(VideoCore::QueryType type) {
  250. query_cache.ResetCounter(type);
  251. }
  252. void RasterizerOpenGL::Query(GPUVAddr gpu_addr, VideoCore::QueryType type,
  253. std::optional<u64> timestamp) {
  254. query_cache.Query(gpu_addr, type, timestamp);
  255. }
  256. void RasterizerOpenGL::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
  257. u32 size) {
  258. std::scoped_lock lock{buffer_cache.mutex};
  259. buffer_cache.BindGraphicsUniformBuffer(stage, index, gpu_addr, size);
  260. }
  261. void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
  262. buffer_cache.DisableGraphicsUniformBuffer(stage, index);
  263. }
  264. void RasterizerOpenGL::FlushAll() {}
  265. void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
  266. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  267. if (addr == 0 || size == 0) {
  268. return;
  269. }
  270. {
  271. std::scoped_lock lock{texture_cache.mutex};
  272. texture_cache.DownloadMemory(addr, size);
  273. }
  274. {
  275. std::scoped_lock lock{buffer_cache.mutex};
  276. buffer_cache.DownloadMemory(addr, size);
  277. }
  278. query_cache.FlushRegion(addr, size);
  279. }
  280. bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) {
  281. std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
  282. if (!Settings::IsGPULevelHigh()) {
  283. return buffer_cache.IsRegionGpuModified(addr, size);
  284. }
  285. return texture_cache.IsRegionGpuModified(addr, size) ||
  286. buffer_cache.IsRegionGpuModified(addr, size);
  287. }
  288. void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
  289. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  290. if (addr == 0 || size == 0) {
  291. return;
  292. }
  293. {
  294. std::scoped_lock lock{texture_cache.mutex};
  295. texture_cache.WriteMemory(addr, size);
  296. }
  297. {
  298. std::scoped_lock lock{buffer_cache.mutex};
  299. buffer_cache.WriteMemory(addr, size);
  300. }
  301. shader_cache.InvalidateRegion(addr, size);
  302. query_cache.InvalidateRegion(addr, size);
  303. }
  304. void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
  305. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  306. if (addr == 0 || size == 0) {
  307. return;
  308. }
  309. shader_cache.OnCPUWrite(addr, size);
  310. {
  311. std::scoped_lock lock{texture_cache.mutex};
  312. texture_cache.WriteMemory(addr, size);
  313. }
  314. {
  315. std::scoped_lock lock{buffer_cache.mutex};
  316. buffer_cache.CachedWriteMemory(addr, size);
  317. }
  318. }
  319. void RasterizerOpenGL::SyncGuestHost() {
  320. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  321. shader_cache.SyncGuestHost();
  322. {
  323. std::scoped_lock lock{buffer_cache.mutex};
  324. buffer_cache.FlushCachedWrites();
  325. }
  326. }
  327. void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) {
  328. {
  329. std::scoped_lock lock{texture_cache.mutex};
  330. texture_cache.UnmapMemory(addr, size);
  331. }
  332. {
  333. std::scoped_lock lock{buffer_cache.mutex};
  334. buffer_cache.WriteMemory(addr, size);
  335. }
  336. shader_cache.OnCPUWrite(addr, size);
  337. }
  338. void RasterizerOpenGL::ModifyGPUMemory(GPUVAddr addr, u64 size) {
  339. {
  340. std::scoped_lock lock{texture_cache.mutex};
  341. texture_cache.UnmapGPUMemory(addr, size);
  342. }
  343. }
  344. void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) {
  345. if (!gpu.IsAsync()) {
  346. gpu_memory.Write<u32>(addr, value);
  347. return;
  348. }
  349. fence_manager.SignalSemaphore(addr, value);
  350. }
  351. void RasterizerOpenGL::SignalSyncPoint(u32 value) {
  352. if (!gpu.IsAsync()) {
  353. gpu.IncrementSyncPoint(value);
  354. return;
  355. }
  356. fence_manager.SignalSyncPoint(value);
  357. }
  358. void RasterizerOpenGL::SignalReference() {
  359. if (!gpu.IsAsync()) {
  360. return;
  361. }
  362. fence_manager.SignalOrdering();
  363. }
  364. void RasterizerOpenGL::ReleaseFences() {
  365. if (!gpu.IsAsync()) {
  366. return;
  367. }
  368. fence_manager.WaitPendingFences();
  369. }
  370. void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
  371. if (Settings::IsGPULevelExtreme()) {
  372. FlushRegion(addr, size);
  373. }
  374. InvalidateRegion(addr, size);
  375. }
  376. void RasterizerOpenGL::WaitForIdle() {
  377. glMemoryBarrier(GL_ALL_BARRIER_BITS);
  378. SignalReference();
  379. }
  380. void RasterizerOpenGL::FragmentBarrier() {
  381. glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
  382. }
  383. void RasterizerOpenGL::TiledCacheBarrier() {
  384. glTextureBarrier();
  385. }
  386. void RasterizerOpenGL::FlushCommands() {
  387. // Only flush when we have commands queued to OpenGL.
  388. if (num_queued_commands == 0) {
  389. return;
  390. }
  391. num_queued_commands = 0;
  392. // Make sure memory stored from the previous GL command stream is visible
  393. // This is only needed on assembly shaders where we write to GPU memory with raw pointers
  394. if (has_written_global_memory) {
  395. has_written_global_memory = false;
  396. glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
  397. }
  398. glFlush();
  399. }
  400. void RasterizerOpenGL::TickFrame() {
  401. // Ticking a frame means that buffers will be swapped, calling glFlush implicitly.
  402. num_queued_commands = 0;
  403. fence_manager.TickFrame();
  404. {
  405. std::scoped_lock lock{texture_cache.mutex};
  406. texture_cache.TickFrame();
  407. }
  408. {
  409. std::scoped_lock lock{buffer_cache.mutex};
  410. buffer_cache.TickFrame();
  411. }
  412. }
  413. bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
  414. const Tegra::Engines::Fermi2D::Surface& dst,
  415. const Tegra::Engines::Fermi2D::Config& copy_config) {
  416. MICROPROFILE_SCOPE(OpenGL_Blits);
  417. std::scoped_lock lock{texture_cache.mutex};
  418. texture_cache.BlitImage(dst, src, copy_config);
  419. return true;
  420. }
  421. Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA() {
  422. return accelerate_dma;
  423. }
  424. bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
  425. VAddr framebuffer_addr, u32 pixel_stride) {
  426. if (framebuffer_addr == 0) {
  427. return false;
  428. }
  429. MICROPROFILE_SCOPE(OpenGL_CacheManagement);
  430. std::scoped_lock lock{texture_cache.mutex};
  431. ImageView* const image_view{texture_cache.TryFindFramebufferImageView(framebuffer_addr)};
  432. if (!image_view) {
  433. return false;
  434. }
  435. // Verify that the cached surface is the same size and format as the requested framebuffer
  436. // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
  437. // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
  438. screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
  439. screen_info.display_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format);
  440. return true;
  441. }
  442. void RasterizerOpenGL::SyncState() {
  443. SyncViewport();
  444. SyncRasterizeEnable();
  445. SyncPolygonModes();
  446. SyncColorMask();
  447. SyncFragmentColorClampState();
  448. SyncMultiSampleState();
  449. SyncDepthTestState();
  450. SyncDepthClamp();
  451. SyncStencilTestState();
  452. SyncBlendState();
  453. SyncLogicOpState();
  454. SyncCullMode();
  455. SyncPrimitiveRestart();
  456. SyncScissorTest();
  457. SyncPointState();
  458. SyncLineState();
  459. SyncPolygonOffset();
  460. SyncAlphaTest();
  461. SyncFramebufferSRGB();
  462. SyncVertexFormats();
  463. SyncVertexInstances();
  464. }
  465. void RasterizerOpenGL::SyncViewport() {
  466. auto& flags = maxwell3d.dirty.flags;
  467. const auto& regs = maxwell3d.regs;
  468. const bool dirty_viewport = flags[Dirty::Viewports];
  469. const bool dirty_clip_control = flags[Dirty::ClipControl];
  470. if (dirty_clip_control || flags[Dirty::FrontFace]) {
  471. flags[Dirty::FrontFace] = false;
  472. GLenum mode = MaxwellToGL::FrontFace(regs.front_face);
  473. if (regs.screen_y_control.triangle_rast_flip != 0 &&
  474. regs.viewport_transform[0].scale_y < 0.0f) {
  475. switch (mode) {
  476. case GL_CW:
  477. mode = GL_CCW;
  478. break;
  479. case GL_CCW:
  480. mode = GL_CW;
  481. break;
  482. }
  483. }
  484. glFrontFace(mode);
  485. }
  486. if (dirty_viewport || flags[Dirty::ClipControl]) {
  487. flags[Dirty::ClipControl] = false;
  488. bool flip_y = false;
  489. if (regs.viewport_transform[0].scale_y < 0.0f) {
  490. flip_y = !flip_y;
  491. }
  492. if (regs.screen_y_control.y_negate != 0) {
  493. flip_y = !flip_y;
  494. }
  495. const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
  496. const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
  497. const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
  498. state_tracker.ClipControl(origin, depth);
  499. state_tracker.SetYNegate(regs.screen_y_control.y_negate != 0);
  500. }
  501. if (dirty_viewport) {
  502. flags[Dirty::Viewports] = false;
  503. const bool force = flags[Dirty::ViewportTransform];
  504. flags[Dirty::ViewportTransform] = false;
  505. for (std::size_t i = 0; i < Maxwell::NumViewports; ++i) {
  506. if (!force && !flags[Dirty::Viewport0 + i]) {
  507. continue;
  508. }
  509. flags[Dirty::Viewport0 + i] = false;
  510. const auto& src = regs.viewport_transform[i];
  511. const Common::Rectangle<f32> rect{src.GetRect()};
  512. glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(),
  513. rect.GetHeight());
  514. const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
  515. const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
  516. const GLdouble far_depth = src.translate_z + src.scale_z;
  517. if (device.HasDepthBufferFloat()) {
  518. glDepthRangeIndexeddNV(static_cast<GLuint>(i), near_depth, far_depth);
  519. } else {
  520. glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth);
  521. }
  522. if (!GLAD_GL_NV_viewport_swizzle) {
  523. continue;
  524. }
  525. glViewportSwizzleNV(static_cast<GLuint>(i), MaxwellToGL::ViewportSwizzle(src.swizzle.x),
  526. MaxwellToGL::ViewportSwizzle(src.swizzle.y),
  527. MaxwellToGL::ViewportSwizzle(src.swizzle.z),
  528. MaxwellToGL::ViewportSwizzle(src.swizzle.w));
  529. }
  530. }
  531. }
  532. void RasterizerOpenGL::SyncDepthClamp() {
  533. auto& flags = maxwell3d.dirty.flags;
  534. if (!flags[Dirty::DepthClampEnabled]) {
  535. return;
  536. }
  537. flags[Dirty::DepthClampEnabled] = false;
  538. oglEnable(GL_DEPTH_CLAMP, maxwell3d.regs.view_volume_clip_control.depth_clamp_disabled == 0);
  539. }
  540. void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
  541. auto& flags = maxwell3d.dirty.flags;
  542. if (!flags[Dirty::ClipDistances] && !flags[VideoCommon::Dirty::Shaders]) {
  543. return;
  544. }
  545. flags[Dirty::ClipDistances] = false;
  546. clip_mask &= maxwell3d.regs.clip_distance_enabled;
  547. if (clip_mask == last_clip_distance_mask) {
  548. return;
  549. }
  550. last_clip_distance_mask = clip_mask;
  551. for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) {
  552. oglEnable(static_cast<GLenum>(GL_CLIP_DISTANCE0 + i), (clip_mask >> i) & 1);
  553. }
  554. }
  555. void RasterizerOpenGL::SyncClipCoef() {
  556. UNIMPLEMENTED();
  557. }
  558. void RasterizerOpenGL::SyncCullMode() {
  559. auto& flags = maxwell3d.dirty.flags;
  560. const auto& regs = maxwell3d.regs;
  561. if (flags[Dirty::CullTest]) {
  562. flags[Dirty::CullTest] = false;
  563. if (regs.cull_test_enabled) {
  564. glEnable(GL_CULL_FACE);
  565. glCullFace(MaxwellToGL::CullFace(regs.cull_face));
  566. } else {
  567. glDisable(GL_CULL_FACE);
  568. }
  569. }
  570. }
  571. void RasterizerOpenGL::SyncPrimitiveRestart() {
  572. auto& flags = maxwell3d.dirty.flags;
  573. if (!flags[Dirty::PrimitiveRestart]) {
  574. return;
  575. }
  576. flags[Dirty::PrimitiveRestart] = false;
  577. if (maxwell3d.regs.primitive_restart.enabled) {
  578. glEnable(GL_PRIMITIVE_RESTART);
  579. glPrimitiveRestartIndex(maxwell3d.regs.primitive_restart.index);
  580. } else {
  581. glDisable(GL_PRIMITIVE_RESTART);
  582. }
  583. }
  584. void RasterizerOpenGL::SyncDepthTestState() {
  585. auto& flags = maxwell3d.dirty.flags;
  586. const auto& regs = maxwell3d.regs;
  587. if (flags[Dirty::DepthMask]) {
  588. flags[Dirty::DepthMask] = false;
  589. glDepthMask(regs.depth_write_enabled ? GL_TRUE : GL_FALSE);
  590. }
  591. if (flags[Dirty::DepthTest]) {
  592. flags[Dirty::DepthTest] = false;
  593. if (regs.depth_test_enable) {
  594. glEnable(GL_DEPTH_TEST);
  595. glDepthFunc(MaxwellToGL::ComparisonOp(regs.depth_test_func));
  596. } else {
  597. glDisable(GL_DEPTH_TEST);
  598. }
  599. }
  600. }
  601. void RasterizerOpenGL::SyncStencilTestState() {
  602. auto& flags = maxwell3d.dirty.flags;
  603. if (!flags[Dirty::StencilTest]) {
  604. return;
  605. }
  606. flags[Dirty::StencilTest] = false;
  607. const auto& regs = maxwell3d.regs;
  608. oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
  609. glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_func_func),
  610. regs.stencil_front_func_ref, regs.stencil_front_func_mask);
  611. glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op_fail),
  612. MaxwellToGL::StencilOp(regs.stencil_front_op_zfail),
  613. MaxwellToGL::StencilOp(regs.stencil_front_op_zpass));
  614. glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
  615. if (regs.stencil_two_side_enable) {
  616. glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_func_func),
  617. regs.stencil_back_func_ref, regs.stencil_back_func_mask);
  618. glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op_fail),
  619. MaxwellToGL::StencilOp(regs.stencil_back_op_zfail),
  620. MaxwellToGL::StencilOp(regs.stencil_back_op_zpass));
  621. glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
  622. } else {
  623. glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
  624. glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
  625. glStencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
  626. }
  627. }
  628. void RasterizerOpenGL::SyncRasterizeEnable() {
  629. auto& flags = maxwell3d.dirty.flags;
  630. if (!flags[Dirty::RasterizeEnable]) {
  631. return;
  632. }
  633. flags[Dirty::RasterizeEnable] = false;
  634. oglEnable(GL_RASTERIZER_DISCARD, maxwell3d.regs.rasterize_enable == 0);
  635. }
  636. void RasterizerOpenGL::SyncPolygonModes() {
  637. auto& flags = maxwell3d.dirty.flags;
  638. if (!flags[Dirty::PolygonModes]) {
  639. return;
  640. }
  641. flags[Dirty::PolygonModes] = false;
  642. const auto& regs = maxwell3d.regs;
  643. if (regs.fill_rectangle) {
  644. if (!GLAD_GL_NV_fill_rectangle) {
  645. LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
  646. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  647. return;
  648. }
  649. flags[Dirty::PolygonModeFront] = true;
  650. flags[Dirty::PolygonModeBack] = true;
  651. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
  652. return;
  653. }
  654. if (regs.polygon_mode_front == regs.polygon_mode_back) {
  655. flags[Dirty::PolygonModeFront] = false;
  656. flags[Dirty::PolygonModeBack] = false;
  657. glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  658. return;
  659. }
  660. if (flags[Dirty::PolygonModeFront]) {
  661. flags[Dirty::PolygonModeFront] = false;
  662. glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(regs.polygon_mode_front));
  663. }
  664. if (flags[Dirty::PolygonModeBack]) {
  665. flags[Dirty::PolygonModeBack] = false;
  666. glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(regs.polygon_mode_back));
  667. }
  668. }
  669. void RasterizerOpenGL::SyncColorMask() {
  670. auto& flags = maxwell3d.dirty.flags;
  671. if (!flags[Dirty::ColorMasks]) {
  672. return;
  673. }
  674. flags[Dirty::ColorMasks] = false;
  675. const bool force = flags[Dirty::ColorMaskCommon];
  676. flags[Dirty::ColorMaskCommon] = false;
  677. const auto& regs = maxwell3d.regs;
  678. if (regs.color_mask_common) {
  679. if (!force && !flags[Dirty::ColorMask0]) {
  680. return;
  681. }
  682. flags[Dirty::ColorMask0] = false;
  683. auto& mask = regs.color_mask[0];
  684. glColorMask(mask.R != 0, mask.B != 0, mask.G != 0, mask.A != 0);
  685. return;
  686. }
  687. // Path without color_mask_common set
  688. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  689. if (!force && !flags[Dirty::ColorMask0 + i]) {
  690. continue;
  691. }
  692. flags[Dirty::ColorMask0 + i] = false;
  693. const auto& mask = regs.color_mask[i];
  694. glColorMaski(static_cast<GLuint>(i), mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0);
  695. }
  696. }
  697. void RasterizerOpenGL::SyncMultiSampleState() {
  698. auto& flags = maxwell3d.dirty.flags;
  699. if (!flags[Dirty::MultisampleControl]) {
  700. return;
  701. }
  702. flags[Dirty::MultisampleControl] = false;
  703. const auto& regs = maxwell3d.regs;
  704. oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage);
  705. oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one);
  706. }
  707. void RasterizerOpenGL::SyncFragmentColorClampState() {
  708. auto& flags = maxwell3d.dirty.flags;
  709. if (!flags[Dirty::FragmentClampColor]) {
  710. return;
  711. }
  712. flags[Dirty::FragmentClampColor] = false;
  713. glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d.regs.frag_color_clamp ? GL_TRUE : GL_FALSE);
  714. }
  715. void RasterizerOpenGL::SyncBlendState() {
  716. auto& flags = maxwell3d.dirty.flags;
  717. const auto& regs = maxwell3d.regs;
  718. if (flags[Dirty::BlendColor]) {
  719. flags[Dirty::BlendColor] = false;
  720. glBlendColor(regs.blend_color.r, regs.blend_color.g, regs.blend_color.b,
  721. regs.blend_color.a);
  722. }
  723. // TODO(Rodrigo): Revisit blending, there are several registers we are not reading
  724. if (!flags[Dirty::BlendStates]) {
  725. return;
  726. }
  727. flags[Dirty::BlendStates] = false;
  728. if (!regs.independent_blend_enable) {
  729. if (!regs.blend.enable[0]) {
  730. glDisable(GL_BLEND);
  731. return;
  732. }
  733. glEnable(GL_BLEND);
  734. glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb),
  735. MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb),
  736. MaxwellToGL::BlendFunc(regs.blend.factor_source_a),
  737. MaxwellToGL::BlendFunc(regs.blend.factor_dest_a));
  738. glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.equation_rgb),
  739. MaxwellToGL::BlendEquation(regs.blend.equation_a));
  740. return;
  741. }
  742. const bool force = flags[Dirty::BlendIndependentEnabled];
  743. flags[Dirty::BlendIndependentEnabled] = false;
  744. for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
  745. if (!force && !flags[Dirty::BlendState0 + i]) {
  746. continue;
  747. }
  748. flags[Dirty::BlendState0 + i] = false;
  749. if (!regs.blend.enable[i]) {
  750. glDisablei(GL_BLEND, static_cast<GLuint>(i));
  751. continue;
  752. }
  753. glEnablei(GL_BLEND, static_cast<GLuint>(i));
  754. const auto& src = regs.independent_blend[i];
  755. glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.factor_source_rgb),
  756. MaxwellToGL::BlendFunc(src.factor_dest_rgb),
  757. MaxwellToGL::BlendFunc(src.factor_source_a),
  758. MaxwellToGL::BlendFunc(src.factor_dest_a));
  759. glBlendEquationSeparatei(static_cast<GLuint>(i),
  760. MaxwellToGL::BlendEquation(src.equation_rgb),
  761. MaxwellToGL::BlendEquation(src.equation_a));
  762. }
  763. }
  764. void RasterizerOpenGL::SyncLogicOpState() {
  765. auto& flags = maxwell3d.dirty.flags;
  766. if (!flags[Dirty::LogicOp]) {
  767. return;
  768. }
  769. flags[Dirty::LogicOp] = false;
  770. const auto& regs = maxwell3d.regs;
  771. if (regs.logic_op.enable) {
  772. glEnable(GL_COLOR_LOGIC_OP);
  773. glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation));
  774. } else {
  775. glDisable(GL_COLOR_LOGIC_OP);
  776. }
  777. }
  778. void RasterizerOpenGL::SyncScissorTest() {
  779. auto& flags = maxwell3d.dirty.flags;
  780. if (!flags[Dirty::Scissors]) {
  781. return;
  782. }
  783. flags[Dirty::Scissors] = false;
  784. const auto& regs = maxwell3d.regs;
  785. for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
  786. if (!flags[Dirty::Scissor0 + index]) {
  787. continue;
  788. }
  789. flags[Dirty::Scissor0 + index] = false;
  790. const auto& src = regs.scissor_test[index];
  791. if (src.enable) {
  792. glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  793. glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y,
  794. src.max_x - src.min_x, src.max_y - src.min_y);
  795. } else {
  796. glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
  797. }
  798. }
  799. }
  800. void RasterizerOpenGL::SyncPointState() {
  801. auto& flags = maxwell3d.dirty.flags;
  802. if (!flags[Dirty::PointSize]) {
  803. return;
  804. }
  805. flags[Dirty::PointSize] = false;
  806. oglEnable(GL_POINT_SPRITE, maxwell3d.regs.point_sprite_enable);
  807. oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d.regs.vp_point_size.enable);
  808. glPointSize(std::max(1.0f, maxwell3d.regs.point_size));
  809. }
  810. void RasterizerOpenGL::SyncLineState() {
  811. auto& flags = maxwell3d.dirty.flags;
  812. if (!flags[Dirty::LineWidth]) {
  813. return;
  814. }
  815. flags[Dirty::LineWidth] = false;
  816. const auto& regs = maxwell3d.regs;
  817. oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable);
  818. glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased);
  819. }
  820. void RasterizerOpenGL::SyncPolygonOffset() {
  821. auto& flags = maxwell3d.dirty.flags;
  822. if (!flags[Dirty::PolygonOffset]) {
  823. return;
  824. }
  825. flags[Dirty::PolygonOffset] = false;
  826. const auto& regs = maxwell3d.regs;
  827. oglEnable(GL_POLYGON_OFFSET_FILL, regs.polygon_offset_fill_enable);
  828. oglEnable(GL_POLYGON_OFFSET_LINE, regs.polygon_offset_line_enable);
  829. oglEnable(GL_POLYGON_OFFSET_POINT, regs.polygon_offset_point_enable);
  830. if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
  831. regs.polygon_offset_point_enable) {
  832. // Hardware divides polygon offset units by two
  833. glPolygonOffsetClamp(regs.polygon_offset_factor, regs.polygon_offset_units / 2.0f,
  834. regs.polygon_offset_clamp);
  835. }
  836. }
  837. void RasterizerOpenGL::SyncAlphaTest() {
  838. auto& flags = maxwell3d.dirty.flags;
  839. if (!flags[Dirty::AlphaTest]) {
  840. return;
  841. }
  842. flags[Dirty::AlphaTest] = false;
  843. const auto& regs = maxwell3d.regs;
  844. if (regs.alpha_test_enabled) {
  845. glEnable(GL_ALPHA_TEST);
  846. glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref);
  847. } else {
  848. glDisable(GL_ALPHA_TEST);
  849. }
  850. }
  851. void RasterizerOpenGL::SyncFramebufferSRGB() {
  852. auto& flags = maxwell3d.dirty.flags;
  853. if (!flags[Dirty::FramebufferSRGB]) {
  854. return;
  855. }
  856. flags[Dirty::FramebufferSRGB] = false;
  857. oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d.regs.framebuffer_srgb);
  858. }
  859. void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
  860. const auto& regs = maxwell3d.regs;
  861. if (regs.tfb_enabled == 0) {
  862. return;
  863. }
  864. program->ConfigureTransformFeedback();
  865. UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
  866. regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
  867. regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
  868. UNIMPLEMENTED_IF(primitive_mode != GL_POINTS);
  869. // We may have to call BeginTransformFeedbackNV here since they seem to call different
  870. // implementations on Nvidia's driver (the pointer is different) but we are using
  871. // ARB_transform_feedback3 features with NV_transform_feedback interactions and the ARB
  872. // extension doesn't define BeginTransformFeedback (without NV) interactions. It just works.
  873. glBeginTransformFeedback(GL_POINTS);
  874. }
  875. void RasterizerOpenGL::EndTransformFeedback() {
  876. if (maxwell3d.regs.tfb_enabled != 0) {
  877. glEndTransformFeedback();
  878. }
  879. }
  880. AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
  881. bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
  882. std::scoped_lock lock{buffer_cache.mutex};
  883. return buffer_cache.DMACopy(src_address, dest_address, amount);
  884. }
  885. bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) {
  886. std::scoped_lock lock{buffer_cache.mutex};
  887. return buffer_cache.DMAClear(src_address, amount, value);
  888. }
  889. } // namespace OpenGL