Methods.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. using Ryujinx.Graphics.GAL;
  2. using Ryujinx.Graphics.GAL.Blend;
  3. using Ryujinx.Graphics.GAL.DepthStencil;
  4. using Ryujinx.Graphics.GAL.InputAssembler;
  5. using Ryujinx.Graphics.GAL.Texture;
  6. using Ryujinx.Graphics.Gpu.Image;
  7. using Ryujinx.Graphics.Gpu.Memory;
  8. using Ryujinx.Graphics.Gpu.State;
  9. using Ryujinx.Graphics.Shader;
  10. using System;
  11. using System.Runtime.InteropServices;
  12. namespace Ryujinx.Graphics.Gpu.Engine
  13. {
  14. partial class Methods
  15. {
  16. private GpuContext _context;
  17. private ShaderCache _shaderCache;
  18. private BufferManager _bufferManager;
  19. private TextureManager _textureManager;
  20. public TextureManager TextureManager => _textureManager;
  21. private bool _isAnyVbInstanced;
  22. private bool _vsUsesInstanceId;
  23. public Methods(GpuContext context)
  24. {
  25. _context = context;
  26. _shaderCache = new ShaderCache(_context);
  27. _bufferManager = new BufferManager(context);
  28. _textureManager = new TextureManager(context, _bufferManager);
  29. RegisterCallbacks();
  30. }
  31. private void RegisterCallbacks()
  32. {
  33. _context.State.RegisterCopyBufferCallback(CopyBuffer);
  34. _context.State.RegisterCopyTextureCallback(CopyTexture);
  35. _context.State.RegisterDrawEndCallback(DrawEnd);
  36. _context.State.RegisterDrawBeginCallback(DrawBegin);
  37. _context.State.RegisterSetIndexCountCallback(SetIndexCount);
  38. _context.State.RegisterClearCallback(Clear);
  39. _context.State.RegisterReportCallback(Report);
  40. _context.State.RegisterUniformBufferUpdateCallback(UniformBufferUpdate);
  41. _context.State.RegisterUniformBufferBind0Callback(UniformBufferBind0);
  42. _context.State.RegisterUniformBufferBind1Callback(UniformBufferBind1);
  43. _context.State.RegisterUniformBufferBind2Callback(UniformBufferBind2);
  44. _context.State.RegisterUniformBufferBind3Callback(UniformBufferBind3);
  45. _context.State.RegisterUniformBufferBind4Callback(UniformBufferBind4);
  46. _context.State.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures);
  47. _context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
  48. _context.State.RegisterCallback(MethodOffset.Inline2MemoryExecute, Execute);
  49. _context.State.RegisterCallback(MethodOffset.Inline2MemoryPushData, PushData);
  50. _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch);
  51. }
  52. public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
  53. private void UpdateState()
  54. {
  55. if ((_context.State.StateWriteFlags & StateWriteFlags.Any) == 0)
  56. {
  57. CommitBindings();
  58. return;
  59. }
  60. // Shaders must be the first one to be updated if modified, because
  61. // some of the other state depends on information from the currently
  62. // bound shaders.
  63. if ((_context.State.StateWriteFlags & StateWriteFlags.ShaderState) != 0)
  64. {
  65. UpdateShaderState();
  66. }
  67. if ((_context.State.StateWriteFlags & StateWriteFlags.RenderTargetGroup) != 0)
  68. {
  69. UpdateRenderTargetGroupState();
  70. }
  71. if ((_context.State.StateWriteFlags & StateWriteFlags.DepthTestState) != 0)
  72. {
  73. UpdateDepthTestState();
  74. }
  75. if ((_context.State.StateWriteFlags & StateWriteFlags.ViewportTransform) != 0)
  76. {
  77. UpdateViewportTransform();
  78. }
  79. if ((_context.State.StateWriteFlags & StateWriteFlags.DepthBiasState) != 0)
  80. {
  81. UpdateDepthBiasState();
  82. }
  83. if ((_context.State.StateWriteFlags & StateWriteFlags.StencilTestState) != 0)
  84. {
  85. UpdateStencilTestState();
  86. }
  87. if ((_context.State.StateWriteFlags & StateWriteFlags.SamplerPoolState) != 0)
  88. {
  89. UpdateSamplerPoolState();
  90. }
  91. if ((_context.State.StateWriteFlags & StateWriteFlags.TexturePoolState) != 0)
  92. {
  93. UpdateTexturePoolState();
  94. }
  95. if ((_context.State.StateWriteFlags & StateWriteFlags.InputAssemblerGroup) != 0)
  96. {
  97. UpdateInputAssemblerGroupState();
  98. }
  99. if ((_context.State.StateWriteFlags & StateWriteFlags.FaceState) != 0)
  100. {
  101. UpdateFaceState();
  102. }
  103. if ((_context.State.StateWriteFlags & StateWriteFlags.RtColorMask) != 0)
  104. {
  105. UpdateRtColorMask();
  106. }
  107. if ((_context.State.StateWriteFlags & StateWriteFlags.BlendState) != 0)
  108. {
  109. UpdateBlendState();
  110. }
  111. _context.State.StateWriteFlags &= ~StateWriteFlags.Any;
  112. CommitBindings();
  113. }
  114. private void CommitBindings()
  115. {
  116. _bufferManager.CommitBindings();
  117. _textureManager.CommitBindings();
  118. }
  119. public void InvalidateRange(ulong address, ulong size)
  120. {
  121. _bufferManager.InvalidateRange(address, size);
  122. _textureManager.InvalidateRange(address, size);
  123. }
  124. public void InvalidateTextureRange(ulong address, ulong size)
  125. {
  126. _textureManager.InvalidateRange(address, size);
  127. }
  128. private void UpdateRenderTargetGroupState()
  129. {
  130. TextureMsaaMode msaaMode = _context.State.GetRtMsaaMode();
  131. int samplesInX = msaaMode.SamplesInX();
  132. int samplesInY = msaaMode.SamplesInY();
  133. Image.Texture color3D = Get3DRenderTarget(samplesInX, samplesInY);
  134. if (color3D == null)
  135. {
  136. for (int index = 0; index < Constants.TotalRenderTargets; index++)
  137. {
  138. RtColorState colorState = _context.State.GetRtColorState(index);
  139. if (!IsRtEnabled(colorState))
  140. {
  141. _textureManager.SetRenderTargetColor(index, null);
  142. continue;
  143. }
  144. Image.Texture color = _textureManager.FindOrCreateTexture(
  145. colorState,
  146. samplesInX,
  147. samplesInY);
  148. _textureManager.SetRenderTargetColor(index, color);
  149. color.Modified = true;
  150. }
  151. }
  152. else
  153. {
  154. _textureManager.SetRenderTargetColor3D(color3D);
  155. color3D.Modified = true;
  156. }
  157. bool dsEnable = _context.State.Get<bool>(MethodOffset.RtDepthStencilEnable);
  158. Image.Texture depthStencil = null;
  159. if (dsEnable)
  160. {
  161. var dsState = _context.State.GetRtDepthStencilState();
  162. var dsSize = _context.State.GetRtDepthStencilSize();
  163. depthStencil = _textureManager.FindOrCreateTexture(
  164. dsState,
  165. dsSize,
  166. samplesInX,
  167. samplesInY);
  168. }
  169. _textureManager.SetRenderTargetDepthStencil(depthStencil);
  170. }
  171. private Image.Texture Get3DRenderTarget(int samplesInX, int samplesInY)
  172. {
  173. RtColorState colorState0 = _context.State.GetRtColorState(0);
  174. if (!IsRtEnabled(colorState0) || !colorState0.MemoryLayout.UnpackIsTarget3D() || colorState0.Depth != 1)
  175. {
  176. return null;
  177. }
  178. int slices = 1;
  179. int unused = 0;
  180. for (int index = 1; index < Constants.TotalRenderTargets; index++)
  181. {
  182. RtColorState colorState = _context.State.GetRtColorState(index);
  183. if (!IsRtEnabled(colorState))
  184. {
  185. unused++;
  186. continue;
  187. }
  188. if (colorState.MemoryLayout.UnpackIsTarget3D() && colorState.Depth == 1)
  189. {
  190. slices++;
  191. }
  192. }
  193. if (slices + unused == Constants.TotalRenderTargets)
  194. {
  195. colorState0.Depth = slices;
  196. return _textureManager.FindOrCreateTexture(colorState0, samplesInX, samplesInY);
  197. }
  198. return null;
  199. }
  200. private static bool IsRtEnabled(RtColorState colorState)
  201. {
  202. // Colors are disabled by writing 0 to the format.
  203. return colorState.Format != 0 && colorState.WidthOrStride != 0;
  204. }
  205. private void UpdateDepthTestState()
  206. {
  207. _context.Renderer.GraphicsPipeline.SetDepthTest(new DepthTestDescriptor(
  208. _context.State.GetDepthTestEnable().IsTrue(),
  209. _context.State.GetDepthWriteEnable().IsTrue(),
  210. _context.State.GetDepthTestFunc()));
  211. }
  212. private void UpdateViewportTransform()
  213. {
  214. Viewport[] viewports = new Viewport[Constants.TotalViewports];
  215. for (int index = 0; index < Constants.TotalViewports; index++)
  216. {
  217. var transform = _context.State.Get<ViewportTransform>(MethodOffset.ViewportTransform + index * 8);
  218. var extents = _context.State.Get<ViewportExtents> (MethodOffset.ViewportExtents + index * 4);
  219. float x = transform.TranslateX - MathF.Abs(transform.ScaleX);
  220. float y = transform.TranslateY - MathF.Abs(transform.ScaleY);
  221. float width = transform.ScaleX * 2;
  222. float height = transform.ScaleY * 2;
  223. RectangleF region = new RectangleF(x, y, width, height);
  224. viewports[index] = new Viewport(
  225. region,
  226. transform.UnpackSwizzleX(),
  227. transform.UnpackSwizzleY(),
  228. transform.UnpackSwizzleZ(),
  229. transform.UnpackSwizzleW(),
  230. extents.DepthNear,
  231. extents.DepthFar);
  232. }
  233. _context.Renderer.GraphicsPipeline.SetViewports(0, viewports);
  234. }
  235. private void UpdateDepthBiasState()
  236. {
  237. var polygonOffset = _context.State.Get<DepthBiasState>(MethodOffset.DepthBiasState);
  238. float factor = _context.State.Get<float>(MethodOffset.DepthBiasFactor);
  239. float units = _context.State.Get<float>(MethodOffset.DepthBiasUnits);
  240. float clamp = _context.State.Get<float>(MethodOffset.DepthBiasClamp);
  241. PolygonModeMask enables = 0;
  242. enables = (polygonOffset.PointEnable.IsTrue() ? PolygonModeMask.Point : 0);
  243. enables |= (polygonOffset.LineEnable.IsTrue() ? PolygonModeMask.Line : 0);
  244. enables |= (polygonOffset.FillEnable.IsTrue() ? PolygonModeMask.Fill : 0);
  245. _context.Renderer.GraphicsPipeline.SetDepthBias(enables, factor, units, clamp);
  246. }
  247. private void UpdateStencilTestState()
  248. {
  249. StencilBackMasks backMasks = _context.State.GetStencilBackMasks();
  250. StencilTestState test = _context.State.GetStencilTestState();
  251. StencilBackTestState backTest = _context.State.GetStencilBackTestState();
  252. CompareOp backFunc;
  253. StencilOp backSFail;
  254. StencilOp backDpPass;
  255. StencilOp backDpFail;
  256. int backFuncRef;
  257. int backFuncMask;
  258. int backMask;
  259. if (backTest.TwoSided.IsTrue())
  260. {
  261. backFunc = backTest.BackFunc;
  262. backSFail = backTest.BackSFail;
  263. backDpPass = backTest.BackDpPass;
  264. backDpFail = backTest.BackDpFail;
  265. backFuncRef = backMasks.FuncRef;
  266. backFuncMask = backMasks.FuncMask;
  267. backMask = backMasks.Mask;
  268. }
  269. else
  270. {
  271. backFunc = test.FrontFunc;
  272. backSFail = test.FrontSFail;
  273. backDpPass = test.FrontDpPass;
  274. backDpFail = test.FrontDpFail;
  275. backFuncRef = test.FrontFuncRef;
  276. backFuncMask = test.FrontFuncMask;
  277. backMask = test.FrontMask;
  278. }
  279. _context.Renderer.GraphicsPipeline.SetStencilTest(new StencilTestDescriptor(
  280. test.Enable.IsTrue(),
  281. test.FrontFunc,
  282. test.FrontSFail,
  283. test.FrontDpPass,
  284. test.FrontDpFail,
  285. test.FrontFuncRef,
  286. test.FrontFuncMask,
  287. test.FrontMask,
  288. backFunc,
  289. backSFail,
  290. backDpPass,
  291. backDpFail,
  292. backFuncRef,
  293. backFuncMask,
  294. backMask));
  295. }
  296. private void UpdateSamplerPoolState()
  297. {
  298. PoolState samplerPool = _context.State.GetSamplerPoolState();
  299. _textureManager.SetSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId);
  300. }
  301. private void UpdateTexturePoolState()
  302. {
  303. PoolState texturePool = _context.State.GetTexturePoolState();
  304. _textureManager.SetTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
  305. _textureManager.SetTextureBufferIndex(_context.State.GetTextureBufferIndex());
  306. }
  307. private void UpdateInputAssemblerGroupState()
  308. {
  309. // Must be updated before the vertex buffer.
  310. if ((_context.State.StateWriteFlags & StateWriteFlags.VertexAttribState) != 0)
  311. {
  312. UpdateVertexAttribState();
  313. }
  314. if ((_context.State.StateWriteFlags & StateWriteFlags.PrimitiveRestartState) != 0)
  315. {
  316. UpdatePrimitiveRestartState();
  317. }
  318. if ((_context.State.StateWriteFlags & StateWriteFlags.IndexBufferState) != 0)
  319. {
  320. UpdateIndexBufferState();
  321. }
  322. if ((_context.State.StateWriteFlags & StateWriteFlags.VertexBufferState) != 0)
  323. {
  324. UpdateVertexBufferState();
  325. }
  326. }
  327. private void UpdateVertexAttribState()
  328. {
  329. VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16];
  330. for (int index = 0; index < 16; index++)
  331. {
  332. VertexAttribState vertexAttrib = _context.State.GetVertexAttribState(index);
  333. if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format))
  334. {
  335. // TODO: warning.
  336. format = Format.R32G32B32A32Float;
  337. }
  338. vertexAttribs[index] = new VertexAttribDescriptor(
  339. vertexAttrib.UnpackBufferIndex(),
  340. vertexAttrib.UnpackOffset(),
  341. format);
  342. }
  343. _context.Renderer.GraphicsPipeline.BindVertexAttribs(vertexAttribs);
  344. }
  345. private void UpdatePrimitiveRestartState()
  346. {
  347. PrimitiveRestartState primitiveRestart = _context.State.Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
  348. _context.Renderer.GraphicsPipeline.SetPrimitiveRestart(
  349. primitiveRestart.Enable,
  350. primitiveRestart.Index);
  351. }
  352. private void UpdateIndexBufferState()
  353. {
  354. IndexBufferState indexBuffer = _context.State.GetIndexBufferState();
  355. _firstIndex = indexBuffer.First;
  356. _indexCount = indexBuffer.Count;
  357. if (_indexCount == 0)
  358. {
  359. return;
  360. }
  361. ulong gpuVa = indexBuffer.Address.Pack();
  362. // Do not use the end address to calculate the size, because
  363. // the result may be much larger than the real size of the index buffer.
  364. ulong size = (ulong)(_firstIndex + _indexCount);
  365. switch (indexBuffer.Type)
  366. {
  367. case IndexType.UShort: size *= 2; break;
  368. case IndexType.UInt: size *= 4; break;
  369. }
  370. _bufferManager.SetIndexBuffer(gpuVa, size, indexBuffer.Type);
  371. // The index buffer affects the vertex buffer size calculation, we
  372. // need to ensure that they are updated.
  373. UpdateVertexBufferState();
  374. }
  375. private uint GetIndexBufferMaxIndex(ulong gpuVa, ulong size, IndexType type)
  376. {
  377. ulong address = _context.MemoryManager.Translate(gpuVa);
  378. Span<byte> data = _context.PhysicalMemory.Read(address, size);
  379. uint maxIndex = 0;
  380. switch (type)
  381. {
  382. case IndexType.UByte:
  383. {
  384. for (int index = 0; index < data.Length; index++)
  385. {
  386. if (maxIndex < data[index])
  387. {
  388. maxIndex = data[index];
  389. }
  390. }
  391. break;
  392. }
  393. case IndexType.UShort:
  394. {
  395. Span<ushort> indices = MemoryMarshal.Cast<byte, ushort>(data);
  396. for (int index = 0; index < indices.Length; index++)
  397. {
  398. if (maxIndex < indices[index])
  399. {
  400. maxIndex = indices[index];
  401. }
  402. }
  403. break;
  404. }
  405. case IndexType.UInt:
  406. {
  407. Span<uint> indices = MemoryMarshal.Cast<byte, uint>(data);
  408. for (int index = 0; index < indices.Length; index++)
  409. {
  410. if (maxIndex < indices[index])
  411. {
  412. maxIndex = indices[index];
  413. }
  414. }
  415. break;
  416. }
  417. }
  418. return maxIndex;
  419. }
  420. private void UpdateVertexBufferState()
  421. {
  422. _isAnyVbInstanced = false;
  423. for (int index = 0; index < 16; index++)
  424. {
  425. VertexBufferState vertexBuffer = _context.State.GetVertexBufferState(index);
  426. if (!vertexBuffer.UnpackEnable())
  427. {
  428. _bufferManager.SetVertexBuffer(index, 0, 0, 0, 0);
  429. continue;
  430. }
  431. GpuVa endAddress = _context.State.GetVertexBufferEndAddress(index);
  432. ulong address = vertexBuffer.Address.Pack();
  433. int stride = vertexBuffer.UnpackStride();
  434. bool instanced = _context.State.Get<bool>(MethodOffset.VertexBufferInstanced + index);
  435. int divisor = instanced ? vertexBuffer.Divisor : 0;
  436. _isAnyVbInstanced |= divisor != 0;
  437. ulong size;
  438. if (_drawIndexed || stride == 0 || instanced)
  439. {
  440. // This size may be (much) larger than the real vertex buffer size.
  441. // Avoid calculating it this way, unless we don't have any other option.
  442. size = endAddress.Pack() - address + 1;
  443. }
  444. else
  445. {
  446. // For non-indexed draws, we can guess the size from the vertex count
  447. // and stride.
  448. int firstInstance = _context.State.GetBaseInstance();
  449. VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState();
  450. size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride);
  451. }
  452. _bufferManager.SetVertexBuffer(index, address, size, stride, divisor);
  453. }
  454. }
  455. private void UpdateFaceState()
  456. {
  457. FaceState face = _context.State.GetFaceState();
  458. _context.Renderer.GraphicsPipeline.SetFaceCulling(face.CullEnable.IsTrue(), face.CullFace);
  459. _context.Renderer.GraphicsPipeline.SetFrontFace(face.FrontFace);
  460. }
  461. private void UpdateRtColorMask()
  462. {
  463. uint[] componentMasks = new uint[Constants.TotalRenderTargets];
  464. for (int index = 0; index < Constants.TotalRenderTargets; index++)
  465. {
  466. RtColorMask colorMask = _context.State.Get<RtColorMask>(MethodOffset.RtColorMask + index);
  467. uint componentMask = 0;
  468. componentMask = (colorMask.UnpackRed() ? 1u : 0u);
  469. componentMask |= (colorMask.UnpackGreen() ? 2u : 0u);
  470. componentMask |= (colorMask.UnpackBlue() ? 4u : 0u);
  471. componentMask |= (colorMask.UnpackAlpha() ? 8u : 0u);
  472. componentMasks[index] = componentMask;
  473. }
  474. _context.Renderer.GraphicsPipeline.SetRenderTargetColorMasks(componentMasks);
  475. }
  476. private void UpdateBlendState()
  477. {
  478. BlendState[] blends = new BlendState[8];
  479. for (int index = 0; index < 8; index++)
  480. {
  481. bool blendEnable = _context.State.GetBlendEnable(index).IsTrue();
  482. BlendState blend = _context.State.GetBlendState(index);
  483. BlendDescriptor descriptor = new BlendDescriptor(
  484. blendEnable,
  485. blend.ColorOp,
  486. blend.ColorSrcFactor,
  487. blend.ColorDstFactor,
  488. blend.AlphaOp,
  489. blend.AlphaSrcFactor,
  490. blend.AlphaDstFactor);
  491. _context.Renderer.GraphicsPipeline.BindBlendState(index, descriptor);
  492. }
  493. }
  494. private struct SbDescriptor
  495. {
  496. public uint AddressLow;
  497. public uint AddressHigh;
  498. public int Size;
  499. public int Padding;
  500. public ulong PackAddress()
  501. {
  502. return AddressLow | ((ulong)AddressHigh << 32);
  503. }
  504. }
  505. private void UpdateShaderState()
  506. {
  507. ShaderAddresses addresses = new ShaderAddresses();
  508. Span<ShaderAddresses> addressesSpan = MemoryMarshal.CreateSpan(ref addresses, 1);
  509. Span<ulong> addressesArray = MemoryMarshal.Cast<ShaderAddresses, ulong>(addressesSpan);
  510. ulong baseAddress = _context.State.GetShaderBaseAddress().Pack();
  511. for (int index = 0; index < 6; index++)
  512. {
  513. ShaderState shader = _context.State.GetShaderState(index);
  514. if (!shader.UnpackEnable() && index != 1)
  515. {
  516. continue;
  517. }
  518. addressesArray[index] = baseAddress + shader.Offset;
  519. }
  520. GraphicsShader gs = _shaderCache.GetGraphicsShader(addresses);
  521. _vsUsesInstanceId = gs.Shader[0].Info.UsesInstanceId;
  522. for (int stage = 0; stage < Constants.TotalShaderStages; stage++)
  523. {
  524. ShaderProgramInfo info = gs.Shader[stage]?.Info;
  525. if (info == null)
  526. {
  527. continue;
  528. }
  529. var textureBindings = new TextureBindingInfo[info.Textures.Count];
  530. for (int index = 0; index < info.Textures.Count; index++)
  531. {
  532. var descriptor = info.Textures[index];
  533. Target target = GetTarget(descriptor.Target);
  534. textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
  535. }
  536. _textureManager.BindTextures(stage, textureBindings);
  537. uint sbEnableMask = 0;
  538. uint ubEnableMask = 0;
  539. for (int index = 0; index < info.SBuffers.Count; index++)
  540. {
  541. BufferDescriptor sb = info.SBuffers[index];
  542. sbEnableMask |= 1u << sb.Slot;
  543. ulong sbDescAddress = _bufferManager.GetGraphicsUniformBufferAddress(stage, 0);
  544. int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10;
  545. sbDescAddress += (ulong)sbDescOffset;
  546. Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
  547. SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
  548. _bufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
  549. }
  550. for (int index = 0; index < info.CBuffers.Count; index++)
  551. {
  552. ubEnableMask |= 1u << info.CBuffers[index].Slot;
  553. }
  554. _bufferManager.SetGraphicsStorageBufferEnableMask(stage, sbEnableMask);
  555. _bufferManager.SetGraphicsUniformBufferEnableMask(stage, ubEnableMask);
  556. }
  557. _context.Renderer.GraphicsPipeline.BindProgram(gs.Interface);
  558. }
  559. private static Target GetTarget(Shader.TextureTarget target)
  560. {
  561. target &= ~Shader.TextureTarget.Shadow;
  562. switch (target)
  563. {
  564. case Shader.TextureTarget.Texture1D:
  565. return Target.Texture1D;
  566. case Shader.TextureTarget.Texture1D | Shader.TextureTarget.Array:
  567. return Target.Texture1DArray;
  568. case Shader.TextureTarget.Texture2D:
  569. return Target.Texture2D;
  570. case Shader.TextureTarget.Texture2D | Shader.TextureTarget.Array:
  571. return Target.Texture2DArray;
  572. case Shader.TextureTarget.Texture2D | Shader.TextureTarget.Multisample:
  573. return Target.Texture2DMultisample;
  574. case Shader.TextureTarget.Texture2D | Shader.TextureTarget.Multisample | Shader.TextureTarget.Array:
  575. return Target.Texture2DMultisampleArray;
  576. case Shader.TextureTarget.Texture3D:
  577. return Target.Texture3D;
  578. case Shader.TextureTarget.TextureCube:
  579. return Target.Cubemap;
  580. case Shader.TextureTarget.TextureCube | Shader.TextureTarget.Array:
  581. return Target.CubemapArray;
  582. }
  583. // TODO: Warning.
  584. return Target.Texture2D;
  585. }
  586. private void InvalidateTextures(int argument)
  587. {
  588. _textureManager.Flush();
  589. }
  590. }
  591. }