gl_rasterizer.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cstring>
  5. #include <memory>
  6. #include <glad/glad.h>
  7. #include "common/color.h"
  8. #include "common/math_util.h"
  9. #include "common/microprofile.h"
  10. #include "common/profiler.h"
  11. #include "core/memory.h"
  12. #include "core/settings.h"
  13. #include "core/hw/gpu.h"
  14. #include "video_core/pica.h"
  15. #include "video_core/utils.h"
  16. #include "video_core/renderer_opengl/gl_rasterizer.h"
  17. #include "video_core/renderer_opengl/gl_shaders.h"
  18. #include "video_core/renderer_opengl/gl_shader_util.h"
  19. #include "video_core/renderer_opengl/pica_to_gl.h"
  20. static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) {
  21. return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace &&
  22. stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace &&
  23. stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous &&
  24. stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous &&
  25. stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor &&
  26. stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha &&
  27. stage.GetColorMultiplier() == 1 &&
  28. stage.GetAlphaMultiplier() == 1);
  29. }
  30. RasterizerOpenGL::RasterizerOpenGL() : last_fb_color_addr(0), last_fb_depth_addr(0) { }
  31. RasterizerOpenGL::~RasterizerOpenGL() { }
  32. void RasterizerOpenGL::InitObjects() {
  33. // Create the hardware shader program and get attrib/uniform locations
  34. shader.Create(GLShaders::g_vertex_shader_hw, GLShaders::g_fragment_shader_hw);
  35. attrib_position = glGetAttribLocation(shader.handle, "vert_position");
  36. attrib_color = glGetAttribLocation(shader.handle, "vert_color");
  37. attrib_texcoords = glGetAttribLocation(shader.handle, "vert_texcoords");
  38. uniform_alphatest_enabled = glGetUniformLocation(shader.handle, "alphatest_enabled");
  39. uniform_alphatest_func = glGetUniformLocation(shader.handle, "alphatest_func");
  40. uniform_alphatest_ref = glGetUniformLocation(shader.handle, "alphatest_ref");
  41. uniform_tex = glGetUniformLocation(shader.handle, "tex");
  42. uniform_tev_combiner_buffer_color = glGetUniformLocation(shader.handle, "tev_combiner_buffer_color");
  43. const auto tev_stages = Pica::g_state.regs.GetTevStages();
  44. for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) {
  45. auto& uniform_tev_cfg = uniform_tev_cfgs[tev_stage_index];
  46. std::string tev_ref_str = "tev_cfgs[" + std::to_string(tev_stage_index) + "]";
  47. uniform_tev_cfg.enabled = glGetUniformLocation(shader.handle, (tev_ref_str + ".enabled").c_str());
  48. uniform_tev_cfg.color_sources = glGetUniformLocation(shader.handle, (tev_ref_str + ".color_sources").c_str());
  49. uniform_tev_cfg.alpha_sources = glGetUniformLocation(shader.handle, (tev_ref_str + ".alpha_sources").c_str());
  50. uniform_tev_cfg.color_modifiers = glGetUniformLocation(shader.handle, (tev_ref_str + ".color_modifiers").c_str());
  51. uniform_tev_cfg.alpha_modifiers = glGetUniformLocation(shader.handle, (tev_ref_str + ".alpha_modifiers").c_str());
  52. uniform_tev_cfg.color_alpha_op = glGetUniformLocation(shader.handle, (tev_ref_str + ".color_alpha_op").c_str());
  53. uniform_tev_cfg.color_alpha_multiplier = glGetUniformLocation(shader.handle, (tev_ref_str + ".color_alpha_multiplier").c_str());
  54. uniform_tev_cfg.const_color = glGetUniformLocation(shader.handle, (tev_ref_str + ".const_color").c_str());
  55. uniform_tev_cfg.updates_combiner_buffer_color_alpha = glGetUniformLocation(shader.handle, (tev_ref_str + ".updates_combiner_buffer_color_alpha").c_str());
  56. }
  57. // Create sampler objects
  58. for (size_t i = 0; i < texture_samplers.size(); ++i) {
  59. texture_samplers[i].Create();
  60. state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
  61. }
  62. // Generate VBO and VAO
  63. vertex_buffer.Create();
  64. vertex_array.Create();
  65. // Update OpenGL state
  66. state.draw.vertex_array = vertex_array.handle;
  67. state.draw.vertex_buffer = vertex_buffer.handle;
  68. state.draw.shader_program = shader.handle;
  69. state.Apply();
  70. // Set the texture samplers to correspond to different texture units
  71. glUniform1i(uniform_tex, 0);
  72. glUniform1i(uniform_tex + 1, 1);
  73. glUniform1i(uniform_tex + 2, 2);
  74. // Set vertex attributes
  75. glVertexAttribPointer(attrib_position, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, position));
  76. glVertexAttribPointer(attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, color));
  77. glVertexAttribPointer(attrib_texcoords, 2, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, tex_coord0));
  78. glVertexAttribPointer(attrib_texcoords + 1, 2, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, tex_coord1));
  79. glVertexAttribPointer(attrib_texcoords + 2, 2, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, tex_coord2));
  80. glEnableVertexAttribArray(attrib_position);
  81. glEnableVertexAttribArray(attrib_color);
  82. glEnableVertexAttribArray(attrib_texcoords);
  83. glEnableVertexAttribArray(attrib_texcoords + 1);
  84. glEnableVertexAttribArray(attrib_texcoords + 2);
  85. // Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
  86. fb_color_texture.texture.Create();
  87. ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1);
  88. state.texture_units[0].texture_2d = fb_color_texture.texture.handle;
  89. state.Apply();
  90. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  91. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  92. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  93. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  94. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  95. state.texture_units[0].texture_2d = 0;
  96. state.Apply();
  97. fb_depth_texture.texture.Create();
  98. ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1);
  99. state.texture_units[0].texture_2d = fb_depth_texture.texture.handle;
  100. state.Apply();
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  102. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  103. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  104. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  105. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  106. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  107. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
  108. state.texture_units[0].texture_2d = 0;
  109. state.Apply();
  110. // Configure OpenGL framebuffer
  111. framebuffer.Create();
  112. state.draw.framebuffer = framebuffer.handle;
  113. state.Apply();
  114. glActiveTexture(GL_TEXTURE0);
  115. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_color_texture.texture.handle, 0);
  116. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fb_depth_texture.texture.handle, 0);
  117. ASSERT_MSG(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
  118. "OpenGL rasterizer framebuffer setup failed, status %X", glCheckFramebufferStatus(GL_FRAMEBUFFER));
  119. }
  120. void RasterizerOpenGL::Reset() {
  121. const auto& regs = Pica::g_state.regs;
  122. SyncCullMode();
  123. SyncBlendEnabled();
  124. SyncBlendFuncs();
  125. SyncBlendColor();
  126. SyncAlphaTest();
  127. SyncLogicOp();
  128. SyncStencilTest();
  129. SyncDepthTest();
  130. // TEV stage 0
  131. SyncTevSources(0, regs.tev_stage0);
  132. SyncTevModifiers(0, regs.tev_stage0);
  133. SyncTevOps(0, regs.tev_stage0);
  134. SyncTevColor(0, regs.tev_stage0);
  135. SyncTevMultipliers(0, regs.tev_stage0);
  136. // TEV stage 1
  137. SyncTevSources(1, regs.tev_stage1);
  138. SyncTevModifiers(1, regs.tev_stage1);
  139. SyncTevOps(1, regs.tev_stage1);
  140. SyncTevColor(1, regs.tev_stage1);
  141. SyncTevMultipliers(1, regs.tev_stage1);
  142. // TEV stage 2
  143. SyncTevSources(2, regs.tev_stage2);
  144. SyncTevModifiers(2, regs.tev_stage2);
  145. SyncTevOps(2, regs.tev_stage2);
  146. SyncTevColor(2, regs.tev_stage2);
  147. SyncTevMultipliers(2, regs.tev_stage2);
  148. // TEV stage 3
  149. SyncTevSources(3, regs.tev_stage3);
  150. SyncTevModifiers(3, regs.tev_stage3);
  151. SyncTevOps(3, regs.tev_stage3);
  152. SyncTevColor(3, regs.tev_stage3);
  153. SyncTevMultipliers(3, regs.tev_stage3);
  154. // TEV stage 4
  155. SyncTevSources(4, regs.tev_stage4);
  156. SyncTevModifiers(4, regs.tev_stage4);
  157. SyncTevOps(4, regs.tev_stage4);
  158. SyncTevColor(4, regs.tev_stage4);
  159. SyncTevMultipliers(4, regs.tev_stage4);
  160. // TEV stage 5
  161. SyncTevSources(5, regs.tev_stage5);
  162. SyncTevModifiers(5, regs.tev_stage5);
  163. SyncTevOps(5, regs.tev_stage5);
  164. SyncTevColor(5, regs.tev_stage5);
  165. SyncTevMultipliers(5, regs.tev_stage5);
  166. SyncCombinerColor();
  167. SyncCombinerWriteFlags();
  168. res_cache.FullFlush();
  169. }
  170. void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
  171. const Pica::Shader::OutputVertex& v1,
  172. const Pica::Shader::OutputVertex& v2) {
  173. vertex_batch.emplace_back(v0);
  174. vertex_batch.emplace_back(v1);
  175. vertex_batch.emplace_back(v2);
  176. }
  177. void RasterizerOpenGL::DrawTriangles() {
  178. SyncFramebuffer();
  179. SyncDrawState();
  180. glBufferData(GL_ARRAY_BUFFER, vertex_batch.size() * sizeof(HardwareVertex), vertex_batch.data(), GL_STREAM_DRAW);
  181. glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertex_batch.size());
  182. vertex_batch.clear();
  183. // Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture
  184. const auto& regs = Pica::g_state.regs;
  185. PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
  186. u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
  187. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  188. PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
  189. u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
  190. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  191. res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size, true);
  192. res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size, true);
  193. }
  194. void RasterizerOpenGL::CommitFramebuffer() {
  195. CommitColorBuffer();
  196. CommitDepthBuffer();
  197. }
  198. void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
  199. const auto& regs = Pica::g_state.regs;
  200. if (!Settings::values.use_hw_renderer)
  201. return;
  202. switch(id) {
  203. // Culling
  204. case PICA_REG_INDEX(cull_mode):
  205. SyncCullMode();
  206. break;
  207. // Blending
  208. case PICA_REG_INDEX(output_merger.alphablend_enable):
  209. SyncBlendEnabled();
  210. break;
  211. case PICA_REG_INDEX(output_merger.alpha_blending):
  212. SyncBlendFuncs();
  213. break;
  214. case PICA_REG_INDEX(output_merger.blend_const):
  215. SyncBlendColor();
  216. break;
  217. // Alpha test
  218. case PICA_REG_INDEX(output_merger.alpha_test):
  219. SyncAlphaTest();
  220. break;
  221. // Stencil test
  222. case PICA_REG_INDEX(output_merger.stencil_test.raw_func):
  223. case PICA_REG_INDEX(output_merger.stencil_test.raw_op):
  224. SyncStencilTest();
  225. break;
  226. // Depth test
  227. case PICA_REG_INDEX(output_merger.depth_test_enable):
  228. SyncDepthTest();
  229. break;
  230. // Logic op
  231. case PICA_REG_INDEX(output_merger.logic_op):
  232. SyncLogicOp();
  233. break;
  234. // TEV stage 0
  235. case PICA_REG_INDEX(tev_stage0.color_source1):
  236. SyncTevSources(0, regs.tev_stage0);
  237. break;
  238. case PICA_REG_INDEX(tev_stage0.color_modifier1):
  239. SyncTevModifiers(0, regs.tev_stage0);
  240. break;
  241. case PICA_REG_INDEX(tev_stage0.color_op):
  242. SyncTevOps(0, regs.tev_stage0);
  243. break;
  244. case PICA_REG_INDEX(tev_stage0.const_r):
  245. SyncTevColor(0, regs.tev_stage0);
  246. break;
  247. case PICA_REG_INDEX(tev_stage0.color_scale):
  248. SyncTevMultipliers(0, regs.tev_stage0);
  249. break;
  250. // TEV stage 1
  251. case PICA_REG_INDEX(tev_stage1.color_source1):
  252. SyncTevSources(1, regs.tev_stage1);
  253. break;
  254. case PICA_REG_INDEX(tev_stage1.color_modifier1):
  255. SyncTevModifiers(1, regs.tev_stage1);
  256. break;
  257. case PICA_REG_INDEX(tev_stage1.color_op):
  258. SyncTevOps(1, regs.tev_stage1);
  259. break;
  260. case PICA_REG_INDEX(tev_stage1.const_r):
  261. SyncTevColor(1, regs.tev_stage1);
  262. break;
  263. case PICA_REG_INDEX(tev_stage1.color_scale):
  264. SyncTevMultipliers(1, regs.tev_stage1);
  265. break;
  266. // TEV stage 2
  267. case PICA_REG_INDEX(tev_stage2.color_source1):
  268. SyncTevSources(2, regs.tev_stage2);
  269. break;
  270. case PICA_REG_INDEX(tev_stage2.color_modifier1):
  271. SyncTevModifiers(2, regs.tev_stage2);
  272. break;
  273. case PICA_REG_INDEX(tev_stage2.color_op):
  274. SyncTevOps(2, regs.tev_stage2);
  275. break;
  276. case PICA_REG_INDEX(tev_stage2.const_r):
  277. SyncTevColor(2, regs.tev_stage2);
  278. break;
  279. case PICA_REG_INDEX(tev_stage2.color_scale):
  280. SyncTevMultipliers(2, regs.tev_stage2);
  281. break;
  282. // TEV stage 3
  283. case PICA_REG_INDEX(tev_stage3.color_source1):
  284. SyncTevSources(3, regs.tev_stage3);
  285. break;
  286. case PICA_REG_INDEX(tev_stage3.color_modifier1):
  287. SyncTevModifiers(3, regs.tev_stage3);
  288. break;
  289. case PICA_REG_INDEX(tev_stage3.color_op):
  290. SyncTevOps(3, regs.tev_stage3);
  291. break;
  292. case PICA_REG_INDEX(tev_stage3.const_r):
  293. SyncTevColor(3, regs.tev_stage3);
  294. break;
  295. case PICA_REG_INDEX(tev_stage3.color_scale):
  296. SyncTevMultipliers(3, regs.tev_stage3);
  297. break;
  298. // TEV stage 4
  299. case PICA_REG_INDEX(tev_stage4.color_source1):
  300. SyncTevSources(4, regs.tev_stage4);
  301. break;
  302. case PICA_REG_INDEX(tev_stage4.color_modifier1):
  303. SyncTevModifiers(4, regs.tev_stage4);
  304. break;
  305. case PICA_REG_INDEX(tev_stage4.color_op):
  306. SyncTevOps(4, regs.tev_stage4);
  307. break;
  308. case PICA_REG_INDEX(tev_stage4.const_r):
  309. SyncTevColor(4, regs.tev_stage4);
  310. break;
  311. case PICA_REG_INDEX(tev_stage4.color_scale):
  312. SyncTevMultipliers(4, regs.tev_stage4);
  313. break;
  314. // TEV stage 5
  315. case PICA_REG_INDEX(tev_stage5.color_source1):
  316. SyncTevSources(5, regs.tev_stage5);
  317. break;
  318. case PICA_REG_INDEX(tev_stage5.color_modifier1):
  319. SyncTevModifiers(5, regs.tev_stage5);
  320. break;
  321. case PICA_REG_INDEX(tev_stage5.color_op):
  322. SyncTevOps(5, regs.tev_stage5);
  323. break;
  324. case PICA_REG_INDEX(tev_stage5.const_r):
  325. SyncTevColor(5, regs.tev_stage5);
  326. break;
  327. case PICA_REG_INDEX(tev_stage5.color_scale):
  328. SyncTevMultipliers(5, regs.tev_stage5);
  329. break;
  330. // TEV combiner buffer color
  331. case PICA_REG_INDEX(tev_combiner_buffer_color):
  332. SyncCombinerColor();
  333. break;
  334. // TEV combiner buffer write flags
  335. case PICA_REG_INDEX(tev_combiner_buffer_input):
  336. SyncCombinerWriteFlags();
  337. break;
  338. }
  339. }
  340. void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
  341. const auto& regs = Pica::g_state.regs;
  342. if (!Settings::values.use_hw_renderer)
  343. return;
  344. PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
  345. u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
  346. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  347. PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
  348. u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
  349. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  350. // If source memory region overlaps 3DS framebuffers, commit them before the copy happens
  351. if (MathUtil::IntervalsIntersect(addr, size, cur_fb_color_addr, cur_fb_color_size))
  352. CommitColorBuffer();
  353. if (MathUtil::IntervalsIntersect(addr, size, cur_fb_depth_addr, cur_fb_depth_size))
  354. CommitDepthBuffer();
  355. }
  356. void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
  357. const auto& regs = Pica::g_state.regs;
  358. if (!Settings::values.use_hw_renderer)
  359. return;
  360. PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
  361. u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
  362. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  363. PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
  364. u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
  365. * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
  366. // If modified memory region overlaps 3DS framebuffers, reload their contents into OpenGL
  367. if (MathUtil::IntervalsIntersect(addr, size, cur_fb_color_addr, cur_fb_color_size))
  368. ReloadColorBuffer();
  369. if (MathUtil::IntervalsIntersect(addr, size, cur_fb_depth_addr, cur_fb_depth_size))
  370. ReloadDepthBuffer();
  371. // Notify cache of flush in case the region touches a cached resource
  372. res_cache.NotifyFlush(addr, size);
  373. }
  374. void RasterizerOpenGL::SamplerInfo::Create() {
  375. sampler.Create();
  376. mag_filter = min_filter = TextureConfig::Linear;
  377. wrap_s = wrap_t = TextureConfig::Repeat;
  378. border_color = 0;
  379. glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // default is GL_LINEAR_MIPMAP_LINEAR
  380. // Other attributes have correct defaults
  381. }
  382. void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) {
  383. GLuint s = sampler.handle;
  384. if (mag_filter != config.mag_filter) {
  385. mag_filter = config.mag_filter;
  386. glSamplerParameteri(s, GL_TEXTURE_MAG_FILTER, PicaToGL::TextureFilterMode(mag_filter));
  387. }
  388. if (min_filter != config.min_filter) {
  389. min_filter = config.min_filter;
  390. glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(min_filter));
  391. }
  392. if (wrap_s != config.wrap_s) {
  393. wrap_s = config.wrap_s;
  394. glSamplerParameteri(s, GL_TEXTURE_WRAP_S, PicaToGL::WrapMode(wrap_s));
  395. }
  396. if (wrap_t != config.wrap_t) {
  397. wrap_t = config.wrap_t;
  398. glSamplerParameteri(s, GL_TEXTURE_WRAP_T, PicaToGL::WrapMode(wrap_t));
  399. }
  400. if (wrap_s == TextureConfig::ClampToBorder || wrap_t == TextureConfig::ClampToBorder) {
  401. if (border_color != config.border_color.raw) {
  402. auto gl_color = PicaToGL::ColorRGBA8(border_color);
  403. glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, gl_color.data());
  404. }
  405. }
  406. }
  407. void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height) {
  408. GLint internal_format;
  409. texture.format = format;
  410. texture.width = width;
  411. texture.height = height;
  412. switch (format) {
  413. case Pica::Regs::ColorFormat::RGBA8:
  414. internal_format = GL_RGBA;
  415. texture.gl_format = GL_RGBA;
  416. texture.gl_type = GL_UNSIGNED_INT_8_8_8_8;
  417. break;
  418. case Pica::Regs::ColorFormat::RGB8:
  419. // This pixel format uses BGR since GL_UNSIGNED_BYTE specifies byte-order, unlike every
  420. // specific OpenGL type used in this function using native-endian (that is, little-endian
  421. // mostly everywhere) for words or half-words.
  422. // TODO: check how those behave on big-endian processors.
  423. internal_format = GL_RGB;
  424. texture.gl_format = GL_BGR;
  425. texture.gl_type = GL_UNSIGNED_BYTE;
  426. break;
  427. case Pica::Regs::ColorFormat::RGB5A1:
  428. internal_format = GL_RGBA;
  429. texture.gl_format = GL_RGBA;
  430. texture.gl_type = GL_UNSIGNED_SHORT_5_5_5_1;
  431. break;
  432. case Pica::Regs::ColorFormat::RGB565:
  433. internal_format = GL_RGB;
  434. texture.gl_format = GL_RGB;
  435. texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
  436. break;
  437. case Pica::Regs::ColorFormat::RGBA4:
  438. internal_format = GL_RGBA;
  439. texture.gl_format = GL_RGBA;
  440. texture.gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
  441. break;
  442. default:
  443. LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer texture color format %x", format);
  444. UNIMPLEMENTED();
  445. break;
  446. }
  447. state.texture_units[0].texture_2d = texture.texture.handle;
  448. state.Apply();
  449. glActiveTexture(GL_TEXTURE0);
  450. glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
  451. texture.gl_format, texture.gl_type, nullptr);
  452. state.texture_units[0].texture_2d = 0;
  453. state.Apply();
  454. }
  455. void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) {
  456. GLint internal_format;
  457. texture.format = format;
  458. texture.width = width;
  459. texture.height = height;
  460. switch (format) {
  461. case Pica::Regs::DepthFormat::D16:
  462. internal_format = GL_DEPTH_COMPONENT16;
  463. texture.gl_format = GL_DEPTH_COMPONENT;
  464. texture.gl_type = GL_UNSIGNED_SHORT;
  465. break;
  466. case Pica::Regs::DepthFormat::D24:
  467. internal_format = GL_DEPTH_COMPONENT24;
  468. texture.gl_format = GL_DEPTH_COMPONENT;
  469. texture.gl_type = GL_UNSIGNED_INT;
  470. break;
  471. case Pica::Regs::DepthFormat::D24S8:
  472. internal_format = GL_DEPTH24_STENCIL8;
  473. texture.gl_format = GL_DEPTH_STENCIL;
  474. texture.gl_type = GL_UNSIGNED_INT_24_8;
  475. break;
  476. default:
  477. LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer texture depth format %x", format);
  478. UNIMPLEMENTED();
  479. break;
  480. }
  481. state.texture_units[0].texture_2d = texture.texture.handle;
  482. state.Apply();
  483. glActiveTexture(GL_TEXTURE0);
  484. glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
  485. texture.gl_format, texture.gl_type, nullptr);
  486. state.texture_units[0].texture_2d = 0;
  487. state.Apply();
  488. }
  489. void RasterizerOpenGL::SyncFramebuffer() {
  490. const auto& regs = Pica::g_state.regs;
  491. PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
  492. Pica::Regs::ColorFormat new_fb_color_format = regs.framebuffer.color_format;
  493. PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
  494. Pica::Regs::DepthFormat new_fb_depth_format = regs.framebuffer.depth_format;
  495. bool fb_size_changed = fb_color_texture.width != static_cast<GLsizei>(regs.framebuffer.GetWidth()) ||
  496. fb_color_texture.height != static_cast<GLsizei>(regs.framebuffer.GetHeight());
  497. bool color_fb_prop_changed = fb_color_texture.format != new_fb_color_format ||
  498. fb_size_changed;
  499. bool depth_fb_prop_changed = fb_depth_texture.format != new_fb_depth_format ||
  500. fb_size_changed;
  501. bool color_fb_modified = last_fb_color_addr != cur_fb_color_addr ||
  502. color_fb_prop_changed;
  503. bool depth_fb_modified = last_fb_depth_addr != cur_fb_depth_addr ||
  504. depth_fb_prop_changed;
  505. // Commit if framebuffer modified in any way
  506. if (color_fb_modified)
  507. CommitColorBuffer();
  508. if (depth_fb_modified)
  509. CommitDepthBuffer();
  510. // Reconfigure framebuffer textures if any property has changed
  511. if (color_fb_prop_changed) {
  512. ReconfigureColorTexture(fb_color_texture, new_fb_color_format,
  513. regs.framebuffer.GetWidth(), regs.framebuffer.GetHeight());
  514. }
  515. if (depth_fb_prop_changed) {
  516. ReconfigureDepthTexture(fb_depth_texture, new_fb_depth_format,
  517. regs.framebuffer.GetWidth(), regs.framebuffer.GetHeight());
  518. // Only attach depth buffer as stencil if it supports stencil
  519. switch (new_fb_depth_format) {
  520. case Pica::Regs::DepthFormat::D16:
  521. case Pica::Regs::DepthFormat::D24:
  522. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
  523. break;
  524. case Pica::Regs::DepthFormat::D24S8:
  525. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fb_depth_texture.texture.handle, 0);
  526. break;
  527. default:
  528. LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer depth format %x", new_fb_depth_format);
  529. UNIMPLEMENTED();
  530. break;
  531. }
  532. }
  533. // Load buffer data again if fb modified in any way
  534. if (color_fb_modified) {
  535. last_fb_color_addr = cur_fb_color_addr;
  536. ReloadColorBuffer();
  537. }
  538. if (depth_fb_modified) {
  539. last_fb_depth_addr = cur_fb_depth_addr;
  540. ReloadDepthBuffer();
  541. }
  542. }
  543. void RasterizerOpenGL::SyncCullMode() {
  544. const auto& regs = Pica::g_state.regs;
  545. switch (regs.cull_mode) {
  546. case Pica::Regs::CullMode::KeepAll:
  547. state.cull.enabled = false;
  548. break;
  549. case Pica::Regs::CullMode::KeepClockWise:
  550. state.cull.enabled = true;
  551. state.cull.mode = GL_BACK;
  552. break;
  553. case Pica::Regs::CullMode::KeepCounterClockWise:
  554. state.cull.enabled = true;
  555. state.cull.mode = GL_FRONT;
  556. break;
  557. default:
  558. LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", regs.cull_mode.Value());
  559. UNIMPLEMENTED();
  560. break;
  561. }
  562. }
  563. void RasterizerOpenGL::SyncBlendEnabled() {
  564. state.blend.enabled = (Pica::g_state.regs.output_merger.alphablend_enable == 1);
  565. }
  566. void RasterizerOpenGL::SyncBlendFuncs() {
  567. const auto& regs = Pica::g_state.regs;
  568. state.blend.src_rgb_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_rgb);
  569. state.blend.dst_rgb_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_rgb);
  570. state.blend.src_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_a);
  571. state.blend.dst_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_a);
  572. }
  573. void RasterizerOpenGL::SyncBlendColor() {
  574. auto blend_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.output_merger.blend_const.raw);
  575. state.blend.color.red = blend_color[0];
  576. state.blend.color.green = blend_color[1];
  577. state.blend.color.blue = blend_color[2];
  578. state.blend.color.alpha = blend_color[3];
  579. }
  580. void RasterizerOpenGL::SyncAlphaTest() {
  581. const auto& regs = Pica::g_state.regs;
  582. glUniform1i(uniform_alphatest_enabled, regs.output_merger.alpha_test.enable);
  583. glUniform1i(uniform_alphatest_func, (GLint)regs.output_merger.alpha_test.func.Value());
  584. glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f);
  585. }
  586. void RasterizerOpenGL::SyncLogicOp() {
  587. state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op);
  588. }
  589. void RasterizerOpenGL::SyncStencilTest() {
  590. const auto& regs = Pica::g_state.regs;
  591. state.stencil.test_enabled = regs.output_merger.stencil_test.enable && regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8;
  592. state.stencil.test_func = PicaToGL::CompareFunc(regs.output_merger.stencil_test.func);
  593. state.stencil.test_ref = regs.output_merger.stencil_test.reference_value;
  594. state.stencil.test_mask = regs.output_merger.stencil_test.input_mask;
  595. state.stencil.write_mask = regs.output_merger.stencil_test.write_mask;
  596. state.stencil.action_stencil_fail = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_stencil_fail);
  597. state.stencil.action_depth_fail = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_fail);
  598. state.stencil.action_depth_pass = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_pass);
  599. }
  600. void RasterizerOpenGL::SyncDepthTest() {
  601. const auto& regs = Pica::g_state.regs;
  602. state.depth.test_enabled = (regs.output_merger.depth_test_enable == 1);
  603. state.depth.test_func = PicaToGL::CompareFunc(regs.output_merger.depth_test_func);
  604. state.color_mask.red_enabled = regs.output_merger.red_enable;
  605. state.color_mask.green_enabled = regs.output_merger.green_enable;
  606. state.color_mask.blue_enabled = regs.output_merger.blue_enable;
  607. state.color_mask.alpha_enabled = regs.output_merger.alpha_enable;
  608. state.depth.write_mask = regs.output_merger.depth_write_enable ? GL_TRUE : GL_FALSE;
  609. }
  610. void RasterizerOpenGL::SyncTevSources(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
  611. GLint color_srcs[3] = { (GLint)config.color_source1.Value(),
  612. (GLint)config.color_source2.Value(),
  613. (GLint)config.color_source3.Value() };
  614. GLint alpha_srcs[3] = { (GLint)config.alpha_source1.Value(),
  615. (GLint)config.alpha_source2.Value(),
  616. (GLint)config.alpha_source3.Value() };
  617. glUniform3iv(uniform_tev_cfgs[stage_index].color_sources, 1, color_srcs);
  618. glUniform3iv(uniform_tev_cfgs[stage_index].alpha_sources, 1, alpha_srcs);
  619. }
  620. void RasterizerOpenGL::SyncTevModifiers(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
  621. GLint color_mods[3] = { (GLint)config.color_modifier1.Value(),
  622. (GLint)config.color_modifier2.Value(),
  623. (GLint)config.color_modifier3.Value() };
  624. GLint alpha_mods[3] = { (GLint)config.alpha_modifier1.Value(),
  625. (GLint)config.alpha_modifier2.Value(),
  626. (GLint)config.alpha_modifier3.Value() };
  627. glUniform3iv(uniform_tev_cfgs[stage_index].color_modifiers, 1, color_mods);
  628. glUniform3iv(uniform_tev_cfgs[stage_index].alpha_modifiers, 1, alpha_mods);
  629. }
  630. void RasterizerOpenGL::SyncTevOps(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
  631. glUniform2i(uniform_tev_cfgs[stage_index].color_alpha_op, (GLint)config.color_op.Value(), (GLint)config.alpha_op.Value());
  632. }
  633. void RasterizerOpenGL::SyncTevColor(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
  634. auto const_color = PicaToGL::ColorRGBA8(config.const_color);
  635. glUniform4fv(uniform_tev_cfgs[stage_index].const_color, 1, const_color.data());
  636. }
  637. void RasterizerOpenGL::SyncTevMultipliers(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
  638. glUniform2i(uniform_tev_cfgs[stage_index].color_alpha_multiplier, config.GetColorMultiplier(), config.GetAlphaMultiplier());
  639. }
  640. void RasterizerOpenGL::SyncCombinerColor() {
  641. auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw);
  642. glUniform4fv(uniform_tev_combiner_buffer_color, 1, combiner_color.data());
  643. }
  644. void RasterizerOpenGL::SyncCombinerWriteFlags() {
  645. const auto& regs = Pica::g_state.regs;
  646. const auto tev_stages = regs.GetTevStages();
  647. for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) {
  648. glUniform2i(uniform_tev_cfgs[tev_stage_index].updates_combiner_buffer_color_alpha,
  649. regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(tev_stage_index),
  650. regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(tev_stage_index));
  651. }
  652. }
  653. void RasterizerOpenGL::SyncDrawState() {
  654. const auto& regs = Pica::g_state.regs;
  655. // Sync the viewport
  656. GLsizei viewport_width = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_x).ToFloat32() * 2;
  657. GLsizei viewport_height = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_y).ToFloat32() * 2;
  658. // OpenGL uses different y coordinates, so negate corner offset and flip origin
  659. // TODO: Ensure viewport_corner.x should not be negated or origin flipped
  660. // TODO: Use floating-point viewports for accuracy if supported
  661. glViewport((GLsizei)static_cast<float>(regs.viewport_corner.x),
  662. -(GLsizei)static_cast<float>(regs.viewport_corner.y)
  663. + regs.framebuffer.GetHeight() - viewport_height,
  664. viewport_width, viewport_height);
  665. // Sync bound texture(s), upload if not cached
  666. const auto pica_textures = regs.GetTextures();
  667. for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
  668. const auto& texture = pica_textures[texture_index];
  669. if (texture.enabled) {
  670. texture_samplers[texture_index].SyncWithConfig(texture.config);
  671. res_cache.LoadAndBindTexture(state, texture_index, texture);
  672. } else {
  673. state.texture_units[texture_index].texture_2d = 0;
  674. }
  675. }
  676. // Skip processing TEV stages that simply pass the previous stage results through
  677. const auto tev_stages = regs.GetTevStages();
  678. for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) {
  679. glUniform1i(uniform_tev_cfgs[tev_stage_index].enabled, !IsPassThroughTevStage(tev_stages[tev_stage_index]));
  680. }
  681. state.Apply();
  682. }
  683. MICROPROFILE_DEFINE(OpenGL_FramebufferReload, "OpenGL", "FB Reload", MP_RGB(70, 70, 200));
  684. void RasterizerOpenGL::ReloadColorBuffer() {
  685. u8* color_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetColorBufferPhysicalAddress());
  686. if (color_buffer == nullptr)
  687. return;
  688. MICROPROFILE_SCOPE(OpenGL_FramebufferReload);
  689. u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format);
  690. std::unique_ptr<u8[]> temp_fb_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]);
  691. // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary.
  692. for (int y = 0; y < fb_color_texture.height; ++y) {
  693. for (int x = 0; x < fb_color_texture.width; ++x) {
  694. const u32 coarse_y = y & ~7;
  695. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
  696. u32 gl_pixel_index = (x + y * fb_color_texture.width) * bytes_per_pixel;
  697. u8* pixel = color_buffer + dst_offset;
  698. memcpy(&temp_fb_color_buffer[gl_pixel_index], pixel, bytes_per_pixel);
  699. }
  700. }
  701. state.texture_units[0].texture_2d = fb_color_texture.texture.handle;
  702. state.Apply();
  703. glActiveTexture(GL_TEXTURE0);
  704. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_color_texture.width, fb_color_texture.height,
  705. fb_color_texture.gl_format, fb_color_texture.gl_type, temp_fb_color_buffer.get());
  706. state.texture_units[0].texture_2d = 0;
  707. state.Apply();
  708. }
  709. void RasterizerOpenGL::ReloadDepthBuffer() {
  710. PAddr depth_buffer_addr = Pica::g_state.regs.framebuffer.GetDepthBufferPhysicalAddress();
  711. if (depth_buffer_addr == 0)
  712. return;
  713. // TODO: Appears to work, but double-check endianness of depth values and order of depth-stencil
  714. u8* depth_buffer = Memory::GetPhysicalPointer(depth_buffer_addr);
  715. if (depth_buffer == nullptr)
  716. return;
  717. MICROPROFILE_SCOPE(OpenGL_FramebufferReload);
  718. u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format);
  719. // OpenGL needs 4 bpp alignment for D24
  720. u32 gl_bpp = bytes_per_pixel == 3 ? 4 : bytes_per_pixel;
  721. std::unique_ptr<u8[]> temp_fb_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]);
  722. u8* temp_fb_depth_data = bytes_per_pixel == 3 ? (temp_fb_depth_buffer.get() + 1) : temp_fb_depth_buffer.get();
  723. if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
  724. for (int y = 0; y < fb_depth_texture.height; ++y) {
  725. for (int x = 0; x < fb_depth_texture.width; ++x) {
  726. const u32 coarse_y = y & ~7;
  727. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
  728. u32 gl_pixel_index = (x + y * fb_depth_texture.width);
  729. u8* pixel = depth_buffer + dst_offset;
  730. u32 depth_stencil = *(u32*)pixel;
  731. ((u32*)temp_fb_depth_data)[gl_pixel_index] = (depth_stencil << 8) | (depth_stencil >> 24);
  732. }
  733. }
  734. } else {
  735. for (int y = 0; y < fb_depth_texture.height; ++y) {
  736. for (int x = 0; x < fb_depth_texture.width; ++x) {
  737. const u32 coarse_y = y & ~7;
  738. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
  739. u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
  740. u8* pixel = depth_buffer + dst_offset;
  741. memcpy(&temp_fb_depth_data[gl_pixel_index], pixel, bytes_per_pixel);
  742. }
  743. }
  744. }
  745. state.texture_units[0].texture_2d = fb_depth_texture.texture.handle;
  746. state.Apply();
  747. glActiveTexture(GL_TEXTURE0);
  748. if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
  749. // TODO(Subv): There is a bug with Intel Windows drivers that makes glTexSubImage2D not change the stencil buffer.
  750. // The bug has been reported to Intel (https://communities.intel.com/message/324464)
  751. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, fb_depth_texture.width, fb_depth_texture.height, 0,
  752. GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, temp_fb_depth_buffer.get());
  753. } else {
  754. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_depth_texture.width, fb_depth_texture.height,
  755. fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get());
  756. }
  757. state.texture_units[0].texture_2d = 0;
  758. state.Apply();
  759. }
  760. Common::Profiling::TimingCategory buffer_commit_category("Framebuffer Commit");
  761. MICROPROFILE_DEFINE(OpenGL_FramebufferCommit, "OpenGL", "FB Commit", MP_RGB(70, 70, 200));
  762. void RasterizerOpenGL::CommitColorBuffer() {
  763. if (last_fb_color_addr != 0) {
  764. u8* color_buffer = Memory::GetPhysicalPointer(last_fb_color_addr);
  765. if (color_buffer != nullptr) {
  766. Common::Profiling::ScopeTimer timer(buffer_commit_category);
  767. MICROPROFILE_SCOPE(OpenGL_FramebufferCommit);
  768. u32 bytes_per_pixel = Pica::Regs::BytesPerColorPixel(fb_color_texture.format);
  769. std::unique_ptr<u8[]> temp_gl_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]);
  770. state.texture_units[0].texture_2d = fb_color_texture.texture.handle;
  771. state.Apply();
  772. glActiveTexture(GL_TEXTURE0);
  773. glGetTexImage(GL_TEXTURE_2D, 0, fb_color_texture.gl_format, fb_color_texture.gl_type, temp_gl_color_buffer.get());
  774. state.texture_units[0].texture_2d = 0;
  775. state.Apply();
  776. // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary.
  777. for (int y = 0; y < fb_color_texture.height; ++y) {
  778. for (int x = 0; x < fb_color_texture.width; ++x) {
  779. const u32 coarse_y = y & ~7;
  780. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
  781. u32 gl_pixel_index = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
  782. u8* pixel = color_buffer + dst_offset;
  783. memcpy(pixel, &temp_gl_color_buffer[gl_pixel_index], bytes_per_pixel);
  784. }
  785. }
  786. }
  787. }
  788. }
  789. void RasterizerOpenGL::CommitDepthBuffer() {
  790. if (last_fb_depth_addr != 0) {
  791. // TODO: Output seems correct visually, but doesn't quite match sw renderer output. One of them is wrong.
  792. u8* depth_buffer = Memory::GetPhysicalPointer(last_fb_depth_addr);
  793. if (depth_buffer != nullptr) {
  794. Common::Profiling::ScopeTimer timer(buffer_commit_category);
  795. MICROPROFILE_SCOPE(OpenGL_FramebufferCommit);
  796. u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format);
  797. // OpenGL needs 4 bpp alignment for D24
  798. u32 gl_bpp = bytes_per_pixel == 3 ? 4 : bytes_per_pixel;
  799. std::unique_ptr<u8[]> temp_gl_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]);
  800. state.texture_units[0].texture_2d = fb_depth_texture.texture.handle;
  801. state.Apply();
  802. glActiveTexture(GL_TEXTURE0);
  803. glGetTexImage(GL_TEXTURE_2D, 0, fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_gl_depth_buffer.get());
  804. state.texture_units[0].texture_2d = 0;
  805. state.Apply();
  806. u8* temp_gl_depth_data = bytes_per_pixel == 3 ? (temp_gl_depth_buffer.get() + 1) : temp_gl_depth_buffer.get();
  807. if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
  808. for (int y = 0; y < fb_depth_texture.height; ++y) {
  809. for (int x = 0; x < fb_depth_texture.width; ++x) {
  810. const u32 coarse_y = y & ~7;
  811. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
  812. u32 gl_pixel_index = (x + y * fb_depth_texture.width);
  813. u8* pixel = depth_buffer + dst_offset;
  814. u32 depth_stencil = ((u32*)temp_gl_depth_data)[gl_pixel_index];
  815. *(u32*)pixel = (depth_stencil >> 8) | (depth_stencil << 24);
  816. }
  817. }
  818. } else {
  819. for (int y = 0; y < fb_depth_texture.height; ++y) {
  820. for (int x = 0; x < fb_depth_texture.width; ++x) {
  821. const u32 coarse_y = y & ~7;
  822. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
  823. u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
  824. u8* pixel = depth_buffer + dst_offset;
  825. memcpy(pixel, &temp_gl_depth_data[gl_pixel_index], bytes_per_pixel);
  826. }
  827. }
  828. }
  829. }
  830. }
  831. }