PixelShaderManager.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "VideoCommon/PixelShaderManager.h"
  4. #include <iterator>
  5. #include "Common/ChunkFile.h"
  6. #include "Common/CommonTypes.h"
  7. #include "VideoCommon/FramebufferManager.h"
  8. #include "VideoCommon/VideoCommon.h"
  9. #include "VideoCommon/VideoConfig.h"
  10. #include "VideoCommon/XFMemory.h"
  11. void PixelShaderManager::Init()
  12. {
  13. constants = {};
  14. // Init any intial constants which aren't zero when bpmem is zero.
  15. m_fog_range_adjusted_changed = true;
  16. m_viewport_changed = false;
  17. SetIndMatrixChanged(0);
  18. SetIndMatrixChanged(1);
  19. SetIndMatrixChanged(2);
  20. SetZTextureTypeChanged();
  21. SetTexCoordChanged(0);
  22. SetTexCoordChanged(1);
  23. SetTexCoordChanged(2);
  24. SetTexCoordChanged(3);
  25. SetTexCoordChanged(4);
  26. SetTexCoordChanged(5);
  27. SetTexCoordChanged(6);
  28. SetTexCoordChanged(7);
  29. // fixed Konstants
  30. for (int component = 0; component < 4; component++)
  31. {
  32. constants.konst[0][component] = 255; // 1
  33. constants.konst[1][component] = 223; // 7/8
  34. constants.konst[2][component] = 191; // 3/4
  35. constants.konst[3][component] = 159; // 5/8
  36. constants.konst[4][component] = 128; // 1/2
  37. constants.konst[5][component] = 96; // 3/8
  38. constants.konst[6][component] = 64; // 1/4
  39. constants.konst[7][component] = 32; // 1/8
  40. // Invalid Konstants (reads as zero on hardware)
  41. constants.konst[8][component] = 0;
  42. constants.konst[9][component] = 0;
  43. constants.konst[10][component] = 0;
  44. constants.konst[11][component] = 0;
  45. // Annoyingly, alpha reads zero values for the .rgb colors (offically
  46. // defined as invalid)
  47. // If it wasn't for this, we could just use one of the first 3 colunms
  48. // instead of
  49. // wasting an entire 4th column just for alpha.
  50. if (component == 3)
  51. {
  52. constants.konst[12][component] = 0;
  53. constants.konst[13][component] = 0;
  54. constants.konst[14][component] = 0;
  55. constants.konst[15][component] = 0;
  56. }
  57. }
  58. Dirty();
  59. }
  60. void PixelShaderManager::Dirty()
  61. {
  62. // This function is called after a savestate is loaded.
  63. // Any constants that can changed based on settings should be re-calculated
  64. m_fog_range_adjusted_changed = true;
  65. SetEfbScaleChanged(g_framebuffer_manager->EFBToScaledXf(1),
  66. g_framebuffer_manager->EFBToScaledYf(1));
  67. SetFogParamChanged();
  68. dirty = true;
  69. }
  70. void PixelShaderManager::SetConstants()
  71. {
  72. if (m_fog_range_adjusted_changed)
  73. {
  74. // set by two components, so keep changed flag here
  75. // TODO: try to split both registers and move this logic to the shader
  76. if (!g_ActiveConfig.bDisableFog && bpmem.fogRange.Base.Enabled == 1)
  77. {
  78. // bpmem.fogRange.Base.Center : center of the viewport in x axis. observation:
  79. // bpmem.fogRange.Base.Center = realcenter + 342;
  80. int center = ((u32)bpmem.fogRange.Base.Center) - 342;
  81. // normalize center to make calculations easy
  82. float ScreenSpaceCenter = center / (2.0f * xfmem.viewport.wd);
  83. ScreenSpaceCenter = (ScreenSpaceCenter * 2.0f) - 1.0f;
  84. // bpmem.fogRange.K seems to be a table of precalculated coefficients for the adjust factor
  85. // observations: bpmem.fogRange.K[0].LO appears to be the lowest value and
  86. // bpmem.fogRange.K[4].HI the largest
  87. // they always seems to be larger than 256 so my theory is :
  88. // they are the coefficients from the center to the border of the screen
  89. // so to simplify I use the hi coefficient as K in the shader taking 256 as the scale
  90. // TODO: Shouldn't this be EFBToScaledXf?
  91. constants.fogf[2] = ScreenSpaceCenter;
  92. constants.fogf[3] = static_cast<float>(
  93. g_framebuffer_manager->EFBToScaledX(static_cast<int>(2.0f * xfmem.viewport.wd)));
  94. for (size_t i = 0, vec_index = 0; i < std::size(bpmem.fogRange.K); i++)
  95. {
  96. constexpr float scale = 4.0f;
  97. constants.fogrange[vec_index / 4][vec_index % 4] = bpmem.fogRange.K[i].GetValue(0) * scale;
  98. vec_index++;
  99. constants.fogrange[vec_index / 4][vec_index % 4] = bpmem.fogRange.K[i].GetValue(1) * scale;
  100. vec_index++;
  101. }
  102. }
  103. else
  104. {
  105. constants.fogf[2] = 0;
  106. constants.fogf[3] = 1;
  107. }
  108. dirty = true;
  109. m_fog_range_adjusted_changed = false;
  110. }
  111. if (m_viewport_changed)
  112. {
  113. constants.zbias[1][0] = (s32)xfmem.viewport.farZ;
  114. constants.zbias[1][1] = (s32)xfmem.viewport.zRange;
  115. dirty = true;
  116. m_viewport_changed = false;
  117. }
  118. if (m_indirect_dirty)
  119. {
  120. for (int i = 0; i < 4; i++)
  121. constants.pack1[i][3] = 0;
  122. for (u32 i = 0; i < (bpmem.genMode.numtevstages + 1); ++i)
  123. {
  124. // Note: a tevind of zero just happens to be a passthrough, so no need
  125. // to set an extra bit. Furthermore, wrap and add to previous apply even if there is no
  126. // indirect stage.
  127. constants.pack1[i][2] = bpmem.tevind[i].hex;
  128. u32 stage = bpmem.tevind[i].bt;
  129. // We use an extra bit (1 << 16) to provide a fast way of testing if this feature is in use.
  130. // Note also that this is indexed by indirect stage, not by TEV stage.
  131. if (bpmem.tevind[i].IsActive() && stage < bpmem.genMode.numindstages)
  132. constants.pack1[stage][3] =
  133. bpmem.tevindref.getTexCoord(stage) | bpmem.tevindref.getTexMap(stage) << 8 | 1 << 16;
  134. }
  135. dirty = true;
  136. m_indirect_dirty = false;
  137. }
  138. if (m_dest_alpha_dirty)
  139. {
  140. // Destination alpha is only enabled if alpha writes are enabled. Force entire uniform to zero
  141. // when disabled.
  142. u32 dstalpha = bpmem.blendmode.alphaupdate && bpmem.dstalpha.enable &&
  143. bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24 ?
  144. bpmem.dstalpha.hex :
  145. 0;
  146. if (constants.dstalpha != dstalpha)
  147. {
  148. constants.dstalpha = dstalpha;
  149. dirty = true;
  150. }
  151. }
  152. }
  153. void PixelShaderManager::SetTevColor(int index, int component, s32 value)
  154. {
  155. auto& c = constants.colors[index];
  156. c[component] = value;
  157. dirty = true;
  158. PRIM_LOG("tev color{}: {} {} {} {}", index, c[0], c[1], c[2], c[3]);
  159. }
  160. void PixelShaderManager::SetTevKonstColor(int index, int component, s32 value)
  161. {
  162. auto& c = constants.kcolors[index];
  163. c[component] = value;
  164. dirty = true;
  165. // Konst for ubershaders. We build the whole array on cpu so the gpu can do a single indirect
  166. // access.
  167. if (component != 3) // Alpha doesn't included in the .rgb konsts
  168. constants.konst[index + 12][component] = value;
  169. // .rrrr .gggg .bbbb .aaaa konsts
  170. constants.konst[index + 16 + component * 4][0] = value;
  171. constants.konst[index + 16 + component * 4][1] = value;
  172. constants.konst[index + 16 + component * 4][2] = value;
  173. constants.konst[index + 16 + component * 4][3] = value;
  174. PRIM_LOG("tev konst color{}: {} {} {} {}", index, c[0], c[1], c[2], c[3]);
  175. }
  176. void PixelShaderManager::SetTevOrder(int index, u32 order)
  177. {
  178. if (constants.pack2[index][0] != order)
  179. {
  180. constants.pack2[index][0] = order;
  181. dirty = true;
  182. }
  183. }
  184. void PixelShaderManager::SetTevKSel(int index, u32 ksel)
  185. {
  186. if (constants.pack2[index][1] != ksel)
  187. {
  188. constants.pack2[index][1] = ksel;
  189. dirty = true;
  190. }
  191. }
  192. void PixelShaderManager::SetTevCombiner(int index, int alpha, u32 combiner)
  193. {
  194. if (constants.pack1[index][alpha] != combiner)
  195. {
  196. constants.pack1[index][alpha] = combiner;
  197. dirty = true;
  198. }
  199. }
  200. void PixelShaderManager::SetTevIndirectChanged()
  201. {
  202. m_indirect_dirty = true;
  203. }
  204. void PixelShaderManager::SetAlpha()
  205. {
  206. constants.alpha[0] = bpmem.alpha_test.ref0;
  207. constants.alpha[1] = bpmem.alpha_test.ref1;
  208. constants.alpha[3] = static_cast<s32>(bpmem.dstalpha.alpha);
  209. dirty = true;
  210. }
  211. void PixelShaderManager::SetAlphaTestChanged()
  212. {
  213. // Force alphaTest Uniform to zero if it will always pass.
  214. // (set an extra bit to distinguish from "never && never")
  215. // TODO: we could optimize this further and check the actual constants,
  216. // i.e. "a <= 0" and "a >= 255" will always pass.
  217. u32 alpha_test =
  218. bpmem.alpha_test.TestResult() != AlphaTestResult::Pass ? bpmem.alpha_test.hex | 1 << 31 : 0;
  219. if (constants.alphaTest != alpha_test)
  220. {
  221. constants.alphaTest = alpha_test;
  222. dirty = true;
  223. }
  224. }
  225. void PixelShaderManager::SetDestAlphaChanged()
  226. {
  227. m_dest_alpha_dirty = true;
  228. }
  229. void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height)
  230. {
  231. // TODO: move this check out to callee. There we could just call this function on texture changes
  232. // or better, use textureSize() in glsl
  233. if (constants.texdims[texmapid][0] != width || constants.texdims[texmapid][1] != height)
  234. dirty = true;
  235. constants.texdims[texmapid][0] = width;
  236. constants.texdims[texmapid][1] = height;
  237. }
  238. void PixelShaderManager::SetSamplerState(int texmapid, u32 tm0, u32 tm1)
  239. {
  240. if (constants.pack2[texmapid][2] != tm0 || constants.pack2[texmapid][3] != tm1)
  241. dirty = true;
  242. constants.pack2[texmapid][2] = tm0;
  243. constants.pack2[texmapid][3] = tm1;
  244. }
  245. void PixelShaderManager::SetZTextureBias()
  246. {
  247. constants.zbias[1][3] = bpmem.ztex1.bias;
  248. dirty = true;
  249. }
  250. void PixelShaderManager::SetViewportChanged()
  251. {
  252. m_viewport_changed = true;
  253. m_fog_range_adjusted_changed =
  254. true; // TODO: Shouldn't be necessary with an accurate fog range adjust implementation
  255. }
  256. void PixelShaderManager::SetEfbScaleChanged(float scalex, float scaley)
  257. {
  258. constants.efbscale[0] = 1.0f / scalex;
  259. constants.efbscale[1] = 1.0f / scaley;
  260. dirty = true;
  261. }
  262. void PixelShaderManager::SetZSlope(float dfdx, float dfdy, float f0)
  263. {
  264. constants.zslope[0] = dfdx;
  265. constants.zslope[1] = dfdy;
  266. constants.zslope[2] = f0;
  267. dirty = true;
  268. }
  269. void PixelShaderManager::SetIndTexScaleChanged(bool high)
  270. {
  271. constants.indtexscale[high][0] = bpmem.texscale[high].ss0;
  272. constants.indtexscale[high][1] = bpmem.texscale[high].ts0;
  273. constants.indtexscale[high][2] = bpmem.texscale[high].ss1;
  274. constants.indtexscale[high][3] = bpmem.texscale[high].ts1;
  275. dirty = true;
  276. }
  277. void PixelShaderManager::SetIndMatrixChanged(int matrixidx)
  278. {
  279. const u8 scale = bpmem.indmtx[matrixidx].GetScale();
  280. // xyz - static matrix
  281. // w - dynamic matrix scale / 128
  282. constants.indtexmtx[2 * matrixidx][0] = bpmem.indmtx[matrixidx].col0.ma;
  283. constants.indtexmtx[2 * matrixidx][1] = bpmem.indmtx[matrixidx].col1.mc;
  284. constants.indtexmtx[2 * matrixidx][2] = bpmem.indmtx[matrixidx].col2.me;
  285. constants.indtexmtx[2 * matrixidx][3] = 17 - scale;
  286. constants.indtexmtx[2 * matrixidx + 1][0] = bpmem.indmtx[matrixidx].col0.mb;
  287. constants.indtexmtx[2 * matrixidx + 1][1] = bpmem.indmtx[matrixidx].col1.md;
  288. constants.indtexmtx[2 * matrixidx + 1][2] = bpmem.indmtx[matrixidx].col2.mf;
  289. constants.indtexmtx[2 * matrixidx + 1][3] = 17 - scale;
  290. dirty = true;
  291. PRIM_LOG("indmtx{}: scale={}, mat=({} {} {}; {} {} {})", matrixidx, scale,
  292. bpmem.indmtx[matrixidx].col0.ma, bpmem.indmtx[matrixidx].col1.mc,
  293. bpmem.indmtx[matrixidx].col2.me, bpmem.indmtx[matrixidx].col0.mb,
  294. bpmem.indmtx[matrixidx].col1.md, bpmem.indmtx[matrixidx].col2.mf);
  295. }
  296. void PixelShaderManager::SetZTextureTypeChanged()
  297. {
  298. switch (bpmem.ztex2.type)
  299. {
  300. case ZTexFormat::U8:
  301. constants.zbias[0][0] = 0;
  302. constants.zbias[0][1] = 0;
  303. constants.zbias[0][2] = 0;
  304. constants.zbias[0][3] = 1;
  305. break;
  306. case ZTexFormat::U16:
  307. constants.zbias[0][0] = 1;
  308. constants.zbias[0][1] = 0;
  309. constants.zbias[0][2] = 0;
  310. constants.zbias[0][3] = 256;
  311. break;
  312. case ZTexFormat::U24:
  313. constants.zbias[0][0] = 65536;
  314. constants.zbias[0][1] = 256;
  315. constants.zbias[0][2] = 1;
  316. constants.zbias[0][3] = 0;
  317. break;
  318. default:
  319. PanicAlertFmt("Invalid ztex format {}", bpmem.ztex2.type);
  320. break;
  321. }
  322. dirty = true;
  323. }
  324. void PixelShaderManager::SetZTextureOpChanged()
  325. {
  326. constants.ztex_op = bpmem.ztex2.op;
  327. dirty = true;
  328. }
  329. void PixelShaderManager::SetTexCoordChanged(u8 texmapid)
  330. {
  331. TCoordInfo& tc = bpmem.texcoords[texmapid];
  332. constants.texdims[texmapid][2] = tc.s.scale_minus_1 + 1;
  333. constants.texdims[texmapid][3] = tc.t.scale_minus_1 + 1;
  334. dirty = true;
  335. }
  336. void PixelShaderManager::SetFogColorChanged()
  337. {
  338. if (g_ActiveConfig.bDisableFog)
  339. return;
  340. constants.fogcolor[0] = bpmem.fog.color.r;
  341. constants.fogcolor[1] = bpmem.fog.color.g;
  342. constants.fogcolor[2] = bpmem.fog.color.b;
  343. dirty = true;
  344. }
  345. void PixelShaderManager::SetFogParamChanged()
  346. {
  347. if (!g_ActiveConfig.bDisableFog)
  348. {
  349. constants.fogf[0] = bpmem.fog.GetA();
  350. constants.fogf[1] = bpmem.fog.GetC();
  351. constants.fogi[1] = bpmem.fog.b_magnitude;
  352. constants.fogi[3] = bpmem.fog.b_shift;
  353. constants.fogParam3 = bpmem.fog.c_proj_fsel.hex;
  354. }
  355. else
  356. {
  357. constants.fogf[0] = 0.f;
  358. constants.fogf[1] = 0.f;
  359. constants.fogi[1] = 1;
  360. constants.fogi[3] = 1;
  361. constants.fogParam3 = 0;
  362. }
  363. dirty = true;
  364. }
  365. void PixelShaderManager::SetFogRangeAdjustChanged()
  366. {
  367. if (g_ActiveConfig.bDisableFog)
  368. return;
  369. m_fog_range_adjusted_changed = true;
  370. if (constants.fogRangeBase != bpmem.fogRange.Base.hex)
  371. {
  372. constants.fogRangeBase = bpmem.fogRange.Base.hex;
  373. dirty = true;
  374. }
  375. }
  376. void PixelShaderManager::SetGenModeChanged()
  377. {
  378. constants.genmode = bpmem.genMode.hex;
  379. m_indirect_dirty = true;
  380. dirty = true;
  381. }
  382. void PixelShaderManager::SetZModeControl()
  383. {
  384. u32 late_ztest = bpmem.GetEmulatedZ() == EmulatedZ::Late;
  385. u32 rgba6_format =
  386. (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor) ?
  387. 1 :
  388. 0;
  389. u32 dither = rgba6_format && bpmem.blendmode.dither;
  390. if (constants.late_ztest != late_ztest || constants.rgba6_format != rgba6_format ||
  391. constants.dither != dither)
  392. {
  393. constants.late_ztest = late_ztest;
  394. constants.rgba6_format = rgba6_format;
  395. constants.dither = dither;
  396. dirty = true;
  397. }
  398. m_dest_alpha_dirty = true;
  399. }
  400. void PixelShaderManager::SetBlendModeChanged()
  401. {
  402. u32 dither = constants.rgba6_format && bpmem.blendmode.dither;
  403. if (constants.dither != dither)
  404. {
  405. constants.dither = dither;
  406. dirty = true;
  407. }
  408. BlendingState state = {};
  409. state.Generate(bpmem);
  410. if (constants.blend_enable != state.blendenable)
  411. {
  412. constants.blend_enable = state.blendenable;
  413. dirty = true;
  414. }
  415. if (constants.blend_src_factor != state.srcfactor)
  416. {
  417. constants.blend_src_factor = state.srcfactor;
  418. dirty = true;
  419. }
  420. if (constants.blend_src_factor_alpha != state.srcfactoralpha)
  421. {
  422. constants.blend_src_factor_alpha = state.srcfactoralpha;
  423. dirty = true;
  424. }
  425. if (constants.blend_dst_factor != state.dstfactor)
  426. {
  427. constants.blend_dst_factor = state.dstfactor;
  428. dirty = true;
  429. }
  430. if (constants.blend_dst_factor_alpha != state.dstfactoralpha)
  431. {
  432. constants.blend_dst_factor_alpha = state.dstfactoralpha;
  433. dirty = true;
  434. }
  435. if (constants.blend_subtract != state.subtract)
  436. {
  437. constants.blend_subtract = state.subtract;
  438. dirty = true;
  439. }
  440. if (constants.blend_subtract_alpha != state.subtractAlpha)
  441. {
  442. constants.blend_subtract_alpha = state.subtractAlpha;
  443. dirty = true;
  444. }
  445. if (constants.logic_op_enable != state.logicopenable)
  446. {
  447. constants.logic_op_enable = state.logicopenable;
  448. dirty = true;
  449. }
  450. if (constants.logic_op_mode != state.logicmode)
  451. {
  452. constants.logic_op_mode = state.logicmode;
  453. dirty = true;
  454. }
  455. m_dest_alpha_dirty = true;
  456. }
  457. void PixelShaderManager::SetBoundingBoxActive(bool active)
  458. {
  459. const bool enable = active && g_ActiveConfig.bBBoxEnable;
  460. if (enable == (constants.bounding_box != 0))
  461. return;
  462. constants.bounding_box = active;
  463. dirty = true;
  464. }
  465. void PixelShaderManager::DoState(PointerWrap& p)
  466. {
  467. p.Do(m_fog_range_adjusted_changed);
  468. p.Do(m_viewport_changed);
  469. p.Do(m_indirect_dirty);
  470. p.Do(m_dest_alpha_dirty);
  471. p.Do(constants);
  472. if (p.IsReadMode())
  473. {
  474. // Fixup the current state from global GPU state
  475. // NOTE: This requires that all GPU memory has been loaded already.
  476. Dirty();
  477. }
  478. }