InstEmitTexture.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using System;
  5. using System.Collections.Generic;
  6. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  7. namespace Ryujinx.Graphics.Shader.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void Tex(EmitterContext context)
  12. {
  13. Tex(context, TextureFlags.None);
  14. }
  15. public static void Tex_B(EmitterContext context)
  16. {
  17. Tex(context, TextureFlags.Bindless);
  18. }
  19. public static void Tld(EmitterContext context)
  20. {
  21. Tex(context, TextureFlags.IntCoords);
  22. }
  23. public static void Tld_B(EmitterContext context)
  24. {
  25. Tex(context, TextureFlags.IntCoords | TextureFlags.Bindless);
  26. }
  27. public static void Texs(EmitterContext context)
  28. {
  29. OpCodeTextureScalar op = (OpCodeTextureScalar)context.CurrOp;
  30. if (op.Rd0.IsRZ && op.Rd1.IsRZ)
  31. {
  32. return;
  33. }
  34. List<Operand> sourcesList = new List<Operand>();
  35. int raIndex = op.Ra.Index;
  36. int rbIndex = op.Rb.Index;
  37. Operand Ra()
  38. {
  39. if (raIndex > RegisterConsts.RegisterZeroIndex)
  40. {
  41. return Const(0);
  42. }
  43. return context.Copy(Register(raIndex++, RegisterType.Gpr));
  44. }
  45. Operand Rb()
  46. {
  47. if (rbIndex > RegisterConsts.RegisterZeroIndex)
  48. {
  49. return Const(0);
  50. }
  51. return context.Copy(Register(rbIndex++, RegisterType.Gpr));
  52. }
  53. void AddTextureOffset(int coordsCount, int stride, int size)
  54. {
  55. Operand packedOffs = Rb();
  56. for (int index = 0; index < coordsCount; index++)
  57. {
  58. sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * stride), Const(size)));
  59. }
  60. }
  61. TextureType type;
  62. TextureFlags flags;
  63. if (op is OpCodeTexs texsOp)
  64. {
  65. type = GetTextureType (texsOp.Type);
  66. flags = GetTextureFlags(texsOp.Type);
  67. if ((type & TextureType.Array) != 0)
  68. {
  69. Operand arrayIndex = Ra();
  70. sourcesList.Add(Ra());
  71. sourcesList.Add(Rb());
  72. sourcesList.Add(arrayIndex);
  73. if ((type & TextureType.Shadow) != 0)
  74. {
  75. sourcesList.Add(Rb());
  76. }
  77. if ((flags & TextureFlags.LodLevel) != 0)
  78. {
  79. sourcesList.Add(ConstF(0));
  80. }
  81. }
  82. else
  83. {
  84. switch (texsOp.Type)
  85. {
  86. case TextureScalarType.Texture1DLodZero:
  87. sourcesList.Add(Ra());
  88. break;
  89. case TextureScalarType.Texture2D:
  90. sourcesList.Add(Ra());
  91. sourcesList.Add(Rb());
  92. break;
  93. case TextureScalarType.Texture2DLodZero:
  94. sourcesList.Add(Ra());
  95. sourcesList.Add(Rb());
  96. sourcesList.Add(ConstF(0));
  97. break;
  98. case TextureScalarType.Texture2DLodLevel:
  99. case TextureScalarType.Texture2DDepthCompare:
  100. case TextureScalarType.Texture3D:
  101. case TextureScalarType.TextureCube:
  102. sourcesList.Add(Ra());
  103. sourcesList.Add(Ra());
  104. sourcesList.Add(Rb());
  105. break;
  106. case TextureScalarType.Texture2DLodZeroDepthCompare:
  107. case TextureScalarType.Texture3DLodZero:
  108. sourcesList.Add(Ra());
  109. sourcesList.Add(Ra());
  110. sourcesList.Add(Rb());
  111. sourcesList.Add(ConstF(0));
  112. break;
  113. case TextureScalarType.Texture2DLodLevelDepthCompare:
  114. case TextureScalarType.TextureCubeLodLevel:
  115. sourcesList.Add(Ra());
  116. sourcesList.Add(Ra());
  117. sourcesList.Add(Rb());
  118. sourcesList.Add(Rb());
  119. break;
  120. }
  121. }
  122. }
  123. else if (op is OpCodeTlds tldsOp)
  124. {
  125. type = GetTextureType (tldsOp.Type);
  126. flags = GetTextureFlags(tldsOp.Type) | TextureFlags.IntCoords;
  127. switch (tldsOp.Type)
  128. {
  129. case TexelLoadScalarType.Texture1DLodZero:
  130. sourcesList.Add(Ra());
  131. sourcesList.Add(Const(0));
  132. break;
  133. case TexelLoadScalarType.Texture1DLodLevel:
  134. sourcesList.Add(Ra());
  135. sourcesList.Add(Rb());
  136. break;
  137. case TexelLoadScalarType.Texture2DLodZero:
  138. sourcesList.Add(Ra());
  139. sourcesList.Add(Rb());
  140. sourcesList.Add(Const(0));
  141. break;
  142. case TexelLoadScalarType.Texture2DLodZeroOffset:
  143. sourcesList.Add(Ra());
  144. sourcesList.Add(Ra());
  145. sourcesList.Add(Const(0));
  146. break;
  147. case TexelLoadScalarType.Texture2DLodZeroMultisample:
  148. case TexelLoadScalarType.Texture2DLodLevel:
  149. case TexelLoadScalarType.Texture2DLodLevelOffset:
  150. sourcesList.Add(Ra());
  151. sourcesList.Add(Ra());
  152. sourcesList.Add(Rb());
  153. break;
  154. case TexelLoadScalarType.Texture3DLodZero:
  155. sourcesList.Add(Ra());
  156. sourcesList.Add(Ra());
  157. sourcesList.Add(Rb());
  158. sourcesList.Add(Const(0));
  159. break;
  160. case TexelLoadScalarType.Texture2DArrayLodZero:
  161. sourcesList.Add(Rb());
  162. sourcesList.Add(Rb());
  163. sourcesList.Add(Ra());
  164. sourcesList.Add(Const(0));
  165. break;
  166. }
  167. if ((flags & TextureFlags.Offset) != 0)
  168. {
  169. AddTextureOffset(type.GetCoordsCount(), 4, 4);
  170. }
  171. }
  172. else if (op is OpCodeTld4s tld4sOp)
  173. {
  174. if (!(tld4sOp.HasDepthCompare || tld4sOp.HasOffset))
  175. {
  176. sourcesList.Add(Ra());
  177. sourcesList.Add(Rb());
  178. }
  179. else
  180. {
  181. sourcesList.Add(Ra());
  182. sourcesList.Add(Ra());
  183. }
  184. type = TextureType.Texture2D;
  185. flags = TextureFlags.Gather;
  186. if (tld4sOp.HasDepthCompare)
  187. {
  188. sourcesList.Add(Rb());
  189. type |= TextureType.Shadow;
  190. }
  191. if (tld4sOp.HasOffset)
  192. {
  193. AddTextureOffset(type.GetCoordsCount(), 8, 6);
  194. flags |= TextureFlags.Offset;
  195. }
  196. sourcesList.Add(Const(tld4sOp.GatherCompIndex));
  197. }
  198. else
  199. {
  200. throw new InvalidOperationException($"Invalid opcode type \"{op.GetType().Name}\".");
  201. }
  202. Operand[] sources = sourcesList.ToArray();
  203. Operand[] rd0 = new Operand[2] { ConstF(0), ConstF(0) };
  204. Operand[] rd1 = new Operand[2] { ConstF(0), ConstF(0) };
  205. int destIncrement = 0;
  206. Operand GetDest()
  207. {
  208. int high = destIncrement >> 1;
  209. int low = destIncrement & 1;
  210. destIncrement++;
  211. if (op.IsFp16)
  212. {
  213. return high != 0
  214. ? (rd1[low] = Local())
  215. : (rd0[low] = Local());
  216. }
  217. else
  218. {
  219. int rdIndex = high != 0 ? op.Rd1.Index : op.Rd0.Index;
  220. if (rdIndex < RegisterConsts.RegisterZeroIndex)
  221. {
  222. rdIndex += low;
  223. }
  224. return Register(rdIndex, RegisterType.Gpr);
  225. }
  226. }
  227. int handle = op.Immediate;
  228. for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
  229. {
  230. if ((compMask & 1) != 0)
  231. {
  232. Operand dest = GetDest();
  233. TextureOperation operation = new TextureOperation(
  234. Instruction.TextureSample,
  235. type,
  236. flags,
  237. handle,
  238. compIndex,
  239. dest,
  240. sources);
  241. context.Add(operation);
  242. }
  243. }
  244. if (op.IsFp16)
  245. {
  246. context.Copy(Register(op.Rd0), context.PackHalf2x16(rd0[0], rd0[1]));
  247. context.Copy(Register(op.Rd1), context.PackHalf2x16(rd1[0], rd1[1]));
  248. }
  249. }
  250. public static void Tld4(EmitterContext context)
  251. {
  252. OpCodeTld4 op = (OpCodeTld4)context.CurrOp;
  253. if (op.Rd.IsRZ)
  254. {
  255. return;
  256. }
  257. int raIndex = op.Ra.Index;
  258. int rbIndex = op.Rb.Index;
  259. Operand Ra()
  260. {
  261. if (raIndex > RegisterConsts.RegisterZeroIndex)
  262. {
  263. return Const(0);
  264. }
  265. return context.Copy(Register(raIndex++, RegisterType.Gpr));
  266. }
  267. Operand Rb()
  268. {
  269. if (rbIndex > RegisterConsts.RegisterZeroIndex)
  270. {
  271. return Const(0);
  272. }
  273. return context.Copy(Register(rbIndex++, RegisterType.Gpr));
  274. }
  275. Operand arrayIndex = op.IsArray ? Ra() : null;
  276. List<Operand> sourcesList = new List<Operand>();
  277. TextureType type = GetTextureType(op.Dimensions);
  278. TextureFlags flags = TextureFlags.Gather;
  279. int coordsCount = type.GetCoordsCount();
  280. for (int index = 0; index < coordsCount; index++)
  281. {
  282. sourcesList.Add(Ra());
  283. }
  284. if (op.IsArray)
  285. {
  286. sourcesList.Add(arrayIndex);
  287. type |= TextureType.Array;
  288. }
  289. Operand[] packedOffs = new Operand[2];
  290. packedOffs[0] = op.Offset != TextureGatherOffset.None ? Rb() : null;
  291. packedOffs[1] = op.Offset == TextureGatherOffset.Offsets ? Rb() : null;
  292. if (op.HasDepthCompare)
  293. {
  294. sourcesList.Add(Rb());
  295. type |= TextureType.Shadow;
  296. }
  297. if (op.Offset != TextureGatherOffset.None)
  298. {
  299. int offsetTexelsCount = op.Offset == TextureGatherOffset.Offsets ? 4 : 1;
  300. for (int index = 0; index < coordsCount * offsetTexelsCount; index++)
  301. {
  302. Operand packed = packedOffs[(index >> 2) & 1];
  303. sourcesList.Add(context.BitfieldExtractS32(packed, Const((index & 3) * 8), Const(6)));
  304. }
  305. flags |= op.Offset == TextureGatherOffset.Offsets
  306. ? TextureFlags.Offsets
  307. : TextureFlags.Offset;
  308. }
  309. sourcesList.Add(Const(op.GatherCompIndex));
  310. Operand[] sources = sourcesList.ToArray();
  311. int rdIndex = op.Rd.Index;
  312. Operand GetDest()
  313. {
  314. if (rdIndex > RegisterConsts.RegisterZeroIndex)
  315. {
  316. return Const(0);
  317. }
  318. return Register(rdIndex++, RegisterType.Gpr);
  319. }
  320. int handle = op.Immediate;
  321. for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
  322. {
  323. if ((compMask & 1) != 0)
  324. {
  325. Operand dest = GetDest();
  326. TextureOperation operation = new TextureOperation(
  327. Instruction.TextureSample,
  328. type,
  329. flags,
  330. handle,
  331. compIndex,
  332. dest,
  333. sources);
  334. context.Add(operation);
  335. }
  336. }
  337. }
  338. public static void Txq(EmitterContext context)
  339. {
  340. Txq(context, bindless: false);
  341. }
  342. public static void Txq_B(EmitterContext context)
  343. {
  344. Txq(context, bindless: true);
  345. }
  346. private static void Txq(EmitterContext context, bool bindless)
  347. {
  348. OpCodeTex op = (OpCodeTex)context.CurrOp;
  349. if (op.Rd.IsRZ)
  350. {
  351. return;
  352. }
  353. TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6);
  354. //TODO: Validate and use property.
  355. Instruction inst = Instruction.TextureSize;
  356. TextureType type = TextureType.Texture2D;
  357. TextureFlags flags = bindless ? TextureFlags.Bindless : TextureFlags.None;
  358. int raIndex = op.Ra.Index;
  359. Operand Ra()
  360. {
  361. if (raIndex > RegisterConsts.RegisterZeroIndex)
  362. {
  363. return Const(0);
  364. }
  365. return context.Copy(Register(raIndex++, RegisterType.Gpr));
  366. }
  367. List<Operand> sourcesList = new List<Operand>();
  368. if (bindless)
  369. {
  370. sourcesList.Add(Ra());
  371. }
  372. sourcesList.Add(Ra());
  373. Operand[] sources = sourcesList.ToArray();
  374. int rdIndex = op.Rd.Index;
  375. Operand GetDest()
  376. {
  377. if (rdIndex > RegisterConsts.RegisterZeroIndex)
  378. {
  379. return Const(0);
  380. }
  381. return Register(rdIndex++, RegisterType.Gpr);
  382. }
  383. int handle = !bindless ? op.Immediate : 0;
  384. for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
  385. {
  386. if ((compMask & 1) != 0)
  387. {
  388. Operand dest = GetDest();
  389. TextureOperation operation = new TextureOperation(
  390. inst,
  391. type,
  392. flags,
  393. handle,
  394. compIndex,
  395. dest,
  396. sources);
  397. context.Add(operation);
  398. }
  399. }
  400. }
  401. private static void Tex(EmitterContext context, TextureFlags flags)
  402. {
  403. OpCodeTexture op = (OpCodeTexture)context.CurrOp;
  404. bool isBindless = (flags & TextureFlags.Bindless) != 0;
  405. bool intCoords = (flags & TextureFlags.IntCoords) != 0;
  406. if (op.Rd.IsRZ)
  407. {
  408. return;
  409. }
  410. int raIndex = op.Ra.Index;
  411. int rbIndex = op.Rb.Index;
  412. Operand Ra()
  413. {
  414. if (raIndex > RegisterConsts.RegisterZeroIndex)
  415. {
  416. return Const(0);
  417. }
  418. return context.Copy(Register(raIndex++, RegisterType.Gpr));
  419. }
  420. Operand Rb()
  421. {
  422. if (rbIndex > RegisterConsts.RegisterZeroIndex)
  423. {
  424. return Const(0);
  425. }
  426. return context.Copy(Register(rbIndex++, RegisterType.Gpr));
  427. }
  428. Operand arrayIndex = op.IsArray ? Ra() : null;
  429. List<Operand> sourcesList = new List<Operand>();
  430. if (isBindless)
  431. {
  432. sourcesList.Add(Rb());
  433. }
  434. TextureType type = GetTextureType(op.Dimensions);
  435. int coordsCount = type.GetCoordsCount();
  436. for (int index = 0; index < coordsCount; index++)
  437. {
  438. sourcesList.Add(Ra());
  439. }
  440. if (op.IsArray)
  441. {
  442. sourcesList.Add(arrayIndex);
  443. type |= TextureType.Array;
  444. }
  445. bool hasLod = op.LodMode > TextureLodMode.LodZero;
  446. Operand lodValue = hasLod ? Rb() : ConstF(0);
  447. Operand packedOffs = op.HasOffset ? Rb() : null;
  448. if (op.HasDepthCompare)
  449. {
  450. sourcesList.Add(Rb());
  451. type |= TextureType.Shadow;
  452. }
  453. if ((op.LodMode == TextureLodMode.LodZero ||
  454. op.LodMode == TextureLodMode.LodLevel ||
  455. op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample)
  456. {
  457. sourcesList.Add(lodValue);
  458. flags |= TextureFlags.LodLevel;
  459. }
  460. if (op.HasOffset)
  461. {
  462. for (int index = 0; index < coordsCount; index++)
  463. {
  464. sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4)));
  465. }
  466. flags |= TextureFlags.Offset;
  467. }
  468. if (op.LodMode == TextureLodMode.LodBias ||
  469. op.LodMode == TextureLodMode.LodBiasA)
  470. {
  471. sourcesList.Add(lodValue);
  472. flags |= TextureFlags.LodBias;
  473. }
  474. if (op.IsMultisample)
  475. {
  476. sourcesList.Add(Rb());
  477. type |= TextureType.Multisample;
  478. }
  479. Operand[] sources = sourcesList.ToArray();
  480. int rdIndex = op.Rd.Index;
  481. Operand GetDest()
  482. {
  483. if (rdIndex > RegisterConsts.RegisterZeroIndex)
  484. {
  485. return Const(0);
  486. }
  487. return Register(rdIndex++, RegisterType.Gpr);
  488. }
  489. int handle = !isBindless ? op.Immediate : 0;
  490. for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
  491. {
  492. if ((compMask & 1) != 0)
  493. {
  494. Operand dest = GetDest();
  495. TextureOperation operation = new TextureOperation(
  496. Instruction.TextureSample,
  497. type,
  498. flags,
  499. handle,
  500. compIndex,
  501. dest,
  502. sources);
  503. context.Add(operation);
  504. }
  505. }
  506. }
  507. private static TextureType GetTextureType(TextureDimensions dimensions)
  508. {
  509. switch (dimensions)
  510. {
  511. case TextureDimensions.Texture1D: return TextureType.Texture1D;
  512. case TextureDimensions.Texture2D: return TextureType.Texture2D;
  513. case TextureDimensions.Texture3D: return TextureType.Texture3D;
  514. case TextureDimensions.TextureCube: return TextureType.TextureCube;
  515. }
  516. throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".");
  517. }
  518. private static TextureType GetTextureType(TextureScalarType type)
  519. {
  520. switch (type)
  521. {
  522. case TextureScalarType.Texture1DLodZero:
  523. return TextureType.Texture1D;
  524. case TextureScalarType.Texture2D:
  525. case TextureScalarType.Texture2DLodZero:
  526. case TextureScalarType.Texture2DLodLevel:
  527. return TextureType.Texture2D;
  528. case TextureScalarType.Texture2DDepthCompare:
  529. case TextureScalarType.Texture2DLodLevelDepthCompare:
  530. case TextureScalarType.Texture2DLodZeroDepthCompare:
  531. return TextureType.Texture2D | TextureType.Shadow;
  532. case TextureScalarType.Texture2DArray:
  533. case TextureScalarType.Texture2DArrayLodZero:
  534. return TextureType.Texture2D | TextureType.Array;
  535. case TextureScalarType.Texture2DArrayLodZeroDepthCompare:
  536. return TextureType.Texture2D | TextureType.Array | TextureType.Shadow;
  537. case TextureScalarType.Texture3D:
  538. case TextureScalarType.Texture3DLodZero:
  539. return TextureType.Texture3D;
  540. case TextureScalarType.TextureCube:
  541. case TextureScalarType.TextureCubeLodLevel:
  542. return TextureType.TextureCube;
  543. }
  544. throw new ArgumentException($"Invalid texture type \"{type}\".");
  545. }
  546. private static TextureType GetTextureType(TexelLoadScalarType type)
  547. {
  548. switch (type)
  549. {
  550. case TexelLoadScalarType.Texture1DLodZero:
  551. case TexelLoadScalarType.Texture1DLodLevel:
  552. return TextureType.Texture1D;
  553. case TexelLoadScalarType.Texture2DLodZero:
  554. case TexelLoadScalarType.Texture2DLodZeroOffset:
  555. case TexelLoadScalarType.Texture2DLodLevel:
  556. case TexelLoadScalarType.Texture2DLodLevelOffset:
  557. return TextureType.Texture2D;
  558. case TexelLoadScalarType.Texture2DLodZeroMultisample:
  559. return TextureType.Texture2D | TextureType.Multisample;
  560. case TexelLoadScalarType.Texture3DLodZero:
  561. return TextureType.Texture3D;
  562. case TexelLoadScalarType.Texture2DArrayLodZero:
  563. return TextureType.Texture2D | TextureType.Array;
  564. }
  565. throw new ArgumentException($"Invalid texture type \"{type}\".");
  566. }
  567. private static TextureFlags GetTextureFlags(TextureScalarType type)
  568. {
  569. switch (type)
  570. {
  571. case TextureScalarType.Texture1DLodZero:
  572. case TextureScalarType.Texture2DLodZero:
  573. case TextureScalarType.Texture2DLodLevel:
  574. case TextureScalarType.Texture2DLodLevelDepthCompare:
  575. case TextureScalarType.Texture2DLodZeroDepthCompare:
  576. case TextureScalarType.Texture2DArrayLodZero:
  577. case TextureScalarType.Texture2DArrayLodZeroDepthCompare:
  578. case TextureScalarType.Texture3DLodZero:
  579. case TextureScalarType.TextureCubeLodLevel:
  580. return TextureFlags.LodLevel;
  581. case TextureScalarType.Texture2D:
  582. case TextureScalarType.Texture2DDepthCompare:
  583. case TextureScalarType.Texture2DArray:
  584. case TextureScalarType.Texture3D:
  585. case TextureScalarType.TextureCube:
  586. return TextureFlags.None;
  587. }
  588. throw new ArgumentException($"Invalid texture type \"{type}\".");
  589. }
  590. private static TextureFlags GetTextureFlags(TexelLoadScalarType type)
  591. {
  592. switch (type)
  593. {
  594. case TexelLoadScalarType.Texture1DLodZero:
  595. case TexelLoadScalarType.Texture1DLodLevel:
  596. case TexelLoadScalarType.Texture2DLodZero:
  597. case TexelLoadScalarType.Texture2DLodLevel:
  598. case TexelLoadScalarType.Texture2DLodZeroMultisample:
  599. case TexelLoadScalarType.Texture3DLodZero:
  600. case TexelLoadScalarType.Texture2DArrayLodZero:
  601. return TextureFlags.LodLevel;
  602. case TexelLoadScalarType.Texture2DLodZeroOffset:
  603. case TexelLoadScalarType.Texture2DLodLevelOffset:
  604. return TextureFlags.LodLevel | TextureFlags.Offset;
  605. }
  606. throw new ArgumentException($"Invalid texture type \"{type}\".");
  607. }
  608. }
  609. }