CapabilityVisitor.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. //===--- CapabilityVisitor.cpp - Capability Visitor --------------*- C++ -*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "CapabilityVisitor.h"
  10. #include "clang/SPIRV/SpirvBuilder.h"
  11. namespace clang {
  12. namespace spirv {
  13. void CapabilityVisitor::addExtension(Extension ext, llvm::StringRef target,
  14. SourceLocation loc) {
  15. featureManager.requestExtension(ext, target, loc);
  16. // Do not emit OpExtension if the given extension is natively supported in
  17. // the target environment.
  18. if (featureManager.isExtensionRequiredForTargetEnv(ext))
  19. spvBuilder.requireExtension(featureManager.getExtensionName(ext), loc);
  20. }
  21. void CapabilityVisitor::addCapability(spv::Capability cap, SourceLocation loc) {
  22. if (cap != spv::Capability::Max) {
  23. spvBuilder.requireCapability(cap, loc);
  24. }
  25. }
  26. void CapabilityVisitor::addCapabilityForType(const SpirvType *type,
  27. SourceLocation loc,
  28. spv::StorageClass sc) {
  29. // Defent against instructions that do not have a return type.
  30. if (!type)
  31. return;
  32. // Integer-related capabilities
  33. if (const auto *intType = dyn_cast<IntegerType>(type)) {
  34. switch (intType->getBitwidth()) {
  35. case 16: {
  36. // Usage of a 16-bit integer type.
  37. addCapability(spv::Capability::Int16);
  38. // Usage of a 16-bit integer type as stage I/O.
  39. if (sc == spv::StorageClass::Input || sc == spv::StorageClass::Output) {
  40. addExtension(Extension::KHR_16bit_storage, "16-bit stage IO variables",
  41. loc);
  42. addCapability(spv::Capability::StorageInputOutput16);
  43. }
  44. break;
  45. }
  46. case 64: {
  47. addCapability(spv::Capability::Int64);
  48. break;
  49. }
  50. default:
  51. break;
  52. }
  53. }
  54. // Float-related capabilities
  55. else if (const auto *floatType = dyn_cast<FloatType>(type)) {
  56. switch (floatType->getBitwidth()) {
  57. case 16: {
  58. // Usage of a 16-bit float type.
  59. addCapability(spv::Capability::Float16);
  60. // Usage of a 16-bit float type as stage I/O.
  61. if (sc == spv::StorageClass::Input || sc == spv::StorageClass::Output) {
  62. addExtension(Extension::KHR_16bit_storage, "16-bit stage IO variables",
  63. loc);
  64. addCapability(spv::Capability::StorageInputOutput16);
  65. }
  66. break;
  67. }
  68. case 64: {
  69. addCapability(spv::Capability::Float64);
  70. break;
  71. }
  72. default:
  73. break;
  74. }
  75. }
  76. // Vectors
  77. else if (const auto *vecType = dyn_cast<VectorType>(type)) {
  78. addCapabilityForType(vecType->getElementType(), loc, sc);
  79. }
  80. // Matrices
  81. else if (const auto *matType = dyn_cast<MatrixType>(type)) {
  82. addCapabilityForType(matType->getElementType(), loc, sc);
  83. }
  84. // Arrays
  85. else if (const auto *arrType = dyn_cast<ArrayType>(type)) {
  86. addCapabilityForType(arrType->getElementType(), loc, sc);
  87. }
  88. // Runtime array of resources requires additional capability.
  89. else if (const auto *raType = dyn_cast<RuntimeArrayType>(type)) {
  90. if (SpirvType::isResourceType(raType->getElementType())) {
  91. // the elements inside the runtime array are resources
  92. addExtension(Extension::EXT_descriptor_indexing,
  93. "runtime array of resources", loc);
  94. addCapability(spv::Capability::RuntimeDescriptorArrayEXT);
  95. }
  96. addCapabilityForType(raType->getElementType(), loc, sc);
  97. }
  98. // Image types
  99. else if (const auto *imageType = dyn_cast<ImageType>(type)) {
  100. switch (imageType->getDimension()) {
  101. case spv::Dim::Buffer: {
  102. addCapability(spv::Capability::SampledBuffer);
  103. if (imageType->withSampler() == ImageType::WithSampler::No) {
  104. addCapability(spv::Capability::ImageBuffer);
  105. }
  106. break;
  107. }
  108. case spv::Dim::Dim1D: {
  109. if (imageType->withSampler() == ImageType::WithSampler::No) {
  110. addCapability(spv::Capability::Image1D);
  111. } else {
  112. addCapability(spv::Capability::Sampled1D);
  113. }
  114. break;
  115. }
  116. case spv::Dim::SubpassData: {
  117. addCapability(spv::Capability::InputAttachment);
  118. break;
  119. }
  120. default:
  121. break;
  122. }
  123. switch (imageType->getImageFormat()) {
  124. case spv::ImageFormat::Rg32f:
  125. case spv::ImageFormat::Rg16f:
  126. case spv::ImageFormat::R11fG11fB10f:
  127. case spv::ImageFormat::R16f:
  128. case spv::ImageFormat::Rgba16:
  129. case spv::ImageFormat::Rgb10A2:
  130. case spv::ImageFormat::Rg16:
  131. case spv::ImageFormat::Rg8:
  132. case spv::ImageFormat::R16:
  133. case spv::ImageFormat::R8:
  134. case spv::ImageFormat::Rgba16Snorm:
  135. case spv::ImageFormat::Rg16Snorm:
  136. case spv::ImageFormat::Rg8Snorm:
  137. case spv::ImageFormat::R16Snorm:
  138. case spv::ImageFormat::R8Snorm:
  139. case spv::ImageFormat::Rg32i:
  140. case spv::ImageFormat::Rg16i:
  141. case spv::ImageFormat::Rg8i:
  142. case spv::ImageFormat::R16i:
  143. case spv::ImageFormat::R8i:
  144. case spv::ImageFormat::Rgb10a2ui:
  145. case spv::ImageFormat::Rg32ui:
  146. case spv::ImageFormat::Rg16ui:
  147. case spv::ImageFormat::Rg8ui:
  148. case spv::ImageFormat::R16ui:
  149. case spv::ImageFormat::R8ui:
  150. addCapability(spv::Capability::StorageImageExtendedFormats);
  151. break;
  152. default:
  153. // Only image formats requiring extended formats are relevant. The rest
  154. // just pass through.
  155. break;
  156. }
  157. if (imageType->isArrayedImage() && imageType->isMSImage())
  158. addCapability(spv::Capability::ImageMSArray);
  159. addCapabilityForType(imageType->getSampledType(), loc, sc);
  160. }
  161. // Sampled image type
  162. else if (const auto *sampledImageType = dyn_cast<SampledImageType>(type)) {
  163. addCapabilityForType(sampledImageType->getImageType(), loc, sc);
  164. }
  165. // Pointer type
  166. else if (const auto *ptrType = dyn_cast<SpirvPointerType>(type)) {
  167. addCapabilityForType(ptrType->getPointeeType(), loc, sc);
  168. }
  169. // Struct type
  170. else if (const auto *structType = dyn_cast<StructType>(type)) {
  171. if (SpirvType::isOrContainsType<NumericalType, 16>(structType)) {
  172. addExtension(Extension::KHR_16bit_storage, "16-bit types in resource",
  173. loc);
  174. if (sc == spv::StorageClass::PushConstant) {
  175. addCapability(spv::Capability::StoragePushConstant16);
  176. } else if (structType->getInterfaceType() ==
  177. StructInterfaceType::UniformBuffer) {
  178. addCapability(spv::Capability::StorageUniform16);
  179. } else if (structType->getInterfaceType() ==
  180. StructInterfaceType::StorageBuffer) {
  181. addCapability(spv::Capability::StorageUniformBufferBlock16);
  182. }
  183. }
  184. for (auto field : structType->getFields())
  185. addCapabilityForType(field.type, loc, sc);
  186. }
  187. }
  188. bool CapabilityVisitor::visit(SpirvDecoration *decor) {
  189. const auto loc = decor->getSourceLocation();
  190. switch (decor->getDecoration()) {
  191. case spv::Decoration::Sample: {
  192. addCapability(spv::Capability::SampleRateShading, loc);
  193. break;
  194. }
  195. case spv::Decoration::NonUniformEXT: {
  196. addExtension(Extension::EXT_descriptor_indexing, "NonUniformEXT", loc);
  197. addCapability(spv::Capability::ShaderNonUniformEXT);
  198. break;
  199. }
  200. case spv::Decoration::HlslSemanticGOOGLE:
  201. case spv::Decoration::HlslCounterBufferGOOGLE: {
  202. addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
  203. loc);
  204. break;
  205. }
  206. // Capabilities needed for built-ins
  207. case spv::Decoration::BuiltIn: {
  208. assert(decor->getParams().size() == 1);
  209. const auto builtin = static_cast<spv::BuiltIn>(decor->getParams()[0]);
  210. switch (builtin) {
  211. case spv::BuiltIn::SampleId:
  212. case spv::BuiltIn::SamplePosition: {
  213. addCapability(spv::Capability::SampleRateShading, loc);
  214. break;
  215. }
  216. case spv::BuiltIn::SubgroupSize:
  217. case spv::BuiltIn::NumSubgroups:
  218. case spv::BuiltIn::SubgroupId:
  219. case spv::BuiltIn::SubgroupLocalInvocationId: {
  220. addCapability(spv::Capability::GroupNonUniform, loc);
  221. break;
  222. }
  223. case spv::BuiltIn::BaseVertex: {
  224. addExtension(Extension::KHR_shader_draw_parameters, "BaseVertex Builtin",
  225. loc);
  226. addCapability(spv::Capability::DrawParameters);
  227. break;
  228. }
  229. case spv::BuiltIn::BaseInstance: {
  230. addExtension(Extension::KHR_shader_draw_parameters,
  231. "BaseInstance Builtin", loc);
  232. addCapability(spv::Capability::DrawParameters);
  233. break;
  234. }
  235. case spv::BuiltIn::DrawIndex: {
  236. addExtension(Extension::KHR_shader_draw_parameters, "DrawIndex Builtin",
  237. loc);
  238. addCapability(spv::Capability::DrawParameters);
  239. break;
  240. }
  241. case spv::BuiltIn::DeviceIndex: {
  242. addExtension(Extension::KHR_device_group, "DeviceIndex Builtin", loc);
  243. addCapability(spv::Capability::DeviceGroup);
  244. break;
  245. }
  246. case spv::BuiltIn::FragStencilRefEXT: {
  247. addExtension(Extension::EXT_shader_stencil_export, "SV_StencilRef", loc);
  248. addCapability(spv::Capability::StencilExportEXT);
  249. break;
  250. }
  251. case spv::BuiltIn::ViewIndex: {
  252. addExtension(Extension::KHR_multiview, "SV_ViewID", loc);
  253. addCapability(spv::Capability::MultiView);
  254. break;
  255. }
  256. case spv::BuiltIn::FullyCoveredEXT: {
  257. addExtension(Extension::EXT_fragment_fully_covered, "SV_InnerCoverage",
  258. loc);
  259. addCapability(spv::Capability::FragmentFullyCoveredEXT);
  260. break;
  261. }
  262. case spv::BuiltIn::PrimitiveId: {
  263. // PrimitiveID can be used as PSIn
  264. if (shaderModel == spv::ExecutionModel::Fragment)
  265. addCapability(spv::Capability::Geometry);
  266. break;
  267. }
  268. case spv::BuiltIn::Layer: {
  269. if (shaderModel == spv::ExecutionModel::Vertex ||
  270. shaderModel == spv::ExecutionModel::TessellationControl ||
  271. shaderModel == spv::ExecutionModel::TessellationEvaluation) {
  272. addExtension(Extension::EXT_shader_viewport_index_layer,
  273. "SV_RenderTargetArrayIndex", loc);
  274. addCapability(spv::Capability::ShaderViewportIndexLayerEXT);
  275. } else if (shaderModel == spv::ExecutionModel::Fragment) {
  276. // SV_RenderTargetArrayIndex can be used as PSIn.
  277. addCapability(spv::Capability::Geometry);
  278. }
  279. break;
  280. }
  281. case spv::BuiltIn::ViewportIndex: {
  282. if (shaderModel == spv::ExecutionModel::Vertex ||
  283. shaderModel == spv::ExecutionModel::TessellationControl ||
  284. shaderModel == spv::ExecutionModel::TessellationEvaluation) {
  285. addExtension(Extension::EXT_shader_viewport_index_layer,
  286. "SV_ViewPortArrayIndex", loc);
  287. addCapability(spv::Capability::ShaderViewportIndexLayerEXT);
  288. } else if (shaderModel == spv::ExecutionModel::Fragment ||
  289. shaderModel == spv::ExecutionModel::Geometry) {
  290. // SV_ViewportArrayIndex can be used as PSIn.
  291. addCapability(spv::Capability::MultiViewport);
  292. }
  293. break;
  294. }
  295. case spv::BuiltIn::ClipDistance: {
  296. addCapability(spv::Capability::ClipDistance);
  297. break;
  298. }
  299. case spv::BuiltIn::CullDistance: {
  300. addCapability(spv::Capability::CullDistance);
  301. break;
  302. }
  303. case spv::BuiltIn::BaryCoordNoPerspAMD:
  304. case spv::BuiltIn::BaryCoordNoPerspCentroidAMD:
  305. case spv::BuiltIn::BaryCoordNoPerspSampleAMD:
  306. case spv::BuiltIn::BaryCoordSmoothAMD:
  307. case spv::BuiltIn::BaryCoordSmoothCentroidAMD:
  308. case spv::BuiltIn::BaryCoordSmoothSampleAMD:
  309. case spv::BuiltIn::BaryCoordPullModelAMD: {
  310. addExtension(Extension::AMD_shader_explicit_vertex_parameter,
  311. "SV_Barycentrics", loc);
  312. break;
  313. }
  314. case spv::BuiltIn::FragSizeEXT: {
  315. addExtension(Extension::EXT_fragment_invocation_density, "SV_ShadingRate",
  316. loc);
  317. addCapability(spv::Capability::FragmentDensityEXT);
  318. break;
  319. }
  320. default:
  321. break;
  322. }
  323. break;
  324. }
  325. default:
  326. break;
  327. }
  328. return true;
  329. }
  330. spv::Capability
  331. CapabilityVisitor::getNonUniformCapability(const SpirvType *type) {
  332. if (!type)
  333. return spv::Capability::Max;
  334. if (const auto *arrayType = dyn_cast<ArrayType>(type)) {
  335. return getNonUniformCapability(arrayType->getElementType());
  336. }
  337. if (SpirvType::isTexture(type) || SpirvType::isSampler(type)) {
  338. return spv::Capability::SampledImageArrayNonUniformIndexingEXT;
  339. }
  340. if (SpirvType::isRWTexture(type)) {
  341. return spv::Capability::StorageImageArrayNonUniformIndexingEXT;
  342. }
  343. if (SpirvType::isBuffer(type)) {
  344. return spv::Capability::UniformTexelBufferArrayNonUniformIndexingEXT;
  345. }
  346. if (SpirvType::isRWBuffer(type)) {
  347. return spv::Capability::StorageTexelBufferArrayNonUniformIndexingEXT;
  348. }
  349. if (SpirvType::isSubpassInput(type) || SpirvType::isSubpassInputMS(type)) {
  350. return spv::Capability::InputAttachmentArrayNonUniformIndexingEXT;
  351. }
  352. return spv::Capability::Max;
  353. }
  354. bool CapabilityVisitor::visit(SpirvImageQuery *instr) {
  355. addCapabilityForType(instr->getResultType(), instr->getSourceLocation(),
  356. instr->getStorageClass());
  357. addCapability(spv::Capability::ImageQuery);
  358. return true;
  359. }
  360. bool CapabilityVisitor::visit(SpirvImageSparseTexelsResident *instr) {
  361. addCapabilityForType(instr->getResultType(), instr->getSourceLocation(),
  362. instr->getStorageClass());
  363. addCapability(spv::Capability::ImageGatherExtended);
  364. addCapability(spv::Capability::SparseResidency);
  365. return true;
  366. }
  367. bool CapabilityVisitor::visit(SpirvImageOp *instr) {
  368. addCapabilityForType(instr->getResultType(), instr->getSourceLocation(),
  369. instr->getStorageClass());
  370. if (instr->hasOffset() || instr->hasConstOffsets())
  371. addCapability(spv::Capability::ImageGatherExtended);
  372. if (instr->hasMinLod())
  373. addCapability(spv::Capability::MinLod);
  374. if (instr->isSparse())
  375. addCapability(spv::Capability::SparseResidency);
  376. return true;
  377. }
  378. bool CapabilityVisitor::visitInstruction(SpirvInstruction *instr) {
  379. const SpirvType *resultType = instr->getResultType();
  380. const auto opcode = instr->getopcode();
  381. const auto loc = instr->getSourceLocation();
  382. // Add result-type-specific capabilities
  383. addCapabilityForType(resultType, loc, instr->getStorageClass());
  384. // Add NonUniform capabilities if necessary
  385. if (instr->isNonUniform()) {
  386. addExtension(Extension::EXT_descriptor_indexing, "NonUniformEXT", loc);
  387. addCapability(spv::Capability::ShaderNonUniformEXT);
  388. addCapability(getNonUniformCapability(resultType));
  389. }
  390. // Add opcode-specific capabilities
  391. switch (opcode) {
  392. case spv::Op::OpDPdxCoarse:
  393. case spv::Op::OpDPdyCoarse:
  394. case spv::Op::OpFwidthCoarse:
  395. case spv::Op::OpDPdxFine:
  396. case spv::Op::OpDPdyFine:
  397. case spv::Op::OpFwidthFine:
  398. addCapability(spv::Capability::DerivativeControl);
  399. break;
  400. case spv::Op::OpGroupNonUniformElect:
  401. addCapability(spv::Capability::GroupNonUniform);
  402. break;
  403. case spv::Op::OpGroupNonUniformAny:
  404. case spv::Op::OpGroupNonUniformAll:
  405. case spv::Op::OpGroupNonUniformAllEqual:
  406. addCapability(spv::Capability::GroupNonUniformVote);
  407. break;
  408. case spv::Op::OpGroupNonUniformBallot:
  409. case spv::Op::OpGroupNonUniformInverseBallot:
  410. case spv::Op::OpGroupNonUniformBallotBitExtract:
  411. case spv::Op::OpGroupNonUniformBallotBitCount:
  412. case spv::Op::OpGroupNonUniformBallotFindLSB:
  413. case spv::Op::OpGroupNonUniformBallotFindMSB:
  414. case spv::Op::OpGroupNonUniformBroadcast:
  415. case spv::Op::OpGroupNonUniformBroadcastFirst:
  416. addCapability(spv::Capability::GroupNonUniformBallot);
  417. break;
  418. case spv::Op::OpGroupNonUniformIAdd:
  419. case spv::Op::OpGroupNonUniformFAdd:
  420. case spv::Op::OpGroupNonUniformIMul:
  421. case spv::Op::OpGroupNonUniformFMul:
  422. case spv::Op::OpGroupNonUniformSMax:
  423. case spv::Op::OpGroupNonUniformUMax:
  424. case spv::Op::OpGroupNonUniformFMax:
  425. case spv::Op::OpGroupNonUniformSMin:
  426. case spv::Op::OpGroupNonUniformUMin:
  427. case spv::Op::OpGroupNonUniformFMin:
  428. case spv::Op::OpGroupNonUniformBitwiseAnd:
  429. case spv::Op::OpGroupNonUniformBitwiseOr:
  430. case spv::Op::OpGroupNonUniformBitwiseXor:
  431. case spv::Op::OpGroupNonUniformLogicalAnd:
  432. case spv::Op::OpGroupNonUniformLogicalOr:
  433. case spv::Op::OpGroupNonUniformLogicalXor:
  434. addCapability(spv::Capability::GroupNonUniformArithmetic);
  435. break;
  436. case spv::Op::OpGroupNonUniformQuadBroadcast:
  437. case spv::Op::OpGroupNonUniformQuadSwap:
  438. addCapability(spv::Capability::GroupNonUniformQuad);
  439. break;
  440. case spv::Op::OpVariable: {
  441. if (spvOptions.enableReflect &&
  442. !cast<SpirvVariable>(instr)->getHlslUserType().empty()) {
  443. addExtension(Extension::GOOGLE_user_type, "HLSL User Type", loc);
  444. addExtension(Extension::GOOGLE_hlsl_functionality1, "HLSL User Type",
  445. loc);
  446. }
  447. break;
  448. }
  449. default:
  450. break;
  451. }
  452. return true;
  453. }
  454. bool CapabilityVisitor::visit(SpirvEntryPoint *entryPoint) {
  455. shaderModel = entryPoint->getExecModel();
  456. switch (shaderModel) {
  457. case spv::ExecutionModel::Fragment:
  458. case spv::ExecutionModel::Vertex:
  459. case spv::ExecutionModel::GLCompute:
  460. addCapability(spv::Capability::Shader);
  461. break;
  462. case spv::ExecutionModel::Geometry:
  463. addCapability(spv::Capability::Geometry);
  464. break;
  465. case spv::ExecutionModel::TessellationControl:
  466. case spv::ExecutionModel::TessellationEvaluation:
  467. addCapability(spv::Capability::Tessellation);
  468. break;
  469. case spv::ExecutionModel::RayGenerationNV:
  470. case spv::ExecutionModel::IntersectionNV:
  471. case spv::ExecutionModel::ClosestHitNV:
  472. case spv::ExecutionModel::AnyHitNV:
  473. case spv::ExecutionModel::MissNV:
  474. case spv::ExecutionModel::CallableNV:
  475. addCapability(spv::Capability::RayTracingNV);
  476. addExtension(Extension::NV_ray_tracing, "SPV_NV_ray_tracing", {});
  477. break;
  478. default:
  479. llvm_unreachable("found unknown shader model");
  480. break;
  481. }
  482. return true;
  483. }
  484. bool CapabilityVisitor::visit(SpirvExecutionMode *execMode) {
  485. if (execMode->getExecutionMode() == spv::ExecutionMode::PostDepthCoverage) {
  486. addCapability(spv::Capability::SampleMaskPostDepthCoverage,
  487. execMode->getEntryPoint()->getSourceLocation());
  488. addExtension(Extension::KHR_post_depth_coverage,
  489. "[[vk::post_depth_coverage]]", execMode->getSourceLocation());
  490. }
  491. return true;
  492. }
  493. bool CapabilityVisitor::visit(SpirvExtInst *instr) {
  494. // OpExtInst using the GLSL extended instruction allows only 32-bit types by
  495. // default. The AMD_gpu_shader_half_float extension adds support for 16-bit
  496. // floating-point component types for the following instructions described in
  497. // the GLSL.std.450 extended instruction set:
  498. // Acos, Acosh, Asin, Asinh, Atan2, Atanh, Atan, Cos, Cosh, Degrees, Exp,
  499. // Exp2, InterpolateAtCentroid, InterpolateAtSample, InterpolateAtOffset, Log,
  500. // Log2, Pow, Radians, Sin, Sinh, Tan, Tanh
  501. if (SpirvType::isOrContainsType<FloatType, 16>(instr->getResultType()))
  502. switch (instr->getInstruction()) {
  503. case GLSLstd450::GLSLstd450Acos:
  504. case GLSLstd450::GLSLstd450Acosh:
  505. case GLSLstd450::GLSLstd450Asin:
  506. case GLSLstd450::GLSLstd450Asinh:
  507. case GLSLstd450::GLSLstd450Atan2:
  508. case GLSLstd450::GLSLstd450Atanh:
  509. case GLSLstd450::GLSLstd450Atan:
  510. case GLSLstd450::GLSLstd450Cos:
  511. case GLSLstd450::GLSLstd450Cosh:
  512. case GLSLstd450::GLSLstd450Degrees:
  513. case GLSLstd450::GLSLstd450Exp:
  514. case GLSLstd450::GLSLstd450Exp2:
  515. case GLSLstd450::GLSLstd450InterpolateAtCentroid:
  516. case GLSLstd450::GLSLstd450InterpolateAtSample:
  517. case GLSLstd450::GLSLstd450InterpolateAtOffset:
  518. case GLSLstd450::GLSLstd450Log:
  519. case GLSLstd450::GLSLstd450Log2:
  520. case GLSLstd450::GLSLstd450Pow:
  521. case GLSLstd450::GLSLstd450Radians:
  522. case GLSLstd450::GLSLstd450Sin:
  523. case GLSLstd450::GLSLstd450Sinh:
  524. case GLSLstd450::GLSLstd450Tan:
  525. case GLSLstd450::GLSLstd450Tanh:
  526. addExtension(Extension::AMD_gpu_shader_half_float, "16-bit float",
  527. instr->getSourceLocation());
  528. default:
  529. break;
  530. }
  531. return visitInstruction(instr);
  532. }
  533. } // end namespace spirv
  534. } // end namespace clang