emit_glsl_image.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string_view>
  5. #include "shader_recompiler/backend/glsl/emit_context.h"
  6. #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
  7. #include "shader_recompiler/frontend/ir/modifiers.h"
  8. #include "shader_recompiler/frontend/ir/value.h"
  9. namespace Shader::Backend::GLSL {
  10. namespace {
  11. std::string Texture(EmitContext& ctx, const IR::TextureInstInfo& info,
  12. [[maybe_unused]] const IR::Value& index) {
  13. if (info.type == TextureType::Buffer) {
  14. throw NotImplementedException("TextureType::Buffer");
  15. } else {
  16. return fmt::format("tex{}", ctx.texture_bindings.at(info.descriptor_index));
  17. }
  18. }
  19. std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) {
  20. switch (info.type) {
  21. case TextureType::Color1D:
  22. return fmt::format("int({})", value);
  23. case TextureType::ColorArray1D:
  24. case TextureType::Color2D:
  25. case TextureType::ColorArray2D:
  26. return fmt::format("ivec2({})", value);
  27. case TextureType::Color3D:
  28. case TextureType::ColorCube:
  29. return fmt::format("ivec3({})", value);
  30. case TextureType::ColorArrayCube:
  31. return fmt::format("ivec4({})", value);
  32. default:
  33. throw NotImplementedException("Offset type {}", info.type.Value());
  34. }
  35. }
  36. std::string TexelFetchCastToInt(std::string_view value, const IR::TextureInstInfo& info) {
  37. switch (info.type) {
  38. case TextureType::Color1D:
  39. return fmt::format("int({})", value);
  40. case TextureType::ColorArray1D:
  41. case TextureType::Color2D:
  42. return fmt::format("ivec2({})", value);
  43. case TextureType::ColorArray2D:
  44. case TextureType::Color3D:
  45. case TextureType::ColorCube:
  46. return fmt::format("ivec3({})", value);
  47. case TextureType::ColorArrayCube:
  48. return fmt::format("ivec4({})", value);
  49. default:
  50. throw NotImplementedException("Offset type {}", info.type.Value());
  51. }
  52. }
  53. std::string ShadowSamplerVecCast(TextureType type) {
  54. switch (type) {
  55. case TextureType::ColorArray2D:
  56. case TextureType::ColorCube:
  57. case TextureType::ColorArrayCube:
  58. return "vec4";
  59. default:
  60. return "vec3";
  61. }
  62. }
  63. std::string PtpOffsets(const IR::Value& offset, const IR::Value& offset2) {
  64. const std::array values{offset.InstRecursive(), offset2.InstRecursive()};
  65. if (!values[0]->AreAllArgsImmediates() || !values[1]->AreAllArgsImmediates()) {
  66. // LOG_WARNING("Not all arguments in PTP are immediate, STUBBING");
  67. return "ivec2[](ivec2(0), ivec2(1), ivec2(2), ivec2(3))";
  68. }
  69. const IR::Opcode opcode{values[0]->GetOpcode()};
  70. if (opcode != values[1]->GetOpcode() || opcode != IR::Opcode::CompositeConstructU32x4) {
  71. throw LogicError("Invalid PTP arguments");
  72. }
  73. auto read{[&](unsigned int a, unsigned int b) { return values[a]->Arg(b).U32(); }};
  74. return fmt::format("ivec2[](ivec2({},{}),ivec2({},{}),ivec2({},{}),ivec2({},{}))", read(0, 0),
  75. read(0, 1), read(0, 2), read(0, 3), read(1, 0), read(1, 1), read(1, 2),
  76. read(1, 3));
  77. }
  78. IR::Inst* PrepareSparse(IR::Inst& inst) {
  79. const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
  80. if (sparse_inst) {
  81. sparse_inst->Invalidate();
  82. }
  83. return sparse_inst;
  84. }
  85. } // namespace
  86. void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  87. [[maybe_unused]] const IR::Value& index,
  88. [[maybe_unused]] std::string_view coords,
  89. [[maybe_unused]] std::string_view bias_lc,
  90. [[maybe_unused]] const IR::Value& offset) {
  91. const auto info{inst.Flags<IR::TextureInstInfo>()};
  92. if (info.has_lod_clamp) {
  93. throw NotImplementedException("EmitImageSampleImplicitLod Lod clamp samples");
  94. }
  95. const auto texture{Texture(ctx, info, index)};
  96. const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""};
  97. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  98. const auto sparse_inst{PrepareSparse(inst)};
  99. if (!sparse_inst) {
  100. if (!offset.IsEmpty()) {
  101. const auto offset_str{CastToIntVec(ctx.var_alloc.Consume(offset), info)};
  102. if (ctx.stage == Stage::Fragment) {
  103. ctx.Add("{}=textureOffset({},{},{}{});", texel, texture, coords, offset_str, bias);
  104. } else {
  105. ctx.Add("{}=textureLodOffset({},{},0.0,{});", texel, texture, coords, offset_str);
  106. }
  107. } else {
  108. if (ctx.stage == Stage::Fragment) {
  109. ctx.Add("{}=texture({},{}{});", texel, texture, coords, bias);
  110. } else {
  111. ctx.Add("{}=textureLod({},{},0.0);", texel, texture, coords);
  112. }
  113. }
  114. return;
  115. }
  116. // TODO: Query sparseTexels extension support
  117. if (!offset.IsEmpty()) {
  118. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureOffsetARB({},{},{},{}{}));",
  119. *sparse_inst, texture, coords, CastToIntVec(ctx.var_alloc.Consume(offset), info),
  120. texel, bias);
  121. } else {
  122. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureARB({},{},{}{}));", *sparse_inst,
  123. texture, coords, texel, bias);
  124. }
  125. }
  126. void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  127. [[maybe_unused]] const IR::Value& index,
  128. [[maybe_unused]] std::string_view coords,
  129. [[maybe_unused]] std::string_view lod_lc,
  130. [[maybe_unused]] const IR::Value& offset) {
  131. const auto info{inst.Flags<IR::TextureInstInfo>()};
  132. if (info.has_bias) {
  133. throw NotImplementedException("EmitImageSampleExplicitLod Bias texture samples");
  134. }
  135. if (info.has_lod_clamp) {
  136. throw NotImplementedException("EmitImageSampleExplicitLod Lod clamp samples");
  137. }
  138. const auto texture{Texture(ctx, info, index)};
  139. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  140. const auto sparse_inst{PrepareSparse(inst)};
  141. if (!sparse_inst) {
  142. if (!offset.IsEmpty()) {
  143. ctx.Add("{}=textureLodOffset({},{},{},{});", texel, texture, coords, lod_lc,
  144. CastToIntVec(ctx.var_alloc.Consume(offset), info));
  145. } else {
  146. ctx.Add("{}=textureLod({},{},{});", texel, texture, coords, lod_lc);
  147. }
  148. return;
  149. }
  150. // TODO: Query sparseTexels extension support
  151. if (!offset.IsEmpty()) {
  152. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTexelFetchOffsetARB({},{},int({}),{},{}));",
  153. *sparse_inst, texture, CastToIntVec(coords, info), lod_lc,
  154. CastToIntVec(ctx.var_alloc.Consume(offset), info), texel);
  155. } else {
  156. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureLodARB({},{},{},{}));", *sparse_inst,
  157. texture, coords, lod_lc, texel);
  158. }
  159. }
  160. void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx,
  161. [[maybe_unused]] IR::Inst& inst,
  162. [[maybe_unused]] const IR::Value& index,
  163. [[maybe_unused]] std::string_view coords,
  164. [[maybe_unused]] std::string_view dref,
  165. [[maybe_unused]] std::string_view bias_lc,
  166. [[maybe_unused]] const IR::Value& offset) {
  167. const auto info{inst.Flags<IR::TextureInstInfo>()};
  168. const auto sparse_inst{PrepareSparse(inst)};
  169. if (sparse_inst) {
  170. throw NotImplementedException("EmitImageSampleDrefImplicitLod Sparse texture samples");
  171. }
  172. if (info.has_bias) {
  173. throw NotImplementedException("EmitImageSampleDrefImplicitLod Bias texture samples");
  174. }
  175. if (info.has_lod_clamp) {
  176. throw NotImplementedException("EmitImageSampleDrefImplicitLod Lod clamp samples");
  177. }
  178. const auto texture{Texture(ctx, info, index)};
  179. const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""};
  180. const auto cast{ShadowSamplerVecCast(info.type)};
  181. if (!offset.IsEmpty()) {
  182. const auto offset_str{CastToIntVec(ctx.var_alloc.Consume(offset), info)};
  183. if (ctx.stage == Stage::Fragment) {
  184. ctx.AddF32("{}=textureOffset({},{}({},{}),{}{});", inst, texture, cast, coords, dref,
  185. offset_str, bias);
  186. } else {
  187. ctx.AddF32("{}=textureLodOffset({},{}({},{}),0.0,{});", inst, texture, cast, coords,
  188. dref, offset_str);
  189. }
  190. } else {
  191. if (ctx.stage == Stage::Fragment) {
  192. ctx.AddF32("{}=texture({},{}({},{}){});", inst, texture, cast, coords, dref, bias);
  193. } else {
  194. ctx.AddF32("{}=textureLod({},{}({},{}),0.0);", inst, texture, cast, coords, dref);
  195. }
  196. }
  197. }
  198. void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx,
  199. [[maybe_unused]] IR::Inst& inst,
  200. [[maybe_unused]] const IR::Value& index,
  201. [[maybe_unused]] std::string_view coords,
  202. [[maybe_unused]] std::string_view dref,
  203. [[maybe_unused]] std::string_view lod_lc,
  204. [[maybe_unused]] const IR::Value& offset) {
  205. const auto info{inst.Flags<IR::TextureInstInfo>()};
  206. const auto sparse_inst{PrepareSparse(inst)};
  207. if (sparse_inst) {
  208. throw NotImplementedException("EmitImageSampleDrefExplicitLod Sparse texture samples");
  209. }
  210. if (info.has_bias) {
  211. throw NotImplementedException("EmitImageSampleDrefExplicitLod Bias texture samples");
  212. }
  213. if (info.has_lod_clamp) {
  214. throw NotImplementedException("EmitImageSampleDrefExplicitLod Lod clamp samples");
  215. }
  216. const auto texture{Texture(ctx, info, index)};
  217. if (!offset.IsEmpty()) {
  218. const auto offset_str{CastToIntVec(ctx.var_alloc.Consume(offset), info)};
  219. if (info.type == TextureType::ColorArrayCube) {
  220. ctx.AddF32("{}=textureLodOffset({},{},{},{},{});", inst, texture, coords, dref, lod_lc,
  221. offset_str);
  222. } else {
  223. ctx.AddF32("{}=textureLodOffset({},vec3({},{}),{},{});", inst, texture, coords, dref,
  224. lod_lc, offset_str);
  225. }
  226. } else {
  227. if (info.type == TextureType::ColorArrayCube) {
  228. ctx.AddF32("{}=textureLod({},{},{},{});", inst, texture, coords, dref, lod_lc);
  229. } else {
  230. ctx.AddF32("{}=textureLod({},vec3({},{}),{});", inst, texture, coords, dref, lod_lc);
  231. }
  232. }
  233. }
  234. void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  235. [[maybe_unused]] const IR::Value& index,
  236. [[maybe_unused]] std::string_view coords,
  237. [[maybe_unused]] const IR::Value& offset,
  238. [[maybe_unused]] const IR::Value& offset2) {
  239. const auto info{inst.Flags<IR::TextureInstInfo>()};
  240. const auto texture{Texture(ctx, info, index)};
  241. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  242. const auto sparse_inst{PrepareSparse(inst)};
  243. if (!sparse_inst) {
  244. if (offset.IsEmpty()) {
  245. ctx.Add("{}=textureGather({},{},int({}));", texel, texture, coords,
  246. info.gather_component);
  247. return;
  248. }
  249. if (offset2.IsEmpty()) {
  250. ctx.Add("{}=textureGatherOffset({},{},{},int({}));", texel, texture, coords,
  251. CastToIntVec(ctx.var_alloc.Consume(offset), info), info.gather_component);
  252. return;
  253. }
  254. // PTP
  255. const auto offsets{PtpOffsets(offset, offset2)};
  256. ctx.Add("{}=textureGatherOffsets({},{},{},int({}));", texel, texture, coords, offsets,
  257. info.gather_component);
  258. return;
  259. }
  260. // TODO: Query sparseTexels extension support
  261. if (offset.IsEmpty()) {
  262. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherARB({},{},{},int({})));",
  263. *sparse_inst, texture, coords, texel, info.gather_component);
  264. }
  265. if (offset2.IsEmpty()) {
  266. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherOffsetARB({},{},{},{},int({})));",
  267. *sparse_inst, texture, CastToIntVec(coords, info),
  268. CastToIntVec(ctx.var_alloc.Consume(offset), info), texel, info.gather_component);
  269. }
  270. // PTP
  271. const auto offsets{PtpOffsets(offset, offset2)};
  272. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherOffsetARB({},{},{},{},int({})));",
  273. *sparse_inst, texture, CastToIntVec(coords, info), offsets, texel,
  274. info.gather_component);
  275. }
  276. void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  277. [[maybe_unused]] const IR::Value& index,
  278. [[maybe_unused]] std::string_view coords,
  279. [[maybe_unused]] const IR::Value& offset,
  280. [[maybe_unused]] const IR::Value& offset2,
  281. [[maybe_unused]] std::string_view dref) {
  282. const auto info{inst.Flags<IR::TextureInstInfo>()};
  283. const auto texture{Texture(ctx, info, index)};
  284. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  285. const auto sparse_inst{PrepareSparse(inst)};
  286. if (!sparse_inst) {
  287. if (offset.IsEmpty()) {
  288. ctx.Add("{}=textureGather({},{},{});", texel, texture, coords, dref);
  289. return;
  290. }
  291. if (offset2.IsEmpty()) {
  292. ctx.Add("{}=textureGatherOffset({},{},{},{});", texel, texture, coords, dref,
  293. CastToIntVec(ctx.var_alloc.Consume(offset), info));
  294. return;
  295. }
  296. // PTP
  297. const auto offsets{PtpOffsets(offset, offset2)};
  298. ctx.Add("{}=textureGatherOffsets({},{},{},{});", texel, texture, coords, dref, offsets);
  299. return;
  300. }
  301. // TODO: Query sparseTexels extension support
  302. if (offset.IsEmpty()) {
  303. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherARB({},{},{},{}));", *sparse_inst,
  304. texture, coords, dref, texel);
  305. }
  306. if (offset2.IsEmpty()) {
  307. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherOffsetARB({},{},{},,{},{}));",
  308. *sparse_inst, texture, CastToIntVec(coords, info), dref,
  309. CastToIntVec(ctx.var_alloc.Consume(offset), info), texel);
  310. }
  311. // PTP
  312. const auto offsets{PtpOffsets(offset, offset2)};
  313. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTextureGatherOffsetARB({},{},{},,{},{}));",
  314. *sparse_inst, texture, CastToIntVec(coords, info), dref, offsets, texel);
  315. }
  316. void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  317. [[maybe_unused]] const IR::Value& index,
  318. [[maybe_unused]] std::string_view coords,
  319. [[maybe_unused]] std::string_view offset, [[maybe_unused]] std::string_view lod,
  320. [[maybe_unused]] std::string_view ms) {
  321. const auto info{inst.Flags<IR::TextureInstInfo>()};
  322. if (info.has_bias) {
  323. throw NotImplementedException("EmitImageFetch Bias texture samples");
  324. }
  325. if (info.has_lod_clamp) {
  326. throw NotImplementedException("EmitImageFetch Lod clamp samples");
  327. }
  328. const auto texture{Texture(ctx, info, index)};
  329. const auto sparse_inst{PrepareSparse(inst)};
  330. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  331. if (!sparse_inst) {
  332. if (!offset.empty()) {
  333. ctx.Add("{}=texelFetchOffset({},{},int({}),{});", texel, texture,
  334. TexelFetchCastToInt(coords, info), lod, TexelFetchCastToInt(offset, info));
  335. } else {
  336. ctx.Add("{}=texelFetch({},{},int({}));", texel, texture,
  337. TexelFetchCastToInt(coords, info), lod);
  338. }
  339. return;
  340. }
  341. // TODO: Query sparseTexels extension support
  342. if (!offset.empty()) {
  343. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTexelFetchOffsetARB({},{},int({}),{},{}));",
  344. *sparse_inst, texture, CastToIntVec(coords, info), lod,
  345. CastToIntVec(offset, info), texel);
  346. } else {
  347. ctx.AddU1("{}=sparseTexelsResidentARB(sparseTexelFetchARB({},{},int({}),{}));",
  348. *sparse_inst, texture, CastToIntVec(coords, info), lod, texel);
  349. }
  350. }
  351. void EmitImageQueryDimensions([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  352. [[maybe_unused]] const IR::Value& index,
  353. [[maybe_unused]] std::string_view lod) {
  354. const auto info{inst.Flags<IR::TextureInstInfo>()};
  355. const auto texture{Texture(ctx, info, index)};
  356. switch (info.type) {
  357. case TextureType::Color1D:
  358. return ctx.AddU32x4(
  359. "{}=uvec4(uint(textureSize({},int({}))),0u,0u,uint(textureQueryLevels({})));", inst,
  360. texture, lod, texture);
  361. case TextureType::ColorArray1D:
  362. case TextureType::Color2D:
  363. case TextureType::ColorCube:
  364. return ctx.AddU32x4(
  365. "{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst,
  366. texture, lod, texture);
  367. case TextureType::ColorArray2D:
  368. case TextureType::Color3D:
  369. case TextureType::ColorArrayCube:
  370. return ctx.AddU32x4(
  371. "{}=uvec4(uvec3(textureSize({},int({}))),uint(textureQueryLevels({})));", inst, texture,
  372. lod, texture);
  373. case TextureType::Buffer:
  374. throw NotImplementedException("EmitImageQueryDimensions Texture buffers");
  375. }
  376. throw LogicError("Unspecified image type {}", info.type.Value());
  377. }
  378. void EmitImageQueryLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  379. [[maybe_unused]] const IR::Value& index,
  380. [[maybe_unused]] std::string_view coords) {
  381. const auto info{inst.Flags<IR::TextureInstInfo>()};
  382. const auto texture{Texture(ctx, info, index)};
  383. return ctx.AddF32x4("{}=vec4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords);
  384. }
  385. void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  386. [[maybe_unused]] const IR::Value& index,
  387. [[maybe_unused]] std::string_view coords,
  388. [[maybe_unused]] const IR::Value& derivatives,
  389. [[maybe_unused]] const IR::Value& offset,
  390. [[maybe_unused]] const IR::Value& lod_clamp) {
  391. const auto info{inst.Flags<IR::TextureInstInfo>()};
  392. if (info.has_lod_clamp) {
  393. throw NotImplementedException("EmitImageGradient Lod clamp samples");
  394. }
  395. const auto sparse_inst{PrepareSparse(inst)};
  396. if (sparse_inst) {
  397. throw NotImplementedException("EmitImageGradient Sparse");
  398. }
  399. if (!offset.IsEmpty()) {
  400. throw NotImplementedException("EmitImageGradient offset");
  401. }
  402. const auto texture{Texture(ctx, info, index)};
  403. const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
  404. const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp};
  405. const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)};
  406. if (multi_component) {
  407. ctx.Add("{}=textureGrad({},{},vec2({}.xz),vec2({}.yz));", texel, texture, coords,
  408. derivatives_vec, derivatives_vec);
  409. } else {
  410. ctx.Add("{}=textureGrad({},{},float({}.x),float({}.y));", texel, texture, coords,
  411. derivatives_vec, derivatives_vec);
  412. }
  413. }
  414. void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  415. [[maybe_unused]] const IR::Value& index,
  416. [[maybe_unused]] std::string_view coords) {
  417. NotImplemented();
  418. }
  419. void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  420. [[maybe_unused]] const IR::Value& index,
  421. [[maybe_unused]] std::string_view coords,
  422. [[maybe_unused]] std::string_view color) {
  423. NotImplemented();
  424. }
  425. void EmitBindlessImageSampleImplicitLod(EmitContext&) {
  426. NotImplemented();
  427. }
  428. void EmitBindlessImageSampleExplicitLod(EmitContext&) {
  429. NotImplemented();
  430. }
  431. void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) {
  432. NotImplemented();
  433. }
  434. void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) {
  435. NotImplemented();
  436. }
  437. void EmitBindlessImageGather(EmitContext&) {
  438. NotImplemented();
  439. }
  440. void EmitBindlessImageGatherDref(EmitContext&) {
  441. NotImplemented();
  442. }
  443. void EmitBindlessImageFetch(EmitContext&) {
  444. NotImplemented();
  445. }
  446. void EmitBindlessImageQueryDimensions(EmitContext&) {
  447. NotImplemented();
  448. }
  449. void EmitBindlessImageQueryLod(EmitContext&) {
  450. NotImplemented();
  451. }
  452. void EmitBindlessImageGradient(EmitContext&) {
  453. NotImplemented();
  454. }
  455. void EmitBindlessImageRead(EmitContext&) {
  456. NotImplemented();
  457. }
  458. void EmitBindlessImageWrite(EmitContext&) {
  459. NotImplemented();
  460. }
  461. void EmitBoundImageSampleImplicitLod(EmitContext&) {
  462. NotImplemented();
  463. }
  464. void EmitBoundImageSampleExplicitLod(EmitContext&) {
  465. NotImplemented();
  466. }
  467. void EmitBoundImageSampleDrefImplicitLod(EmitContext&) {
  468. NotImplemented();
  469. }
  470. void EmitBoundImageSampleDrefExplicitLod(EmitContext&) {
  471. NotImplemented();
  472. }
  473. void EmitBoundImageGather(EmitContext&) {
  474. NotImplemented();
  475. }
  476. void EmitBoundImageGatherDref(EmitContext&) {
  477. NotImplemented();
  478. }
  479. void EmitBoundImageFetch(EmitContext&) {
  480. NotImplemented();
  481. }
  482. void EmitBoundImageQueryDimensions(EmitContext&) {
  483. NotImplemented();
  484. }
  485. void EmitBoundImageQueryLod(EmitContext&) {
  486. NotImplemented();
  487. }
  488. void EmitBoundImageGradient(EmitContext&) {
  489. NotImplemented();
  490. }
  491. void EmitBoundImageRead(EmitContext&) {
  492. NotImplemented();
  493. }
  494. void EmitBoundImageWrite(EmitContext&) {
  495. NotImplemented();
  496. }
  497. } // namespace Shader::Backend::GLSL