설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

STP.cs 67KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. using System;
  2. using UnityEngine.Assertions;
  3. using UnityEngine.Experimental.Rendering;
  4. using UnityEngine.Rendering.RenderGraphModule;
  5. namespace UnityEngine.Rendering
  6. {
  7. /// <summary>
  8. /// Interface to the Spatial-Temporal Post-Processing Upscaler (STP).
  9. /// This class allows users to configure and execute STP via render graph.
  10. /// </summary>
  11. public static class STP
  12. {
  13. /// <summary>
  14. /// Returns true if STP is supported on the current device. Otherwise, false.
  15. /// STP requires compute shaders
  16. /// </summary>
  17. /// <returns>True if supported</returns>
  18. public static bool IsSupported()
  19. {
  20. bool isSupported = true;
  21. // STP uses compute shaders as part of its implementation
  22. isSupported &= SystemInfo.supportsComputeShaders;
  23. // GLES has stricter rules than GL when it comes to image store format declarations and matching them with underlying image types.
  24. // STP's implementation uses several image formats that don't translate accurately from HLSL to GLSL which means a format mismatch will occur.
  25. // Image format mismatches result in undefined behavior on writes, so we disable STP support for GLES in order to avoid problems.
  26. // In most cases, hardware that meets the requirements for STP should be capable of running Vulkan anyways.
  27. isSupported &= (SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES3);
  28. return isSupported;
  29. }
  30. /// <summary>
  31. /// Helper function that calculates the STP-specific jitter pattern associated with the provided frame index.
  32. /// </summary>
  33. /// <param name="frameIndex">Index of the current frame</param>
  34. /// <returns>Jitter pattern for the provided frame index</returns>
  35. public static Vector2 Jit16(int frameIndex)
  36. {
  37. Vector2 result;
  38. result.x = HaltonSequence.Get(frameIndex, 2) - 0.5f;
  39. result.y = HaltonSequence.Get(frameIndex, 3) - 0.5f;
  40. return result;
  41. }
  42. // We use a constant to define the debug view arrays to guarantee that they're exactly the same length at compile time
  43. const int kNumDebugViews = 6;
  44. // We define a fixed array of GUIContent values here which map to supported debug views within the STP shader code
  45. static readonly GUIContent[] s_DebugViewDescriptions = new GUIContent[kNumDebugViews]
  46. {
  47. new GUIContent("Clipped Input Color", "Shows input color clipped to {0 to 1}"),
  48. new GUIContent("Log Input Depth", "Shows input depth in log scale"),
  49. new GUIContent("Reversible Tonemapped Input Color", "Shows input color after conversion to reversible tonemaped space"),
  50. new GUIContent("Shaped Absolute Input Motion", "Visualizes input motion vectors"),
  51. new GUIContent("Motion Reprojection {R=Prior G=This Sqrt Luma Feedback Diff, B=Offscreen}", "Visualizes reprojected frame difference"),
  52. new GUIContent("Sensitivity {G=No motion match, R=Responsive, B=Luma}", "Visualize pixel sensitivities"),
  53. };
  54. // Unfortunately we must maintain a sequence of index values that map to the supported debug view indices
  55. // if we want to be able to display the debug views as an enum field without allocating any garbage.
  56. static readonly int[] s_DebugViewIndices = new int[kNumDebugViews]
  57. {
  58. 0,
  59. 1,
  60. 2,
  61. 3,
  62. 4,
  63. 5,
  64. };
  65. /// <summary>
  66. /// Array of debug view descriptions expected to be used in the rendering debugger UI
  67. /// </summary>
  68. public static GUIContent[] debugViewDescriptions { get { return s_DebugViewDescriptions; } }
  69. /// <summary>
  70. /// Array of debug view indices expected to be used in the rendering debugger UI
  71. /// </summary>
  72. public static int[] debugViewIndices { get { return s_DebugViewIndices; } }
  73. /// <summary>
  74. /// STP configuration data that varies per rendered view
  75. /// </summary>
  76. public struct PerViewConfig
  77. {
  78. /// <summary>
  79. /// Non-Jittered projection matrix for the current frame
  80. /// Used by the static geometry reprojection feature
  81. /// </summary>
  82. public Matrix4x4 currentProj;
  83. /// <summary>
  84. /// Non-Jittered projection matrix for the previous frame
  85. /// Used by the static geometry reprojection feature
  86. /// </summary>
  87. public Matrix4x4 lastProj;
  88. /// <summary>
  89. /// Non-Jittered projection matrix for the frame before the previous frame
  90. /// Used by the static geometry reprojection feature
  91. /// </summary>
  92. public Matrix4x4 lastLastProj;
  93. /// <summary>
  94. /// View matrix for the current frame
  95. /// Used by the static geometry reprojection feature
  96. /// </summary>
  97. public Matrix4x4 currentView;
  98. /// <summary>
  99. /// View matrix for the previous frame
  100. /// Used by the static geometry reprojection feature
  101. /// </summary>
  102. public Matrix4x4 lastView;
  103. /// <summary>
  104. /// View matrix for the frame before the previous frame
  105. /// Used by the static geometry reprojection feature
  106. /// </summary>
  107. public Matrix4x4 lastLastView;
  108. }
  109. /// <summary>
  110. /// Maximum amount of supported per-view configurations
  111. /// </summary>
  112. const int kMaxPerViewConfigs = 2;
  113. /// <summary>
  114. /// Static allocation of per-view configurations
  115. /// </summary>
  116. static PerViewConfig[] s_PerViewConfigs = new PerViewConfig[kMaxPerViewConfigs];
  117. /// <summary>
  118. /// Static allocation of per-view configurations
  119. /// Users are expected to populate this during STP configuration and then assign it to the relevant
  120. /// configuration structure field(s) to avoid unnecessary allocations.
  121. /// </summary>
  122. public static PerViewConfig[] perViewConfigs
  123. {
  124. get { return s_PerViewConfigs; }
  125. set { s_PerViewConfigs = value; }
  126. }
  127. /// <summary>
  128. /// Top-level configuration structure required for STP execution
  129. /// </summary>
  130. public struct Config
  131. {
  132. /// <summary>
  133. /// Blue noise texture used in various parts of the upscaling logic
  134. /// </summary>
  135. public Texture2D noiseTexture;
  136. /// <summary>
  137. /// Input color texture to be upscaled
  138. /// </summary>
  139. public TextureHandle inputColor;
  140. /// <summary>
  141. /// Input depth texture which will be analyzed during upscaling
  142. /// </summary>
  143. public TextureHandle inputDepth;
  144. /// <summary>
  145. /// Input motion vector texture which is used to reproject information across frames
  146. /// </summary>
  147. public TextureHandle inputMotion;
  148. /// <summary>
  149. /// [Optional] Input stencil texture which is used to identify pixels that need special treatment such as particles or in-game screens
  150. /// </summary>
  151. public TextureHandle inputStencil;
  152. /// <summary>
  153. /// [Optional] Output debug view texture which STP can be configured to render debug visualizations into
  154. /// </summary>
  155. public TextureHandle debugView;
  156. /// <summary>
  157. /// Output color texture which will receive the final upscaled color result
  158. /// </summary>
  159. public TextureHandle destination;
  160. /// <summary>
  161. /// Input history context to use when executing STP
  162. /// </summary>
  163. public HistoryContext historyContext;
  164. /// <summary>
  165. /// Set to true if hardware dynamic resolution scaling is currently active
  166. /// </summary>
  167. public bool enableHwDrs;
  168. /// <summary>
  169. /// Set to true if the rendering environment is using 2d array textures (usually due to XR)
  170. /// </summary>
  171. public bool enableTexArray;
  172. /// <summary>
  173. /// Set to true to enable the motion scaling feature which attempts to compensate for variable frame timing when working with motion vectors
  174. /// </summary>
  175. public bool enableMotionScaling;
  176. /// <summary>
  177. /// Distance to the camera's near plane
  178. /// Used to encode depth values
  179. /// </summary>
  180. public float nearPlane;
  181. /// <summary>
  182. /// Distance to the camera's far plane
  183. /// Used to encode depth values
  184. /// </summary>
  185. public float farPlane;
  186. /// <summary>
  187. /// Index of the current frame
  188. /// Used to calculate jitter pattern
  189. /// </summary>
  190. public int frameIndex;
  191. /// <summary>
  192. /// True if the current frame has valid history information
  193. /// Used to prevent STP from producing invalid data
  194. /// </summary>
  195. public bool hasValidHistory;
  196. /// <summary>
  197. /// A mask value applied that determines which stencil bit is associated with the responsive feature
  198. /// Used to prevent STP from producing incorrect values on transparent pixels
  199. /// Set to 0 if no stencil data is present
  200. /// </summary>
  201. public int stencilMask;
  202. /// <summary>
  203. /// An index value that indicates which debug visualization to render in the debug view
  204. /// This value is only used when a valid debug view handle is provided
  205. /// </summary>
  206. public int debugViewIndex;
  207. /// <summary>
  208. /// Delta frame time for the current frame
  209. /// Used to compensate for inconsistent frame timings when working with motion vectors
  210. /// </summary>
  211. public float deltaTime;
  212. /// <summary>
  213. /// Delta frame time for the previous frame
  214. /// Used to compensate for inconsistent frame timings when working with motion vectors
  215. /// </summary>
  216. public float lastDeltaTime;
  217. /// <summary>
  218. /// Size of the current viewport in pixels
  219. /// Used to calculate image coordinate scaling factors
  220. /// </summary>
  221. public Vector2Int currentImageSize;
  222. /// <summary>
  223. /// Size of the previous viewport in pixels
  224. /// Used to calculate image coordinate scaling factors
  225. /// </summary>
  226. public Vector2Int priorImageSize;
  227. /// <summary>
  228. /// Size of the upscaled output image in pixels
  229. /// Used to calculate image coordinate scaling factors
  230. /// </summary>
  231. public Vector2Int outputImageSize;
  232. /// <summary>
  233. /// Number of active views in the perViewConfigs array
  234. /// </summary>
  235. public int numActiveViews;
  236. /// <summary>
  237. /// Configuration parameters that are unique per rendered view
  238. /// </summary>
  239. public PerViewConfig[] perViewConfigs;
  240. }
  241. /// <summary>
  242. /// Enumeration of unique types of history textures
  243. /// </summary>
  244. internal enum HistoryTextureType
  245. {
  246. DepthMotion,
  247. Luma,
  248. Convergence,
  249. Feedback,
  250. Count
  251. }
  252. /// <summary>
  253. /// Number of unique types of history textures used by STP
  254. /// </summary>
  255. const int kNumHistoryTextureTypes = (int)HistoryTextureType.Count;
  256. /// <summary>
  257. /// Describes the information needed to update the history context
  258. /// </summary>
  259. public struct HistoryUpdateInfo
  260. {
  261. /// <summary>
  262. /// Size of the target image before upscaling is applied
  263. /// </summary>
  264. public Vector2Int preUpscaleSize;
  265. /// <summary>
  266. /// Size of the target image after upscaling is applied
  267. /// </summary>
  268. public Vector2Int postUpscaleSize;
  269. /// <summary>
  270. /// True if hardware dynamic resolution scaling is active
  271. /// </summary>
  272. public bool useHwDrs;
  273. /// <summary>
  274. /// True if texture arrays are being used in the current rendering environment
  275. /// </summary>
  276. public bool useTexArray;
  277. }
  278. /// <summary>
  279. /// Computes a hash value that changes whenever the history context needs to be re-created
  280. /// </summary>
  281. /// <param name="hashParams">parameters used to calculate the history hash</param>
  282. /// <returns>A hash value that changes whenever the history context needs to be re-created</returns>
  283. static Hash128 ComputeHistoryHash(ref HistoryUpdateInfo info)
  284. {
  285. Hash128 hash = new Hash128();
  286. hash.Append(ref info.useHwDrs);
  287. hash.Append(ref info.useTexArray);
  288. hash.Append(ref info.postUpscaleSize);
  289. // The pre-upscale size only affects the history texture logic when hardware dynamic resolution scaling is disabled.
  290. if (!info.useHwDrs)
  291. {
  292. hash.Append(ref info.preUpscaleSize);
  293. }
  294. return hash;
  295. }
  296. /// <summary>
  297. /// Calculates the correct size for the STP low-frequency convergence texture
  298. /// </summary>
  299. /// <param name="historyTextureSize">size of the render-size history textures used by STP</param>
  300. /// <returns>size of the convergence texture</returns>
  301. static Vector2Int CalculateConvergenceTextureSize(Vector2Int historyTextureSize)
  302. {
  303. // The convergence texture is a 4x4 reduction of data computed at render size, but we must always make sure the size is rounded up.
  304. return new Vector2Int(CoreUtils.DivRoundUp(historyTextureSize.x, 4), CoreUtils.DivRoundUp(historyTextureSize.y, 4));
  305. }
  306. /// <summary>
  307. /// Opaque history information required by STP's implementation
  308. /// Users are expected to create their own persistent history context, update it once per frame, and provide it to
  309. /// STP's execution logic through the configuration structure.
  310. /// </summary>
  311. public sealed class HistoryContext : IDisposable
  312. {
  313. /// <summary>
  314. /// Array of history textures used by STP
  315. /// The array is subdivided into two sets. Each set represents the history textures for a single frame.
  316. /// </summary>
  317. RTHandle[] m_textures = new RTHandle[kNumHistoryTextureTypes * 2];
  318. /// <summary>
  319. /// Hash value that changes whenever the history context needs to be re-created
  320. /// </summary>
  321. Hash128 m_hash = Hash128.Compute(0);
  322. /// <summary>
  323. /// Updated the state of the history context based on the provided information
  324. /// This may result in re-allocation of resources internally if state has changed and is now incompatible or if this is the first update
  325. /// </summary>
  326. /// <param name="info">information required to update the history context</param>
  327. /// <returns>True if the internal history data within the context is valid after the update operation</returns>
  328. public bool Update(ref HistoryUpdateInfo info)
  329. {
  330. bool hasValidHistory = true;
  331. var hash = ComputeHistoryHash(ref info);
  332. if (hash != m_hash)
  333. {
  334. hasValidHistory = false;
  335. Dispose();
  336. m_hash = hash;
  337. // Allocate two new sets of history textures for STP based on the current settings
  338. Vector2Int historyTextureSize = info.useHwDrs ? info.postUpscaleSize : info.preUpscaleSize;
  339. TextureDimension texDimension = info.useTexArray ? TextureDimension.Tex2DArray : TextureDimension.Tex2D;
  340. int width = 0;
  341. int height = 0;
  342. GraphicsFormat format = GraphicsFormat.None;
  343. bool useDynamicScaleExplicit = false;
  344. string name = "";
  345. for (int historyTypeIndex = 0; historyTypeIndex < kNumHistoryTextureTypes; ++historyTypeIndex)
  346. {
  347. switch ((HistoryTextureType)historyTypeIndex)
  348. {
  349. case HistoryTextureType.DepthMotion:
  350. {
  351. width = historyTextureSize.x;
  352. height = historyTextureSize.y;
  353. format = GraphicsFormat.R32_UInt;
  354. useDynamicScaleExplicit = info.useHwDrs;
  355. name = "STP Depth & Motion";
  356. break;
  357. }
  358. case HistoryTextureType.Luma:
  359. {
  360. width = historyTextureSize.x;
  361. height = historyTextureSize.y;
  362. format = GraphicsFormat.R8G8_UNorm;
  363. useDynamicScaleExplicit = info.useHwDrs;
  364. name = "STP Luma";
  365. break;
  366. }
  367. case HistoryTextureType.Convergence:
  368. {
  369. Vector2Int convergenceSize = CalculateConvergenceTextureSize(historyTextureSize);
  370. width = convergenceSize.x;
  371. height = convergenceSize.y;
  372. format = GraphicsFormat.R8_UNorm;
  373. useDynamicScaleExplicit = info.useHwDrs;
  374. name = "STP Convergence";
  375. break;
  376. }
  377. case HistoryTextureType.Feedback:
  378. {
  379. width = info.postUpscaleSize.x;
  380. height = info.postUpscaleSize.y;
  381. format = GraphicsFormat.A2B10G10R10_UNormPack32;
  382. useDynamicScaleExplicit = false;
  383. name = "STP Feedback";
  384. break;
  385. }
  386. default:
  387. {
  388. // Invalid history texture type
  389. Debug.Assert(false);
  390. break;
  391. }
  392. }
  393. for (int frameIndex = 0; frameIndex < 2; ++frameIndex)
  394. {
  395. int offset = (frameIndex * kNumHistoryTextureTypes) + historyTypeIndex;
  396. m_textures[offset] = RTHandles.Alloc(
  397. width, height, TextureXR.slices, DepthBits.None, format, dimension: texDimension, enableRandomWrite: true,
  398. name: name, useDynamicScaleExplicit: useDynamicScaleExplicit
  399. );
  400. }
  401. }
  402. }
  403. return hasValidHistory;
  404. }
  405. internal RTHandle GetCurrentHistoryTexture(HistoryTextureType historyType, int frameIndex)
  406. {
  407. return m_textures[((frameIndex & 1) * (int)HistoryTextureType.Count) + (int)historyType];
  408. }
  409. internal RTHandle GetPreviousHistoryTexture(HistoryTextureType historyType, int frameIndex)
  410. {
  411. return m_textures[(((frameIndex & 1) ^ 1) * (int)HistoryTextureType.Count) + (int)historyType];
  412. }
  413. /// <summary>
  414. /// Releases the internal resources held within the history context
  415. /// Typically things like texture allocations
  416. /// </summary>
  417. public void Dispose()
  418. {
  419. for (int texIndex = 0; texIndex < m_textures.Length; ++texIndex)
  420. {
  421. if (m_textures[texIndex] != null)
  422. {
  423. m_textures[texIndex].Release();
  424. m_textures[texIndex] = null;
  425. }
  426. }
  427. m_hash = Hash128.Compute(0);
  428. }
  429. }
  430. /// <summary>
  431. /// Returns a motion scaling ratio based on the difference in delta times across frames
  432. /// </summary>
  433. /// <param name="deltaTime">Time elapsed from the last frame to the current frame in seconds</param>
  434. /// <param name="lastDeltaTime">Time elapsed from the frame before the last frame to the last frame in seconds</param>
  435. /// <returns>Motion scale factor for the current frame</returns>
  436. static float CalculateMotionScale(float deltaTime, float lastDeltaTime)
  437. {
  438. float motionScale = 1.0f;
  439. float currentDeltaTime = deltaTime;
  440. float previousDeltaTime = lastDeltaTime;
  441. if (!Mathf.Approximately(previousDeltaTime, 0.0f))
  442. {
  443. motionScale = currentDeltaTime / previousDeltaTime;
  444. }
  445. return motionScale;
  446. }
  447. /// <summary>
  448. /// Returns a matrix with the translation component removed
  449. /// This function is intended to be used with view matrices
  450. /// </summary>
  451. /// <param name="input">input view matrix</param>
  452. /// <returns>a matrix with the translation component removed</returns>
  453. static Matrix4x4 ExtractRotation(Matrix4x4 input)
  454. {
  455. Matrix4x4 output = input;
  456. output[0, 3] = 0.0f;
  457. output[1, 3] = 0.0f;
  458. output[2, 3] = 0.0f;
  459. output[3, 3] = 1.0f;
  460. return output;
  461. }
  462. /// <summary>
  463. /// Helper function that converts the provided Vector2 into a packed integer with two FP16 values
  464. /// </summary>
  465. /// <param name="value">input Vector2 value to be packed</param>
  466. /// <returns>an integer that contains the two vector components packed together as FP16 values</returns>
  467. static int PackVector2ToInt(Vector2 value)
  468. {
  469. uint xAsHalf = Mathf.FloatToHalf(value.x);
  470. uint yAsHalf = Mathf.FloatToHalf(value.y);
  471. return (int)(xAsHalf | (yAsHalf << 16));
  472. }
  473. /// <summary>
  474. /// Number of constants that contain per-view information for the setup pass
  475. /// NOTE: The name here is important as it's directly translated into HLSL
  476. /// </summary>
  477. [GenerateHLSL(PackingRules.Exact)]
  478. enum StpSetupPerViewConstants
  479. {
  480. Count = 8
  481. };
  482. /// <summary>
  483. /// Total number of constants used for per-view data in STP
  484. /// </summary>
  485. const int kTotalSetupViewConstantsCount = kMaxPerViewConfigs * ((int)StpSetupPerViewConstants.Count);
  486. /// <summary>
  487. /// Constant buffer layout used by STP
  488. /// NOTE: The name here is important as it's directly translated into HLSL
  489. /// </summary>
  490. [GenerateHLSL(needAccessors = false, generateCBuffer = true)]
  491. unsafe struct StpConstantBufferData
  492. {
  493. public Vector4 _StpCommonConstant;
  494. public Vector4 _StpSetupConstants0;
  495. public Vector4 _StpSetupConstants1;
  496. public Vector4 _StpSetupConstants2;
  497. public Vector4 _StpSetupConstants3;
  498. public Vector4 _StpSetupConstants4;
  499. public Vector4 _StpSetupConstants5;
  500. [HLSLArray(kTotalSetupViewConstantsCount, typeof(Vector4))]
  501. public fixed float _StpSetupPerViewConstants[kTotalSetupViewConstantsCount * 4];
  502. public Vector4 _StpDilConstants0;
  503. public Vector4 _StpTaaConstants0;
  504. public Vector4 _StpTaaConstants1;
  505. public Vector4 _StpTaaConstants2;
  506. public Vector4 _StpTaaConstants3;
  507. }
  508. /// <summary>
  509. /// Produces constant buffer data in the format required by STP
  510. /// </summary>
  511. /// <param name="config">STP's configuration data</param>
  512. /// <param name="constants">constant buffer data structure required by STP</param>
  513. static void PopulateConstantData(ref Config config, ref StpConstantBufferData constants)
  514. {
  515. Assert.IsTrue(Mathf.IsPowerOfTwo(config.noiseTexture.width));
  516. //
  517. // Common
  518. //
  519. // [DebugViewIndex | StencilMask | HasValidHistory | (Width - 1)]
  520. int packedBlueNoiseWidthMinusOne = (config.noiseTexture.width - 1) & 0xFF;
  521. int packedHasValidHistory = (config.hasValidHistory ? 1 : 0) << 8;
  522. int packedStencilMask = (config.stencilMask & 0xFF) << 16;
  523. int packedDebugViewIndex = (config.debugViewIndex & 0xFF) << 24;
  524. int constant0 = packedStencilMask | packedHasValidHistory | packedBlueNoiseWidthMinusOne | packedDebugViewIndex;
  525. // Compute values used for linear depth conversion
  526. // These values are normally in the _ZBufferParams constant, but we re-compute them here since this constant is defined differently across SRPs
  527. float zBufferParamZ = (config.farPlane - config.nearPlane) / (config.nearPlane * config.farPlane);
  528. float zBufferParamW = 1.0f / config.farPlane;
  529. constants._StpCommonConstant = new Vector4(BitConverter.Int32BitsToSingle(constant0), zBufferParamZ, zBufferParamW, 0.0f);
  530. //
  531. // NOTE: The logic below is effectively a C# port of the HLSL constant setup logic found in Stp.hlsl
  532. // The C# code attempts to be as close as possible to the HLSL in order to simplify maintenance.
  533. //
  534. //
  535. // Setup
  536. //
  537. //------------------------------------------------------------------------------------------------------------------------------
  538. // StpF2 kRcpC := 1.0 / size of current input image in pixels.
  539. constants._StpSetupConstants0.x = (1.0f / config.currentImageSize.x);
  540. constants._StpSetupConstants0.y = (1.0f / config.currentImageSize.y);
  541. // StpF2 kHalfRcpC := 0.5 / size of current input image in pixels.
  542. constants._StpSetupConstants0.z = (0.5f / config.currentImageSize.x);
  543. constants._StpSetupConstants0.w = (0.5f / config.currentImageSize.y);
  544. //------------------------------------------------------------------------------------------------------------------------------
  545. // Grab jitter for current and prior frames.
  546. Vector2 jitP = Jit16(config.frameIndex - 1);
  547. Vector2 jitC = Jit16(config.frameIndex);
  548. // StpF2 kJitCRcpCUnjitPRcpP := Map current into prior frame.
  549. constants._StpSetupConstants1.x = (jitC.x / config.currentImageSize.x - jitP.x / config.priorImageSize.x);
  550. constants._StpSetupConstants1.y = (jitC.y / config.currentImageSize.y - jitP.y / config.priorImageSize.y);
  551. // StpF2 kJitCRcpC := Take {0 to 1} position in current image, and map back to {0 to 1} position in feedback (removes jitter).
  552. constants._StpSetupConstants1.z = jitC.x / config.currentImageSize.x;
  553. constants._StpSetupConstants1.w = jitC.y / config.currentImageSize.y;
  554. //------------------------------------------------------------------------------------------------------------------------------
  555. // StpF2 kF := size of feedback (aka output) in pixels.
  556. constants._StpSetupConstants2.x = config.outputImageSize.x;
  557. constants._StpSetupConstants2.y = config.outputImageSize.y;
  558. // StpF2 kDepth := Copied logic from StpZCon().
  559. float k0 = (1.0f / config.nearPlane);
  560. float k1 = (1.0f / Mathf.Log(k0 * config.farPlane, 2.0f));
  561. constants._StpSetupConstants2.z = k0;
  562. constants._StpSetupConstants2.w = k1;
  563. //------------------------------------------------------------------------------------------------------------------------------
  564. // StpF4 kOS := Scale and bias to check for out of bounds (and kill feedback).
  565. // Scaled and biased output needs to {-1 out of bounds, >-1 in bounds, <1 in bounds, 1 out of bounds}.
  566. Vector2 s;
  567. // Undo 'pM' scaling, and multiply by 2 (as this needs to be -1 to 1 at edge of acceptable reprojection).
  568. s.x = 2.0f;
  569. s.y = 2.0f;
  570. // Scaling to push outside safe reprojection over 1.
  571. s.x *= (config.priorImageSize.x / (config.priorImageSize.x + 4.0f));
  572. s.y *= (config.priorImageSize.y / (config.priorImageSize.y + 4.0f));
  573. constants._StpSetupConstants3.x = s[0];
  574. constants._StpSetupConstants3.y = s[1];
  575. // Factor out subtracting off the mid point scaled by the multiply term.
  576. constants._StpSetupConstants3.z = (-0.5f * s[0]);
  577. constants._StpSetupConstants3.w = (-0.5f * s[1]);
  578. //------------------------------------------------------------------------------------------------------------------------------
  579. // StpF2 kUnDepth := Copied logic from StpZUnCon().
  580. constants._StpSetupConstants4.x = Mathf.Log(config.farPlane / config.nearPlane, 2.0f);
  581. constants._StpSetupConstants4.y = config.nearPlane;
  582. // kMotionMatch
  583. constants._StpSetupConstants4.z = config.enableMotionScaling ? CalculateMotionScale(config.deltaTime, config.lastDeltaTime) : 1.0f;
  584. // Unused for now.
  585. constants._StpSetupConstants4.w = 0.0f;
  586. //------------------------------------------------------------------------------------------------------------------------------
  587. // StpF2 kC := Size of current input image in pixels.
  588. constants._StpSetupConstants5.x = config.currentImageSize.x;
  589. constants._StpSetupConstants5.y = config.currentImageSize.y;
  590. //------------------------------------------------------------------------------------------------------------------------------
  591. // StpF2 kFS := scale factor used to convert from feedback uv space to reduction uv space
  592. constants._StpSetupConstants5.z = config.outputImageSize.x / (Mathf.Ceil(config.outputImageSize.x / 4.0f) * 4.0f);
  593. constants._StpSetupConstants5.w = config.outputImageSize.y / (Mathf.Ceil(config.outputImageSize.y / 4.0f) * 4.0f);
  594. // Per View
  595. for (uint viewIndex = 0; viewIndex < config.numActiveViews; ++viewIndex)
  596. {
  597. uint baseViewDataOffset = viewIndex * ((int)StpSetupPerViewConstants.Count) * 4;
  598. var perViewConfig = config.perViewConfigs[viewIndex];
  599. //------------------------------------------------------------------------------------------------------------------------------
  600. // See header docs in "STATIC GEOMETRY MOTION FORWARD PROJECTION".
  601. Vector4 prjPriABEF;
  602. prjPriABEF.x = perViewConfig.lastProj[0, 0];
  603. // NOTE: Unity flips the Y axis inside the projection matrix. STP requires a non-flipped Y axis, so we undo the flip here with abs
  604. prjPriABEF.y = Mathf.Abs(perViewConfig.lastProj[1, 1]);
  605. // TODO: We need to understand why we need to negate these values for the inverse projection in order to get correct results.
  606. prjPriABEF.z = -perViewConfig.lastProj[0, 2];
  607. prjPriABEF.w = -perViewConfig.lastProj[1, 2];
  608. Vector4 prjPriCDGH;
  609. prjPriCDGH.x = perViewConfig.lastProj[2, 2];
  610. prjPriCDGH.y = perViewConfig.lastProj[2, 3];
  611. prjPriCDGH.z = perViewConfig.lastProj[3, 2];
  612. prjPriCDGH.w = perViewConfig.lastProj[3, 3];
  613. Vector4 prjCurABEF;
  614. prjCurABEF.x = perViewConfig.currentProj[0, 0];
  615. // NOTE: Unity flips the Y axis inside the projection matrix. STP requires a non-flipped Y axis, so we undo the flip here with abs
  616. prjCurABEF.y = Mathf.Abs(perViewConfig.currentProj[1, 1]);
  617. prjCurABEF.z = perViewConfig.currentProj[0, 2];
  618. prjCurABEF.w = perViewConfig.currentProj[1, 2];
  619. Vector4 prjCurCDGH;
  620. prjCurCDGH.x = perViewConfig.currentProj[2, 2];
  621. prjCurCDGH.y = perViewConfig.currentProj[2, 3];
  622. prjCurCDGH.z = perViewConfig.currentProj[3, 2];
  623. prjCurCDGH.w = perViewConfig.currentProj[3, 3];
  624. Matrix4x4 forwardTransform = ExtractRotation(perViewConfig.currentView) *
  625. Matrix4x4.Translate(-perViewConfig.currentView.GetColumn(3)) *
  626. Matrix4x4.Translate(perViewConfig.lastView.GetColumn(3)) *
  627. ExtractRotation(perViewConfig.lastView).transpose;
  628. Vector4 forIJKL = forwardTransform.GetRow(0);
  629. Vector4 forMNOP = forwardTransform.GetRow(1);
  630. Vector4 forQRST = forwardTransform.GetRow(2);
  631. Vector4 prjPrvABEF;
  632. prjPrvABEF.x = perViewConfig.lastLastProj[0, 0];
  633. // NOTE: Unity flips the Y axis inside the projection matrix. STP requires a non-flipped Y axis, so we undo the flip here with abs
  634. prjPrvABEF.y = Mathf.Abs(perViewConfig.lastLastProj[1, 1]);
  635. prjPrvABEF.z = perViewConfig.lastLastProj[0, 2];
  636. prjPrvABEF.w = perViewConfig.lastLastProj[1, 2];
  637. Vector4 prjPrvCDGH;
  638. prjPrvCDGH.x = perViewConfig.lastLastProj[2, 2];
  639. prjPrvCDGH.y = perViewConfig.lastLastProj[2, 3];
  640. prjPrvCDGH.z = perViewConfig.lastLastProj[3, 2];
  641. prjPrvCDGH.w = perViewConfig.lastLastProj[3, 3];
  642. Matrix4x4 backwardTransform = ExtractRotation(perViewConfig.lastLastView) *
  643. Matrix4x4.Translate(-perViewConfig.lastLastView.GetColumn(3)) *
  644. Matrix4x4.Translate(perViewConfig.lastView.GetColumn(3)) *
  645. ExtractRotation(perViewConfig.lastView).transpose;
  646. Vector4 bckIJKL = backwardTransform.GetRow(0);
  647. Vector4 bckMNOP = backwardTransform.GetRow(1);
  648. Vector4 bckQRST = backwardTransform.GetRow(2);
  649. unsafe
  650. {
  651. // Forwards
  652. // k0123
  653. constants._StpSetupPerViewConstants[baseViewDataOffset + 0] = prjPriCDGH.z / prjPriABEF.x;
  654. constants._StpSetupPerViewConstants[baseViewDataOffset + 1] = prjPriCDGH.w / prjPriABEF.x;
  655. constants._StpSetupPerViewConstants[baseViewDataOffset + 2] = prjPriABEF.z / prjPriABEF.x;
  656. constants._StpSetupPerViewConstants[baseViewDataOffset + 3] = prjPriCDGH.z / prjPriABEF.y;
  657. // k4567
  658. constants._StpSetupPerViewConstants[baseViewDataOffset + 4] = prjPriCDGH.w / prjPriABEF.y;
  659. constants._StpSetupPerViewConstants[baseViewDataOffset + 5] = prjPriABEF.w / prjPriABEF.y;
  660. constants._StpSetupPerViewConstants[baseViewDataOffset + 6] = forIJKL.x * prjCurABEF.x + forQRST.x * prjCurABEF.z;
  661. constants._StpSetupPerViewConstants[baseViewDataOffset + 7] = forIJKL.y * prjCurABEF.x + forQRST.y * prjCurABEF.z;
  662. // k89AB
  663. constants._StpSetupPerViewConstants[baseViewDataOffset + 8] = forIJKL.z * prjCurABEF.x + forQRST.z * prjCurABEF.z;
  664. constants._StpSetupPerViewConstants[baseViewDataOffset + 9] = forIJKL.w * prjCurABEF.x + forQRST.w * prjCurABEF.z;
  665. constants._StpSetupPerViewConstants[baseViewDataOffset + 10] = forMNOP.x * prjCurABEF.y + forQRST.x * prjCurABEF.w;
  666. constants._StpSetupPerViewConstants[baseViewDataOffset + 11] = forMNOP.y * prjCurABEF.y + forQRST.y * prjCurABEF.w;
  667. // kCDEF
  668. constants._StpSetupPerViewConstants[baseViewDataOffset + 12] = forMNOP.z * prjCurABEF.y + forQRST.z * prjCurABEF.w;
  669. constants._StpSetupPerViewConstants[baseViewDataOffset + 13] = forMNOP.w * prjCurABEF.y + forQRST.w * prjCurABEF.w;
  670. constants._StpSetupPerViewConstants[baseViewDataOffset + 14] = forQRST.x * prjCurCDGH.z;
  671. constants._StpSetupPerViewConstants[baseViewDataOffset + 15] = forQRST.y * prjCurCDGH.z;
  672. // kGHIJ
  673. constants._StpSetupPerViewConstants[baseViewDataOffset + 16] = forQRST.z * prjCurCDGH.z;
  674. constants._StpSetupPerViewConstants[baseViewDataOffset + 17] = forQRST.w * prjCurCDGH.z + prjCurCDGH.w;
  675. // Backwards
  676. constants._StpSetupPerViewConstants[baseViewDataOffset + 18] = bckIJKL.x * prjPrvABEF.x + bckQRST.x * prjPrvABEF.z;
  677. constants._StpSetupPerViewConstants[baseViewDataOffset + 19] = bckIJKL.y * prjPrvABEF.x + bckQRST.y * prjPrvABEF.z;
  678. // kKLMN
  679. constants._StpSetupPerViewConstants[baseViewDataOffset + 20] = bckIJKL.z * prjPrvABEF.x + bckQRST.z * prjPrvABEF.z;
  680. constants._StpSetupPerViewConstants[baseViewDataOffset + 21] = bckIJKL.w * prjPrvABEF.x + bckQRST.w * prjPrvABEF.z;
  681. constants._StpSetupPerViewConstants[baseViewDataOffset + 22] = bckMNOP.x * prjPrvABEF.y + bckQRST.x * prjPrvABEF.w;
  682. constants._StpSetupPerViewConstants[baseViewDataOffset + 23] = bckMNOP.y * prjPrvABEF.y + bckQRST.y * prjPrvABEF.w;
  683. // kOPQR
  684. constants._StpSetupPerViewConstants[baseViewDataOffset + 24] = bckMNOP.z * prjPrvABEF.y + bckQRST.z * prjPrvABEF.w;
  685. constants._StpSetupPerViewConstants[baseViewDataOffset + 25] = bckMNOP.w * prjPrvABEF.y + bckQRST.w * prjPrvABEF.w;
  686. constants._StpSetupPerViewConstants[baseViewDataOffset + 26] = bckQRST.x * prjPrvCDGH.z;
  687. constants._StpSetupPerViewConstants[baseViewDataOffset + 27] = bckQRST.y * prjPrvCDGH.z;
  688. // kST
  689. constants._StpSetupPerViewConstants[baseViewDataOffset + 28] = bckQRST.z * prjPrvCDGH.z;
  690. constants._StpSetupPerViewConstants[baseViewDataOffset + 29] = bckQRST.w * prjPrvCDGH.z + prjPrvCDGH.w;
  691. // Unused
  692. constants._StpSetupPerViewConstants[baseViewDataOffset + 30] = 0.0f;
  693. constants._StpSetupPerViewConstants[baseViewDataOffset + 31] = 0.0f;
  694. }
  695. }
  696. //------------------------------------------------------------------------------------------------------------------------------
  697. //
  698. // Dilation
  699. //
  700. // StpF2 kRcpR := 4/size of current input image in pixels.
  701. constants._StpDilConstants0.x = 4.0f / config.currentImageSize.x;
  702. constants._StpDilConstants0.y = 4.0f / config.currentImageSize.y;
  703. // StpU2 kR := size/4 of the current input image in pixels.
  704. // Used for pass merging (DIL and SAA), since convergence is 1/16 area of input, must check position.
  705. constants._StpDilConstants0.z = BitConverter.Int32BitsToSingle(config.currentImageSize.x >> 2);
  706. constants._StpDilConstants0.w = BitConverter.Int32BitsToSingle(config.currentImageSize.y >> 2);
  707. //
  708. // TAA
  709. //
  710. //------------------------------------------------------------------------------------------------------------------------------
  711. // Conversion from integer pix position to center pix float pixel position in image for current input.
  712. // xy := multiply term (M) --- Scale by 1/imgF to get to {0 to 1}.
  713. // zw := addition term (A) --- Add 0.5*M to get to center of pixel, then subtract jitC to undo jitter.
  714. // StpF2 kCRcpF.
  715. constants._StpTaaConstants0.x = (((float)config.currentImageSize.x) / config.outputImageSize.x);
  716. constants._StpTaaConstants0.y = (((float)config.currentImageSize.y) / config.outputImageSize.y);
  717. // StpF2 kHalfCRcpFUnjitC.
  718. constants._StpTaaConstants0.z = (0.5f * config.currentImageSize.x / config.outputImageSize.x - jitC.x);
  719. constants._StpTaaConstants0.w = (0.5f * config.currentImageSize.y / config.outputImageSize.y - jitC.y);
  720. //------------------------------------------------------------------------------------------------------------------------------
  721. // StpF2 kRcpC := 1/size of current input image in pixels.
  722. constants._StpTaaConstants1.x = (1.0f / config.currentImageSize.x);
  723. constants._StpTaaConstants1.y = (1.0f / config.currentImageSize.y);
  724. //------------------------------------------------------------------------------------------------------------------------------
  725. // StpF2 kRcpF := 1/size of feedback image (aka output) in pixels.
  726. constants._StpTaaConstants1.z = (1.0f / config.outputImageSize.x);
  727. constants._StpTaaConstants1.w = (1.0f / config.outputImageSize.y);
  728. //------------------------------------------------------------------------------------------------------------------------------
  729. // StpF2 kHalfRcpF := 0.5/size of feedback image (aka output) in pixels.
  730. constants._StpTaaConstants2.x = (0.5f / config.outputImageSize.x);
  731. constants._StpTaaConstants2.y = (0.5f / config.outputImageSize.y);
  732. //------------------------------------------------------------------------------------------------------------------------------
  733. // Conversion from a {0 to 1} position in current input to feedback.
  734. // StpH3 kJitCRcpC0 := jitC / image image size in pixels + {-0.5/size, +0.5/size} of current input image in pixels.
  735. constants._StpTaaConstants2.z = jitC.x / config.currentImageSize.x - 0.5f / config.currentImageSize.x;
  736. constants._StpTaaConstants2.w = jitC.y / config.currentImageSize.y + 0.5f / config.currentImageSize.y;
  737. //------------------------------------------------------------------------------------------------------------------------------
  738. // StpF2 kHalfRcpC := 0.5/size of current input image in pixels.
  739. constants._StpTaaConstants3.x = 0.5f / config.currentImageSize.x;
  740. constants._StpTaaConstants3.y = 0.5f / config.currentImageSize.y;
  741. //------------------------------------------------------------------------------------------------------------------------------
  742. // StpF2 kF := size of feedback image in pixels.
  743. constants._StpTaaConstants3.z = config.outputImageSize.x;
  744. constants._StpTaaConstants3.w = config.outputImageSize.y;
  745. }
  746. /// <summary>
  747. /// Shader resource ids used to communicate with the STP shader implementation
  748. /// </summary>
  749. static class ShaderResources
  750. {
  751. public static readonly int _StpConstantBufferData = Shader.PropertyToID("StpConstantBufferData");
  752. public static readonly int _StpBlueNoiseIn = Shader.PropertyToID("_StpBlueNoiseIn");
  753. public static readonly int _StpDebugOut = Shader.PropertyToID("_StpDebugOut");
  754. public static readonly int _StpInputColor = Shader.PropertyToID("_StpInputColor");
  755. public static readonly int _StpInputDepth = Shader.PropertyToID("_StpInputDepth");
  756. public static readonly int _StpInputMotion = Shader.PropertyToID("_StpInputMotion");
  757. public static readonly int _StpInputStencil = Shader.PropertyToID("_StpInputStencil");
  758. public static readonly int _StpIntermediateColor = Shader.PropertyToID("_StpIntermediateColor");
  759. public static readonly int _StpIntermediateConvergence = Shader.PropertyToID("_StpIntermediateConvergence");
  760. public static readonly int _StpIntermediateWeights = Shader.PropertyToID("_StpIntermediateWeights");
  761. public static readonly int _StpPriorLuma = Shader.PropertyToID("_StpPriorLuma");
  762. public static readonly int _StpLuma = Shader.PropertyToID("_StpLuma");
  763. public static readonly int _StpPriorDepthMotion = Shader.PropertyToID("_StpPriorDepthMotion");
  764. public static readonly int _StpDepthMotion = Shader.PropertyToID("_StpDepthMotion");
  765. public static readonly int _StpPriorFeedback = Shader.PropertyToID("_StpPriorFeedback");
  766. public static readonly int _StpFeedback = Shader.PropertyToID("_StpFeedback");
  767. public static readonly int _StpPriorConvergence = Shader.PropertyToID("_StpPriorConvergence");
  768. public static readonly int _StpConvergence = Shader.PropertyToID("_StpConvergence");
  769. public static readonly int _StpOutput = Shader.PropertyToID("_StpOutput");
  770. }
  771. /// <summary>
  772. /// Shader keyword strings used to configure the STP shader implementation
  773. /// </summary>
  774. static class ShaderKeywords
  775. {
  776. public static readonly string EnableDebugMode = "ENABLE_DEBUG_MODE";
  777. public static readonly string EnableLargeKernel = "ENABLE_LARGE_KERNEL";
  778. public static readonly string EnableStencilResponsive = "ENABLE_STENCIL_RESPONSIVE";
  779. public static readonly string DisableTexture2DXArray = "DISABLE_TEXTURE2D_X_ARRAY";
  780. }
  781. /// <summary>
  782. /// Contains the compute shaders used during STP's passes
  783. /// </summary>
  784. [Serializable]
  785. [SupportedOnRenderPipeline]
  786. [Categorization.CategoryInfo(Name = "R: STP", Order = 1000)]
  787. [Categorization.ElementInfo(Order = 0), HideInInspector]
  788. class RuntimeResources : IRenderPipelineResources
  789. {
  790. public int version => 0;
  791. bool IRenderPipelineGraphicsSettings.isAvailableInPlayerBuild => true;
  792. [SerializeField, ResourcePath("Runtime/STP/StpSetup.compute")]
  793. private ComputeShader m_setupCS;
  794. public ComputeShader setupCS
  795. {
  796. get => m_setupCS;
  797. set => this.SetValueAndNotify(ref m_setupCS, value);
  798. }
  799. [SerializeField, ResourcePath("Runtime/STP/StpPreTaa.compute")]
  800. private ComputeShader m_preTaaCS;
  801. public ComputeShader preTaaCS
  802. {
  803. get => m_preTaaCS;
  804. set => this.SetValueAndNotify(ref m_preTaaCS, value);
  805. }
  806. [SerializeField, ResourcePath("Runtime/STP/StpTaa.compute")]
  807. private ComputeShader m_taaCS;
  808. public ComputeShader taaCS
  809. {
  810. get => m_taaCS;
  811. set => this.SetValueAndNotify(ref m_taaCS, value);
  812. }
  813. }
  814. /// <summary>
  815. /// Profiling identifiers associated with STP's passes
  816. /// </summary>
  817. enum ProfileId
  818. {
  819. StpSetup,
  820. StpPreTaa,
  821. StpTaa
  822. }
  823. /// <summary>
  824. /// Integer value used to identify when STP is running on a Qualcomm GPU
  825. /// </summary>
  826. static readonly int kQualcommVendorId = 0x5143;
  827. /// <summary>
  828. /// Information required for STP's setup pass
  829. /// </summary>
  830. class SetupData
  831. {
  832. public ComputeShader cs;
  833. public int kernelIndex;
  834. public int viewCount;
  835. public Vector2Int dispatchSize;
  836. public StpConstantBufferData constantBufferData;
  837. // Common
  838. public TextureHandle noiseTexture;
  839. public TextureHandle debugView;
  840. // Inputs
  841. public TextureHandle inputColor;
  842. public TextureHandle inputDepth;
  843. public TextureHandle inputMotion;
  844. public TextureHandle inputStencil;
  845. // Intermediates
  846. public TextureHandle intermediateColor;
  847. public TextureHandle intermediateConvergence;
  848. // History
  849. public TextureHandle priorDepthMotion;
  850. public TextureHandle depthMotion;
  851. public TextureHandle priorLuma;
  852. public TextureHandle luma;
  853. public TextureHandle priorFeedback;
  854. public TextureHandle priorConvergence;
  855. }
  856. /// <summary>
  857. /// Information required for STP's Pre-TAA pass
  858. /// </summary>
  859. class PreTaaData
  860. {
  861. public ComputeShader cs;
  862. public int kernelIndex;
  863. public int viewCount;
  864. public Vector2Int dispatchSize;
  865. // Common
  866. public TextureHandle noiseTexture;
  867. public TextureHandle debugView;
  868. // Inputs
  869. public TextureHandle intermediateConvergence;
  870. // Intermediates
  871. public TextureHandle intermediateWeights;
  872. // History
  873. public TextureHandle luma;
  874. public TextureHandle convergence;
  875. }
  876. /// <summary>
  877. /// Information required for STP's TAA pass
  878. /// </summary>
  879. class TaaData
  880. {
  881. public ComputeShader cs;
  882. public int kernelIndex;
  883. public int viewCount;
  884. public Vector2Int dispatchSize;
  885. // Common
  886. public TextureHandle noiseTexture;
  887. public TextureHandle debugView;
  888. // Inputs
  889. public TextureHandle intermediateColor;
  890. public TextureHandle intermediateWeights;
  891. // History
  892. public TextureHandle priorFeedback;
  893. public TextureHandle depthMotion;
  894. public TextureHandle convergence;
  895. // Outputs
  896. public TextureHandle feedback;
  897. public TextureHandle output;
  898. }
  899. // Internal helper function used to streamline usage of the render graph API
  900. static TextureHandle UseTexture(IBaseRenderGraphBuilder builder, TextureHandle texture, AccessFlags flags = AccessFlags.Read)
  901. {
  902. builder.UseTexture(texture, flags);
  903. return texture;
  904. }
  905. /// <summary>
  906. /// Executes the STP technique using the provided configuration in the target render graph
  907. /// </summary>
  908. /// <param name="renderGraph">render graph to execute STP within</param>
  909. /// <param name="config">configuration parameters for STP</param>
  910. /// <returns>Texture handle that contains the upscaled color output</returns>
  911. public static TextureHandle Execute(RenderGraph renderGraph, ref Config config)
  912. {
  913. var runtimeResources = GraphicsSettings.GetRenderPipelineSettings<RuntimeResources>();
  914. // Temporarily wrap the noise texture in an RTHandle so it can be imported into render graph
  915. var noiseTexture = config.noiseTexture;
  916. RTHandleStaticHelpers.SetRTHandleStaticWrapper(noiseTexture);
  917. var noiseTextureRtHandle = RTHandleStaticHelpers.s_RTHandleWrapper;
  918. RenderTargetInfo noiseTextureInfo;
  919. noiseTextureInfo.width = noiseTexture.width;
  920. noiseTextureInfo.height = noiseTexture.height;
  921. noiseTextureInfo.volumeDepth = 1;
  922. noiseTextureInfo.msaaSamples = 1;
  923. noiseTextureInfo.format = noiseTexture.graphicsFormat;
  924. noiseTextureInfo.bindMS = false;
  925. TextureHandle noiseTextureHandle = renderGraph.ImportTexture(noiseTextureRtHandle, noiseTextureInfo);
  926. var priorDepthMotion = config.historyContext.GetPreviousHistoryTexture(HistoryTextureType.DepthMotion, config.frameIndex);
  927. var priorLuma = config.historyContext.GetPreviousHistoryTexture(HistoryTextureType.Luma, config.frameIndex);
  928. var priorConvergence = config.historyContext.GetPreviousHistoryTexture(HistoryTextureType.Convergence, config.frameIndex);
  929. var priorFeedback = config.historyContext.GetPreviousHistoryTexture(HistoryTextureType.Feedback, config.frameIndex);
  930. var depthMotion = config.historyContext.GetCurrentHistoryTexture(HistoryTextureType.DepthMotion, config.frameIndex);
  931. var luma = config.historyContext.GetCurrentHistoryTexture(HistoryTextureType.Luma, config.frameIndex);
  932. var convergence = config.historyContext.GetCurrentHistoryTexture(HistoryTextureType.Convergence, config.frameIndex);
  933. var feedback = config.historyContext.GetCurrentHistoryTexture(HistoryTextureType.Feedback, config.frameIndex);
  934. // Resize the current render-size history textures if hardware dynamic scaling is enabled
  935. if (config.enableHwDrs)
  936. {
  937. depthMotion.rt.ApplyDynamicScale();
  938. luma.rt.ApplyDynamicScale();
  939. convergence.rt.ApplyDynamicScale();
  940. }
  941. Vector2Int intermediateSize = config.enableHwDrs ? config.outputImageSize : config.currentImageSize;
  942. // Enable the large 128 wide kernel whenever STP runs on Qualcomm GPUs.
  943. // These GPUs require larger compute work groups in order to reach maximum FP16 ALU efficiency
  944. bool enableLargeKernel = SystemInfo.graphicsDeviceVendorID == kQualcommVendorId;
  945. Vector2Int kernelSize = new Vector2Int(8, enableLargeKernel ? 16 : 8);
  946. SetupData setupData;
  947. using (var builder = renderGraph.AddComputePass<SetupData>("STP Setup", out var passData, ProfilingSampler.Get(ProfileId.StpSetup)))
  948. {
  949. passData.cs = runtimeResources.setupCS;
  950. passData.cs.shaderKeywords = null;
  951. if (enableLargeKernel)
  952. passData.cs.EnableKeyword(ShaderKeywords.EnableLargeKernel);
  953. if (!config.enableTexArray)
  954. passData.cs.EnableKeyword(ShaderKeywords.DisableTexture2DXArray);
  955. // Populate the constant buffer data structure in the render graph pass data
  956. // This data will be uploaded to the GPU when the node executes later in the frame
  957. PopulateConstantData(ref config, ref passData.constantBufferData);
  958. passData.noiseTexture = UseTexture(builder, noiseTextureHandle);
  959. if (config.debugView.IsValid())
  960. {
  961. passData.cs.EnableKeyword(ShaderKeywords.EnableDebugMode);
  962. passData.debugView = UseTexture(builder, config.debugView, AccessFlags.WriteAll);
  963. }
  964. passData.kernelIndex = passData.cs.FindKernel("StpSetup");
  965. passData.viewCount = config.numActiveViews;
  966. passData.dispatchSize = new Vector2Int(
  967. CoreUtils.DivRoundUp(config.currentImageSize.x, kernelSize.x),
  968. CoreUtils.DivRoundUp(config.currentImageSize.y, kernelSize.y)
  969. );
  970. passData.inputColor = UseTexture(builder, config.inputColor);
  971. passData.inputDepth = UseTexture(builder, config.inputDepth);
  972. passData.inputMotion = UseTexture(builder, config.inputMotion);
  973. if (config.inputStencil.IsValid())
  974. {
  975. passData.cs.EnableKeyword(ShaderKeywords.EnableStencilResponsive);
  976. passData.inputStencil = UseTexture(builder, config.inputStencil);
  977. }
  978. passData.intermediateColor = UseTexture(builder, renderGraph.CreateTexture(new TextureDesc(intermediateSize.x, intermediateSize.y, config.enableHwDrs, config.enableTexArray)
  979. {
  980. name = "STP Intermediate Color",
  981. colorFormat = GraphicsFormat.A2B10G10R10_UNormPack32,
  982. enableRandomWrite = true
  983. }), AccessFlags.WriteAll);
  984. Vector2Int convergenceSize = CalculateConvergenceTextureSize(intermediateSize);
  985. passData.intermediateConvergence = UseTexture(builder, renderGraph.CreateTexture(new TextureDesc(convergenceSize.x, convergenceSize.y, config.enableHwDrs, config.enableTexArray)
  986. {
  987. name = "STP Intermediate Convergence",
  988. colorFormat = GraphicsFormat.R8_UNorm,
  989. enableRandomWrite = true
  990. }), AccessFlags.WriteAll);
  991. passData.priorDepthMotion = UseTexture(builder, renderGraph.ImportTexture(priorDepthMotion));
  992. passData.depthMotion = UseTexture(builder, renderGraph.ImportTexture(depthMotion), AccessFlags.WriteAll);
  993. passData.priorLuma = UseTexture(builder, renderGraph.ImportTexture(priorLuma));
  994. passData.luma = UseTexture(builder, renderGraph.ImportTexture(luma), AccessFlags.WriteAll);
  995. passData.priorFeedback = UseTexture(builder, renderGraph.ImportTexture(priorFeedback));
  996. passData.priorConvergence = UseTexture(builder, renderGraph.ImportTexture(priorConvergence));
  997. builder.SetRenderFunc(
  998. (SetupData data, ComputeGraphContext ctx) =>
  999. {
  1000. // Update the constant buffer data on the GPU
  1001. // TODO: Fix usage of m_WrappedCommandBuffer here once NRP support is added to ConstantBuffer.cs
  1002. ConstantBuffer.UpdateData(ctx.cmd.m_WrappedCommandBuffer, data.constantBufferData);
  1003. ConstantBuffer.Set<StpConstantBufferData>(data.cs, ShaderResources._StpConstantBufferData);
  1004. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpBlueNoiseIn, data.noiseTexture);
  1005. if (data.debugView.IsValid())
  1006. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpDebugOut, data.debugView);
  1007. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpInputColor, data.inputColor);
  1008. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpInputDepth, data.inputDepth);
  1009. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpInputMotion, data.inputMotion);
  1010. if (data.inputStencil.IsValid())
  1011. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpInputStencil, data.inputStencil, 0, RenderTextureSubElement.Stencil);
  1012. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateColor, data.intermediateColor);
  1013. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateConvergence, data.intermediateConvergence);
  1014. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpPriorDepthMotion, data.priorDepthMotion);
  1015. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpDepthMotion, data.depthMotion);
  1016. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpPriorLuma, data.priorLuma);
  1017. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpLuma, data.luma);
  1018. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpPriorFeedback, data.priorFeedback);
  1019. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpPriorConvergence, data.priorConvergence);
  1020. ctx.cmd.DispatchCompute(data.cs, data.kernelIndex, data.dispatchSize.x, data.dispatchSize.y, data.viewCount);
  1021. });
  1022. setupData = passData;
  1023. }
  1024. PreTaaData preTaaData;
  1025. using (var builder = renderGraph.AddComputePass<PreTaaData>("STP Pre-TAA", out var passData, ProfilingSampler.Get(ProfileId.StpPreTaa)))
  1026. {
  1027. passData.cs = runtimeResources.preTaaCS;
  1028. passData.cs.shaderKeywords = null;
  1029. if (enableLargeKernel)
  1030. passData.cs.EnableKeyword(ShaderKeywords.EnableLargeKernel);
  1031. if (!config.enableTexArray)
  1032. passData.cs.EnableKeyword(ShaderKeywords.DisableTexture2DXArray);
  1033. passData.noiseTexture = UseTexture(builder, noiseTextureHandle);
  1034. if (config.debugView.IsValid())
  1035. {
  1036. passData.cs.EnableKeyword(ShaderKeywords.EnableDebugMode);
  1037. passData.debugView = UseTexture(builder, config.debugView, AccessFlags.ReadWrite);
  1038. }
  1039. passData.kernelIndex = passData.cs.FindKernel("StpPreTaa");
  1040. passData.viewCount = config.numActiveViews;
  1041. passData.dispatchSize = new Vector2Int(
  1042. CoreUtils.DivRoundUp(config.currentImageSize.x, kernelSize.x),
  1043. CoreUtils.DivRoundUp(config.currentImageSize.y, kernelSize.y)
  1044. );
  1045. passData.intermediateConvergence = UseTexture(builder, setupData.intermediateConvergence);
  1046. passData.intermediateWeights = UseTexture(builder, renderGraph.CreateTexture(new TextureDesc(intermediateSize.x, intermediateSize.y, config.enableHwDrs, config.enableTexArray)
  1047. {
  1048. name = "STP Intermediate Weights",
  1049. colorFormat = GraphicsFormat.R8_UNorm,
  1050. enableRandomWrite = true
  1051. }), AccessFlags.WriteAll);
  1052. passData.luma = UseTexture(builder, renderGraph.ImportTexture(luma));
  1053. passData.convergence = UseTexture(builder, renderGraph.ImportTexture(convergence), AccessFlags.WriteAll);
  1054. builder.SetRenderFunc(
  1055. (PreTaaData data, ComputeGraphContext ctx) =>
  1056. {
  1057. ConstantBuffer.Set<StpConstantBufferData>(data.cs, ShaderResources._StpConstantBufferData);
  1058. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpBlueNoiseIn, data.noiseTexture);
  1059. if (data.debugView.IsValid())
  1060. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpDebugOut, data.debugView);
  1061. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateConvergence, data.intermediateConvergence);
  1062. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateWeights, data.intermediateWeights);
  1063. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpLuma, data.luma);
  1064. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpConvergence, data.convergence);
  1065. ctx.cmd.DispatchCompute(data.cs, data.kernelIndex, data.dispatchSize.x, data.dispatchSize.y, data.viewCount);
  1066. });
  1067. preTaaData = passData;
  1068. }
  1069. TaaData taaData;
  1070. using (var builder = renderGraph.AddComputePass<TaaData>("STP TAA", out var passData, ProfilingSampler.Get(ProfileId.StpTaa)))
  1071. {
  1072. passData.cs = runtimeResources.taaCS;
  1073. passData.cs.shaderKeywords = null;
  1074. if (enableLargeKernel)
  1075. passData.cs.EnableKeyword(ShaderKeywords.EnableLargeKernel);
  1076. if (!config.enableTexArray)
  1077. passData.cs.EnableKeyword(ShaderKeywords.DisableTexture2DXArray);
  1078. passData.noiseTexture = UseTexture(builder, noiseTextureHandle);
  1079. if (config.debugView.IsValid())
  1080. {
  1081. passData.cs.EnableKeyword(ShaderKeywords.EnableDebugMode);
  1082. passData.debugView = UseTexture(builder, config.debugView, AccessFlags.ReadWrite);
  1083. }
  1084. passData.kernelIndex = passData.cs.FindKernel("StpTaa");
  1085. passData.viewCount = config.numActiveViews;
  1086. passData.dispatchSize = new Vector2Int(
  1087. CoreUtils.DivRoundUp(config.outputImageSize.x, kernelSize.x),
  1088. CoreUtils.DivRoundUp(config.outputImageSize.y, kernelSize.y)
  1089. );
  1090. passData.intermediateColor = UseTexture(builder, setupData.intermediateColor);
  1091. passData.intermediateWeights = UseTexture(builder, preTaaData.intermediateWeights);
  1092. passData.priorFeedback = UseTexture(builder, renderGraph.ImportTexture(priorFeedback));
  1093. passData.depthMotion = UseTexture(builder, renderGraph.ImportTexture(depthMotion));
  1094. passData.convergence = UseTexture(builder, renderGraph.ImportTexture(convergence));
  1095. passData.feedback = UseTexture(builder, renderGraph.ImportTexture(feedback), AccessFlags.WriteAll);
  1096. passData.output = UseTexture(builder, config.destination, AccessFlags.WriteAll);
  1097. builder.SetRenderFunc(
  1098. (TaaData data, ComputeGraphContext ctx) =>
  1099. {
  1100. ConstantBuffer.Set<StpConstantBufferData>(data.cs, ShaderResources._StpConstantBufferData);
  1101. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpBlueNoiseIn, data.noiseTexture);
  1102. if (data.debugView.IsValid())
  1103. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpDebugOut, data.debugView);
  1104. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateColor, data.intermediateColor);
  1105. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpIntermediateWeights, data.intermediateWeights);
  1106. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpPriorFeedback, data.priorFeedback);
  1107. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpDepthMotion, data.depthMotion);
  1108. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpConvergence, data.convergence);
  1109. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpFeedback, data.feedback);
  1110. ctx.cmd.SetComputeTextureParam(data.cs, data.kernelIndex, ShaderResources._StpOutput, data.output);
  1111. ctx.cmd.DispatchCompute(data.cs, data.kernelIndex, data.dispatchSize.x, data.dispatchSize.y, data.viewCount);
  1112. });
  1113. taaData = passData;
  1114. }
  1115. return taaData.output;
  1116. }
  1117. }
  1118. }