ModuleBuilder.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. //===--- ModuleBuilder.cpp - SPIR-V builder implementation ----*- 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 "clang/SPIRV/ModuleBuilder.h"
  10. #include "TypeTranslator.h"
  11. #include "spirv/unified1//spirv.hpp11"
  12. #include "clang/SPIRV/BitwiseCast.h"
  13. #include "clang/SPIRV/InstBuilder.h"
  14. namespace clang {
  15. namespace spirv {
  16. ModuleBuilder::ModuleBuilder(SPIRVContext *C, FeatureManager *features,
  17. const EmitSPIRVOptions &opts)
  18. : theContext(*C), featureManager(features), spirvOptions(opts), theModule(),
  19. theFunction(nullptr), insertPoint(nullptr), instBuilder(nullptr),
  20. glslExtSetId(0) {
  21. instBuilder.setConsumer([this](std::vector<uint32_t> &&words) {
  22. this->constructSite = std::move(words);
  23. });
  24. // Set the SPIR-V version and the command line options that were used to
  25. // generate this module, if needed.
  26. if (featureManager && featureManager->getTargetEnv() == SPV_ENV_VULKAN_1_1) {
  27. theModule.useVulkan1p1();
  28. if (spirvOptions.enableDebugInfo)
  29. theModule.setClOptions(opts.clOptions);
  30. }
  31. }
  32. std::vector<uint32_t> ModuleBuilder::takeModule() {
  33. theModule.setBound(theContext.getNextId());
  34. std::vector<uint32_t> binary;
  35. auto ib = InstBuilder([&binary](std::vector<uint32_t> &&words) {
  36. binary.insert(binary.end(), words.begin(), words.end());
  37. });
  38. theModule.take(&ib);
  39. return binary;
  40. }
  41. uint32_t ModuleBuilder::beginFunction(uint32_t funcType, uint32_t returnType,
  42. llvm::StringRef funcName, uint32_t fId) {
  43. if (theFunction) {
  44. assert(false && "found nested function");
  45. return 0;
  46. }
  47. // If the caller doesn't supply a function <result-id>, we need to get one.
  48. if (!fId)
  49. fId = theContext.takeNextId();
  50. theFunction = llvm::make_unique<Function>(
  51. returnType, fId, spv::FunctionControlMask::MaskNone, funcType);
  52. theModule.addDebugName(fId, funcName);
  53. return fId;
  54. }
  55. uint32_t ModuleBuilder::addFnParam(uint32_t ptrType, llvm::StringRef name) {
  56. assert(theFunction && "found detached parameter");
  57. const uint32_t paramId = theContext.takeNextId();
  58. theFunction->addParameter(ptrType, paramId);
  59. theModule.addDebugName(paramId, name);
  60. return paramId;
  61. }
  62. uint32_t ModuleBuilder::addFnVar(uint32_t varType, llvm::StringRef name,
  63. llvm::Optional<uint32_t> init) {
  64. assert(theFunction && "found detached local variable");
  65. const uint32_t ptrType = getPointerType(varType, spv::StorageClass::Function);
  66. const uint32_t varId = theContext.takeNextId();
  67. theFunction->addVariable(ptrType, varId, init);
  68. theModule.addDebugName(varId, name);
  69. return varId;
  70. }
  71. bool ModuleBuilder::endFunction() {
  72. if (theFunction == nullptr) {
  73. assert(false && "no active function");
  74. return false;
  75. }
  76. // Move all basic blocks into the current function.
  77. // TODO: we should adjust the order the basic blocks according to
  78. // SPIR-V validation rules.
  79. for (auto &bb : basicBlocks) {
  80. theFunction->addBasicBlock(std::move(bb.second));
  81. }
  82. basicBlocks.clear();
  83. theModule.addFunction(std::move(theFunction));
  84. theFunction.reset(nullptr);
  85. insertPoint = nullptr;
  86. return true;
  87. }
  88. uint32_t ModuleBuilder::createBasicBlock(llvm::StringRef name) {
  89. if (theFunction == nullptr) {
  90. assert(false && "found detached basic block");
  91. return 0;
  92. }
  93. const uint32_t labelId = theContext.takeNextId();
  94. basicBlocks[labelId] = llvm::make_unique<BasicBlock>(labelId, name);
  95. return labelId;
  96. }
  97. void ModuleBuilder::addSuccessor(uint32_t successorLabel) {
  98. assert(insertPoint && "null insert point");
  99. insertPoint->addSuccessor(getBasicBlock(successorLabel));
  100. }
  101. void ModuleBuilder::setMergeTarget(uint32_t mergeLabel) {
  102. assert(insertPoint && "null insert point");
  103. insertPoint->setMergeTarget(getBasicBlock(mergeLabel));
  104. }
  105. void ModuleBuilder::setContinueTarget(uint32_t continueLabel) {
  106. assert(insertPoint && "null insert point");
  107. insertPoint->setContinueTarget(getBasicBlock(continueLabel));
  108. }
  109. void ModuleBuilder::setInsertPoint(uint32_t labelId) {
  110. insertPoint = getBasicBlock(labelId);
  111. }
  112. uint32_t
  113. ModuleBuilder::createCompositeConstruct(uint32_t resultType,
  114. llvm::ArrayRef<uint32_t> constituents) {
  115. assert(insertPoint && "null insert point");
  116. const uint32_t resultId = theContext.takeNextId();
  117. instBuilder.opCompositeConstruct(resultType, resultId, constituents).x();
  118. insertPoint->appendInstruction(std::move(constructSite));
  119. return resultId;
  120. }
  121. uint32_t
  122. ModuleBuilder::createCompositeExtract(uint32_t resultType, uint32_t composite,
  123. llvm::ArrayRef<uint32_t> indexes) {
  124. assert(insertPoint && "null insert point");
  125. const uint32_t resultId = theContext.takeNextId();
  126. instBuilder.opCompositeExtract(resultType, resultId, composite, indexes).x();
  127. insertPoint->appendInstruction(std::move(constructSite));
  128. return resultId;
  129. }
  130. uint32_t ModuleBuilder::createCompositeInsert(uint32_t resultType,
  131. uint32_t composite,
  132. llvm::ArrayRef<uint32_t> indices,
  133. uint32_t object) {
  134. assert(insertPoint && "null insert point");
  135. const uint32_t resultId = theContext.takeNextId();
  136. instBuilder
  137. .opCompositeInsert(resultType, resultId, object, composite, indices)
  138. .x();
  139. insertPoint->appendInstruction(std::move(constructSite));
  140. return resultId;
  141. }
  142. uint32_t
  143. ModuleBuilder::createVectorShuffle(uint32_t resultType, uint32_t vector1,
  144. uint32_t vector2,
  145. llvm::ArrayRef<uint32_t> selectors) {
  146. assert(insertPoint && "null insert point");
  147. const uint32_t resultId = theContext.takeNextId();
  148. instBuilder.opVectorShuffle(resultType, resultId, vector1, vector2, selectors)
  149. .x();
  150. insertPoint->appendInstruction(std::move(constructSite));
  151. return resultId;
  152. }
  153. uint32_t ModuleBuilder::createLoad(uint32_t resultType, uint32_t pointer) {
  154. assert(insertPoint && "null insert point");
  155. const uint32_t resultId = theContext.takeNextId();
  156. instBuilder.opLoad(resultType, resultId, pointer, llvm::None).x();
  157. insertPoint->appendInstruction(std::move(constructSite));
  158. return resultId;
  159. }
  160. void ModuleBuilder::createStore(uint32_t address, uint32_t value) {
  161. assert(insertPoint && "null insert point");
  162. instBuilder.opStore(address, value, llvm::None).x();
  163. insertPoint->appendInstruction(std::move(constructSite));
  164. }
  165. uint32_t ModuleBuilder::createFunctionCall(uint32_t returnType,
  166. uint32_t functionId,
  167. llvm::ArrayRef<uint32_t> params) {
  168. assert(insertPoint && "null insert point");
  169. const uint32_t id = theContext.takeNextId();
  170. instBuilder.opFunctionCall(returnType, id, functionId, params).x();
  171. insertPoint->appendInstruction(std::move(constructSite));
  172. return id;
  173. }
  174. uint32_t ModuleBuilder::createAccessChain(uint32_t resultType, uint32_t base,
  175. llvm::ArrayRef<uint32_t> indexes) {
  176. assert(insertPoint && "null insert point");
  177. const uint32_t id = theContext.takeNextId();
  178. instBuilder.opAccessChain(resultType, id, base, indexes).x();
  179. insertPoint->appendInstruction(std::move(constructSite));
  180. return id;
  181. }
  182. uint32_t ModuleBuilder::createUnaryOp(spv::Op op, uint32_t resultType,
  183. uint32_t operand) {
  184. assert(insertPoint && "null insert point");
  185. const uint32_t id = theContext.takeNextId();
  186. instBuilder.unaryOp(op, resultType, id, operand).x();
  187. insertPoint->appendInstruction(std::move(constructSite));
  188. switch (op) {
  189. case spv::Op::OpImageQuerySize:
  190. case spv::Op::OpImageQueryLevels:
  191. case spv::Op::OpImageQuerySamples:
  192. requireCapability(spv::Capability::ImageQuery);
  193. break;
  194. default:
  195. // Only checking for ImageQueries, the other Ops can be ignored.
  196. break;
  197. }
  198. return id;
  199. }
  200. uint32_t ModuleBuilder::createBinaryOp(spv::Op op, uint32_t resultType,
  201. uint32_t lhs, uint32_t rhs) {
  202. assert(insertPoint && "null insert point");
  203. const uint32_t id = theContext.takeNextId();
  204. instBuilder.binaryOp(op, resultType, id, lhs, rhs).x();
  205. insertPoint->appendInstruction(std::move(constructSite));
  206. switch (op) {
  207. case spv::Op::OpImageQueryLod:
  208. case spv::Op::OpImageQuerySizeLod:
  209. requireCapability(spv::Capability::ImageQuery);
  210. break;
  211. default:
  212. // Only checking for ImageQueries, the other Ops can be ignored.
  213. break;
  214. }
  215. return id;
  216. }
  217. uint32_t ModuleBuilder::createSpecConstantBinaryOp(spv::Op op,
  218. uint32_t resultType,
  219. uint32_t lhs, uint32_t rhs) {
  220. const uint32_t id = theContext.takeNextId();
  221. instBuilder.specConstantBinaryOp(op, resultType, id, lhs, rhs).x();
  222. theModule.addVariable(std::move(constructSite));
  223. return id;
  224. }
  225. uint32_t ModuleBuilder::createGroupNonUniformOp(spv::Op op, uint32_t resultType,
  226. uint32_t execScope) {
  227. assert(insertPoint && "null insert point");
  228. const uint32_t id = theContext.takeNextId();
  229. instBuilder.groupNonUniformOp(op, resultType, id, execScope).x();
  230. insertPoint->appendInstruction(std::move(constructSite));
  231. return id;
  232. }
  233. uint32_t ModuleBuilder::createGroupNonUniformUnaryOp(
  234. spv::Op op, uint32_t resultType, uint32_t execScope, uint32_t operand,
  235. llvm::Optional<spv::GroupOperation> groupOp) {
  236. assert(insertPoint && "null insert point");
  237. const uint32_t id = theContext.takeNextId();
  238. instBuilder
  239. .groupNonUniformUnaryOp(op, resultType, id, execScope, groupOp, operand)
  240. .x();
  241. insertPoint->appendInstruction(std::move(constructSite));
  242. return id;
  243. }
  244. uint32_t ModuleBuilder::createGroupNonUniformBinaryOp(spv::Op op,
  245. uint32_t resultType,
  246. uint32_t execScope,
  247. uint32_t operand1,
  248. uint32_t operand2) {
  249. assert(insertPoint && "null insert point");
  250. const uint32_t id = theContext.takeNextId();
  251. instBuilder
  252. .groupNonUniformBinaryOp(op, resultType, id, execScope, operand1,
  253. operand2)
  254. .x();
  255. insertPoint->appendInstruction(std::move(constructSite));
  256. return id;
  257. }
  258. uint32_t ModuleBuilder::createAtomicOp(spv::Op opcode, uint32_t resultType,
  259. uint32_t orignalValuePtr,
  260. uint32_t scopeId,
  261. uint32_t memorySemanticsId,
  262. uint32_t valueToOp) {
  263. assert(insertPoint && "null insert point");
  264. const uint32_t id = theContext.takeNextId();
  265. instBuilder
  266. .atomicOp(opcode, resultType, id, orignalValuePtr, scopeId,
  267. memorySemanticsId, valueToOp)
  268. .x();
  269. insertPoint->appendInstruction(std::move(constructSite));
  270. return id;
  271. }
  272. uint32_t ModuleBuilder::createAtomicCompareExchange(
  273. uint32_t resultType, uint32_t orignalValuePtr, uint32_t scopeId,
  274. uint32_t equalMemorySemanticsId, uint32_t unequalMemorySemanticsId,
  275. uint32_t valueToOp, uint32_t comparator) {
  276. assert(insertPoint && "null insert point");
  277. const uint32_t id = theContext.takeNextId();
  278. instBuilder.opAtomicCompareExchange(
  279. resultType, id, orignalValuePtr, scopeId, equalMemorySemanticsId,
  280. unequalMemorySemanticsId, valueToOp, comparator);
  281. instBuilder.x();
  282. insertPoint->appendInstruction(std::move(constructSite));
  283. return id;
  284. }
  285. spv::ImageOperandsMask ModuleBuilder::composeImageOperandsMask(
  286. uint32_t bias, uint32_t lod, const std::pair<uint32_t, uint32_t> &grad,
  287. uint32_t constOffset, uint32_t varOffset, uint32_t constOffsets,
  288. uint32_t sample, uint32_t minLod,
  289. llvm::SmallVectorImpl<uint32_t> *orderedParams) {
  290. using spv::ImageOperandsMask;
  291. // SPIR-V Image Operands from least significant bit to most significant bit
  292. // Bias, Lod, Grad, ConstOffset, Offset, ConstOffsets, Sample, MinLod
  293. auto mask = ImageOperandsMask::MaskNone;
  294. orderedParams->clear();
  295. if (bias) {
  296. mask = mask | ImageOperandsMask::Bias;
  297. orderedParams->push_back(bias);
  298. }
  299. if (lod) {
  300. mask = mask | ImageOperandsMask::Lod;
  301. orderedParams->push_back(lod);
  302. }
  303. if (grad.first && grad.second) {
  304. mask = mask | ImageOperandsMask::Grad;
  305. orderedParams->push_back(grad.first);
  306. orderedParams->push_back(grad.second);
  307. }
  308. if (constOffset) {
  309. mask = mask | ImageOperandsMask::ConstOffset;
  310. orderedParams->push_back(constOffset);
  311. }
  312. if (varOffset) {
  313. mask = mask | ImageOperandsMask::Offset;
  314. requireCapability(spv::Capability::ImageGatherExtended);
  315. orderedParams->push_back(varOffset);
  316. }
  317. if (constOffsets) {
  318. mask = mask | ImageOperandsMask::ConstOffsets;
  319. requireCapability(spv::Capability::ImageGatherExtended);
  320. orderedParams->push_back(constOffsets);
  321. }
  322. if (sample) {
  323. mask = mask | ImageOperandsMask::Sample;
  324. orderedParams->push_back(sample);
  325. }
  326. if (minLod) {
  327. requireCapability(spv::Capability::MinLod);
  328. mask = mask | ImageOperandsMask::MinLod;
  329. orderedParams->push_back(minLod);
  330. }
  331. return mask;
  332. }
  333. uint32_t
  334. ModuleBuilder::createImageSparseTexelsResident(uint32_t resident_code) {
  335. assert(insertPoint && "null insert point");
  336. // Result type must be a boolean
  337. const uint32_t result_type = getBoolType();
  338. const uint32_t id = theContext.takeNextId();
  339. instBuilder.opImageSparseTexelsResident(result_type, id, resident_code).x();
  340. insertPoint->appendInstruction(std::move(constructSite));
  341. return id;
  342. }
  343. uint32_t ModuleBuilder::createImageTexelPointer(uint32_t resultType,
  344. uint32_t imageId,
  345. uint32_t coordinate,
  346. uint32_t sample) {
  347. assert(insertPoint && "null insert point");
  348. const uint32_t id = theContext.takeNextId();
  349. instBuilder.opImageTexelPointer(resultType, id, imageId, coordinate, sample)
  350. .x();
  351. insertPoint->appendInstruction(std::move(constructSite));
  352. return id;
  353. }
  354. uint32_t ModuleBuilder::createImageSample(
  355. uint32_t texelType, uint32_t imageType, uint32_t image, uint32_t sampler,
  356. bool isNonUniform, uint32_t coordinate, uint32_t compareVal, uint32_t bias,
  357. uint32_t lod, std::pair<uint32_t, uint32_t> grad, uint32_t constOffset,
  358. uint32_t varOffset, uint32_t constOffsets, uint32_t sample, uint32_t minLod,
  359. uint32_t residencyCodeId) {
  360. assert(insertPoint && "null insert point");
  361. // The Lod and Grad image operands requires explicit-lod instructions.
  362. // Otherwise we use implicit-lod instructions.
  363. const bool isExplicit = lod || (grad.first && grad.second);
  364. const bool isSparse = (residencyCodeId != 0);
  365. // minLod is only valid with Implicit instructions and Grad instructions.
  366. // This means that we cannot have Lod and minLod together because Lod requires
  367. // explicit insturctions. So either lod or minLod or both must be zero.
  368. assert(lod == 0 || minLod == 0);
  369. uint32_t retType = texelType;
  370. if (isSparse) {
  371. requireCapability(spv::Capability::SparseResidency);
  372. retType = getSparseResidencyStructType(texelType);
  373. }
  374. // An OpSampledImage is required to do the image sampling.
  375. const uint32_t sampledImgId = theContext.takeNextId();
  376. const uint32_t sampledImgTy = getSampledImageType(imageType);
  377. instBuilder.opSampledImage(sampledImgTy, sampledImgId, image, sampler).x();
  378. insertPoint->appendInstruction(std::move(constructSite));
  379. if (isNonUniform) {
  380. // The sampled image will be used to access resource's memory, so we need
  381. // to decorate it with NonUniformEXT.
  382. decorateNonUniformEXT(sampledImgId);
  383. }
  384. uint32_t texelId = theContext.takeNextId();
  385. llvm::SmallVector<uint32_t, 4> params;
  386. const auto mask =
  387. composeImageOperandsMask(bias, lod, grad, constOffset, varOffset,
  388. constOffsets, sample, minLod, &params);
  389. instBuilder.opImageSample(retType, texelId, sampledImgId, coordinate,
  390. compareVal, mask, isExplicit, isSparse);
  391. for (const auto param : params)
  392. instBuilder.idRef(param);
  393. instBuilder.x();
  394. insertPoint->appendInstruction(std::move(constructSite));
  395. if (isSparse) {
  396. // Write the Residency Code
  397. const auto status = createCompositeExtract(getUint32Type(), texelId, {0});
  398. createStore(residencyCodeId, status);
  399. // Extract the real result from the struct
  400. texelId = createCompositeExtract(texelType, texelId, {1});
  401. }
  402. return texelId;
  403. }
  404. void ModuleBuilder::createImageWrite(QualType imageType, uint32_t imageId,
  405. uint32_t coordId, uint32_t texelId) {
  406. assert(insertPoint && "null insert point");
  407. requireCapability(
  408. TypeTranslator::getCapabilityForStorageImageReadWrite(imageType));
  409. instBuilder.opImageWrite(imageId, coordId, texelId, llvm::None).x();
  410. insertPoint->appendInstruction(std::move(constructSite));
  411. }
  412. uint32_t ModuleBuilder::createImageFetchOrRead(
  413. bool doImageFetch, uint32_t texelType, QualType imageType, uint32_t image,
  414. uint32_t coordinate, uint32_t lod, uint32_t constOffset, uint32_t varOffset,
  415. uint32_t constOffsets, uint32_t sample, uint32_t residencyCodeId) {
  416. assert(insertPoint && "null insert point");
  417. llvm::SmallVector<uint32_t, 2> params;
  418. const auto mask =
  419. llvm::Optional<spv::ImageOperandsMask>(composeImageOperandsMask(
  420. /*bias*/ 0, lod, std::make_pair(0, 0), constOffset, varOffset,
  421. constOffsets, sample, /*minLod*/ 0, &params));
  422. const bool isSparse = (residencyCodeId != 0);
  423. uint32_t retType = texelType;
  424. if (isSparse) {
  425. requireCapability(spv::Capability::SparseResidency);
  426. retType = getSparseResidencyStructType(texelType);
  427. }
  428. if (!doImageFetch) {
  429. requireCapability(
  430. TypeTranslator::getCapabilityForStorageImageReadWrite(imageType));
  431. }
  432. uint32_t texelId = theContext.takeNextId();
  433. instBuilder.opImageFetchRead(retType, texelId, image, coordinate, mask,
  434. doImageFetch, isSparse);
  435. for (const auto param : params)
  436. instBuilder.idRef(param);
  437. instBuilder.x();
  438. insertPoint->appendInstruction(std::move(constructSite));
  439. if (isSparse) {
  440. // Write the Residency Code
  441. const auto status = createCompositeExtract(getUint32Type(), texelId, {0});
  442. createStore(residencyCodeId, status);
  443. // Extract the real result from the struct
  444. texelId = createCompositeExtract(texelType, texelId, {1});
  445. }
  446. return texelId;
  447. }
  448. uint32_t ModuleBuilder::createImageGather(
  449. uint32_t texelType, uint32_t imageType, uint32_t image, uint32_t sampler,
  450. bool isNonUniform, uint32_t coordinate, uint32_t component,
  451. uint32_t compareVal, uint32_t constOffset, uint32_t varOffset,
  452. uint32_t constOffsets, uint32_t sample, uint32_t residencyCodeId) {
  453. assert(insertPoint && "null insert point");
  454. uint32_t sparseRetType = 0;
  455. if (residencyCodeId) {
  456. requireCapability(spv::Capability::SparseResidency);
  457. sparseRetType = getSparseResidencyStructType(texelType);
  458. }
  459. // An OpSampledImage is required to do the image sampling.
  460. const uint32_t sampledImgId = theContext.takeNextId();
  461. const uint32_t sampledImgTy = getSampledImageType(imageType);
  462. instBuilder.opSampledImage(sampledImgTy, sampledImgId, image, sampler).x();
  463. insertPoint->appendInstruction(std::move(constructSite));
  464. if (isNonUniform) {
  465. // The sampled image will be used to access resource's memory, so we need
  466. // to decorate it with NonUniformEXT.
  467. decorateNonUniformEXT(sampledImgId);
  468. }
  469. llvm::SmallVector<uint32_t, 2> params;
  470. // TODO: Update ImageGather to accept minLod if necessary.
  471. const auto mask =
  472. llvm::Optional<spv::ImageOperandsMask>(composeImageOperandsMask(
  473. /*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
  474. constOffsets, sample, /*minLod*/ 0, &params));
  475. uint32_t texelId = theContext.takeNextId();
  476. if (compareVal) {
  477. if (residencyCodeId) {
  478. // Note: OpImageSparseDrefGather does not take the component parameter.
  479. instBuilder.opImageSparseDrefGather(sparseRetType, texelId, sampledImgId,
  480. coordinate, compareVal, mask);
  481. } else {
  482. // Note: OpImageDrefGather does not take the component parameter.
  483. instBuilder.opImageDrefGather(texelType, texelId, sampledImgId,
  484. coordinate, compareVal, mask);
  485. }
  486. } else {
  487. if (residencyCodeId) {
  488. instBuilder.opImageSparseGather(sparseRetType, texelId, sampledImgId,
  489. coordinate, component, mask);
  490. } else {
  491. instBuilder.opImageGather(texelType, texelId, sampledImgId, coordinate,
  492. component, mask);
  493. }
  494. }
  495. for (const auto param : params)
  496. instBuilder.idRef(param);
  497. instBuilder.x();
  498. insertPoint->appendInstruction(std::move(constructSite));
  499. if (residencyCodeId) {
  500. // Write the Residency Code
  501. const auto status = createCompositeExtract(getUint32Type(), texelId, {0});
  502. createStore(residencyCodeId, status);
  503. // Extract the real result from the struct
  504. texelId = createCompositeExtract(texelType, texelId, {1});
  505. }
  506. return texelId;
  507. }
  508. uint32_t ModuleBuilder::createSelect(uint32_t resultType, uint32_t condition,
  509. uint32_t trueValue, uint32_t falseValue) {
  510. assert(insertPoint && "null insert point");
  511. const uint32_t id = theContext.takeNextId();
  512. instBuilder.opSelect(resultType, id, condition, trueValue, falseValue).x();
  513. insertPoint->appendInstruction(std::move(constructSite));
  514. return id;
  515. }
  516. void ModuleBuilder::createSwitch(
  517. uint32_t mergeLabel, uint32_t selector, uint32_t defaultLabel,
  518. llvm::ArrayRef<std::pair<uint32_t, uint32_t>> target) {
  519. assert(insertPoint && "null insert point");
  520. // Create the OpSelectioMerege.
  521. instBuilder.opSelectionMerge(mergeLabel, spv::SelectionControlMask::MaskNone)
  522. .x();
  523. insertPoint->appendInstruction(std::move(constructSite));
  524. // Create the OpSwitch.
  525. instBuilder.opSwitch(selector, defaultLabel, target).x();
  526. insertPoint->appendInstruction(std::move(constructSite));
  527. }
  528. void ModuleBuilder::createKill() {
  529. assert(insertPoint && "null insert point");
  530. assert(!isCurrentBasicBlockTerminated());
  531. instBuilder.opKill().x();
  532. insertPoint->appendInstruction(std::move(constructSite));
  533. }
  534. void ModuleBuilder::createBranch(uint32_t targetLabel, uint32_t mergeBB,
  535. uint32_t continueBB,
  536. spv::LoopControlMask loopControl) {
  537. assert(insertPoint && "null insert point");
  538. if (mergeBB && continueBB) {
  539. instBuilder.opLoopMerge(mergeBB, continueBB, loopControl).x();
  540. insertPoint->appendInstruction(std::move(constructSite));
  541. }
  542. instBuilder.opBranch(targetLabel).x();
  543. insertPoint->appendInstruction(std::move(constructSite));
  544. }
  545. void ModuleBuilder::createConditionalBranch(
  546. uint32_t condition, uint32_t trueLabel, uint32_t falseLabel,
  547. uint32_t mergeLabel, uint32_t continueLabel,
  548. spv::SelectionControlMask selectionControl,
  549. spv::LoopControlMask loopControl) {
  550. assert(insertPoint && "null insert point");
  551. if (mergeLabel) {
  552. if (continueLabel) {
  553. instBuilder.opLoopMerge(mergeLabel, continueLabel, loopControl).x();
  554. insertPoint->appendInstruction(std::move(constructSite));
  555. } else {
  556. instBuilder.opSelectionMerge(mergeLabel, selectionControl).x();
  557. insertPoint->appendInstruction(std::move(constructSite));
  558. }
  559. }
  560. instBuilder.opBranchConditional(condition, trueLabel, falseLabel, {}).x();
  561. insertPoint->appendInstruction(std::move(constructSite));
  562. }
  563. void ModuleBuilder::createReturn() {
  564. assert(insertPoint && "null insert point");
  565. instBuilder.opReturn().x();
  566. insertPoint->appendInstruction(std::move(constructSite));
  567. }
  568. void ModuleBuilder::createReturnValue(uint32_t value) {
  569. assert(insertPoint && "null insert point");
  570. instBuilder.opReturnValue(value).x();
  571. insertPoint->appendInstruction(std::move(constructSite));
  572. }
  573. uint32_t ModuleBuilder::createExtInst(uint32_t resultType, uint32_t setId,
  574. uint32_t instId,
  575. llvm::ArrayRef<uint32_t> operands) {
  576. assert(insertPoint && "null insert point");
  577. uint32_t resultId = theContext.takeNextId();
  578. instBuilder.opExtInst(resultType, resultId, setId, instId, operands).x();
  579. insertPoint->appendInstruction(std::move(constructSite));
  580. return resultId;
  581. }
  582. void ModuleBuilder::createBarrier(uint32_t execution, uint32_t memory,
  583. uint32_t semantics) {
  584. assert(insertPoint && "null insert point");
  585. if (execution)
  586. instBuilder.opControlBarrier(execution, memory, semantics).x();
  587. else
  588. instBuilder.opMemoryBarrier(memory, semantics).x();
  589. insertPoint->appendInstruction(std::move(constructSite));
  590. }
  591. uint32_t ModuleBuilder::createBitFieldExtract(uint32_t resultType,
  592. uint32_t base, uint32_t offset,
  593. uint32_t count, bool isSigned) {
  594. assert(insertPoint && "null insert point");
  595. uint32_t resultId = theContext.takeNextId();
  596. if (isSigned)
  597. instBuilder.opBitFieldSExtract(resultType, resultId, base, offset, count);
  598. else
  599. instBuilder.opBitFieldUExtract(resultType, resultId, base, offset, count);
  600. instBuilder.x();
  601. insertPoint->appendInstruction(std::move(constructSite));
  602. return resultId;
  603. }
  604. uint32_t ModuleBuilder::createBitFieldInsert(uint32_t resultType, uint32_t base,
  605. uint32_t insert, uint32_t offset,
  606. uint32_t count) {
  607. assert(insertPoint && "null insert point");
  608. uint32_t resultId = theContext.takeNextId();
  609. instBuilder
  610. .opBitFieldInsert(resultType, resultId, base, insert, offset, count)
  611. .x();
  612. insertPoint->appendInstruction(std::move(constructSite));
  613. return resultId;
  614. }
  615. void ModuleBuilder::createEmitVertex() {
  616. assert(insertPoint && "null insert point");
  617. instBuilder.opEmitVertex().x();
  618. insertPoint->appendInstruction(std::move(constructSite));
  619. }
  620. void ModuleBuilder::createEndPrimitive() {
  621. assert(insertPoint && "null insert point");
  622. instBuilder.opEndPrimitive().x();
  623. insertPoint->appendInstruction(std::move(constructSite));
  624. }
  625. void ModuleBuilder::addExecutionMode(uint32_t entryPointId,
  626. spv::ExecutionMode em,
  627. llvm::ArrayRef<uint32_t> params) {
  628. instBuilder.opExecutionMode(entryPointId, em);
  629. for (const auto &param : params) {
  630. instBuilder.literalInteger(param);
  631. }
  632. instBuilder.x();
  633. theModule.addExecutionMode(std::move(constructSite));
  634. }
  635. void ModuleBuilder::addExtension(Extension ext, llvm::StringRef target,
  636. SourceLocation srcLoc) {
  637. assert(featureManager);
  638. featureManager->requestExtension(ext, target, srcLoc);
  639. // Do not emit OpExtension if the given extension is natively supported in the
  640. // target environment.
  641. if (featureManager->isExtensionRequiredForTargetEnv(ext))
  642. theModule.addExtension(featureManager->getExtensionName(ext));
  643. }
  644. uint32_t ModuleBuilder::getGLSLExtInstSet() {
  645. if (glslExtSetId == 0) {
  646. glslExtSetId = theContext.takeNextId();
  647. theModule.addExtInstSet(glslExtSetId, "GLSL.std.450");
  648. }
  649. return glslExtSetId;
  650. }
  651. uint32_t ModuleBuilder::addStageIOVar(uint32_t type,
  652. spv::StorageClass storageClass,
  653. std::string name) {
  654. const uint32_t pointerType = getPointerType(type, storageClass);
  655. const uint32_t varId = theContext.takeNextId();
  656. instBuilder.opVariable(pointerType, varId, storageClass, llvm::None).x();
  657. theModule.addVariable(std::move(constructSite));
  658. theModule.addDebugName(varId, name);
  659. return varId;
  660. }
  661. uint32_t ModuleBuilder::addStageBuiltinVar(uint32_t type, spv::StorageClass sc,
  662. spv::BuiltIn builtin) {
  663. const uint32_t pointerType = getPointerType(type, sc);
  664. const uint32_t varId = theContext.takeNextId();
  665. instBuilder.opVariable(pointerType, varId, sc, llvm::None).x();
  666. theModule.addVariable(std::move(constructSite));
  667. // Decorate with the specified Builtin
  668. const Decoration *d = Decoration::getBuiltIn(theContext, builtin);
  669. theModule.addDecoration(d, varId);
  670. return varId;
  671. }
  672. uint32_t ModuleBuilder::addModuleVar(uint32_t type, spv::StorageClass sc,
  673. llvm::StringRef name,
  674. llvm::Optional<uint32_t> init) {
  675. assert(sc != spv::StorageClass::Function);
  676. // TODO: basically duplicated code of addFileVar()
  677. const uint32_t pointerType = getPointerType(type, sc);
  678. const uint32_t varId = theContext.takeNextId();
  679. instBuilder.opVariable(pointerType, varId, sc, init).x();
  680. theModule.addVariable(std::move(constructSite));
  681. theModule.addDebugName(varId, name);
  682. return varId;
  683. }
  684. void ModuleBuilder::decorateDSetBinding(uint32_t targetId, uint32_t setNumber,
  685. uint32_t bindingNumber) {
  686. const auto *d = Decoration::getDescriptorSet(theContext, setNumber);
  687. theModule.addDecoration(d, targetId);
  688. d = Decoration::getBinding(theContext, bindingNumber);
  689. theModule.addDecoration(d, targetId);
  690. }
  691. void ModuleBuilder::decorateInputAttachmentIndex(uint32_t targetId,
  692. uint32_t indexNumber) {
  693. const auto *d = Decoration::getInputAttachmentIndex(theContext, indexNumber);
  694. theModule.addDecoration(d, targetId);
  695. }
  696. void ModuleBuilder::decorateCounterBufferId(uint32_t mainBufferId,
  697. uint32_t counterBufferId) {
  698. if (spirvOptions.enableReflect) {
  699. addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
  700. {});
  701. theModule.addDecoration(
  702. Decoration::getHlslCounterBufferGOOGLE(theContext, counterBufferId),
  703. mainBufferId);
  704. }
  705. }
  706. void ModuleBuilder::decorateHlslSemantic(uint32_t targetId,
  707. llvm::StringRef semantic,
  708. llvm::Optional<uint32_t> memberIdx) {
  709. if (spirvOptions.enableReflect) {
  710. addExtension(Extension::GOOGLE_hlsl_functionality1, "SPIR-V reflection",
  711. {});
  712. theModule.addDecoration(
  713. Decoration::getHlslSemanticGOOGLE(theContext, semantic, memberIdx),
  714. targetId);
  715. }
  716. }
  717. void ModuleBuilder::decorateLocation(uint32_t targetId, uint32_t location) {
  718. const Decoration *d =
  719. Decoration::getLocation(theContext, location, llvm::None);
  720. theModule.addDecoration(d, targetId);
  721. }
  722. void ModuleBuilder::decorateIndex(uint32_t targetId, uint32_t index) {
  723. const Decoration *d = Decoration::getIndex(theContext, index);
  724. theModule.addDecoration(d, targetId);
  725. }
  726. void ModuleBuilder::decorateSpecId(uint32_t targetId, uint32_t specId) {
  727. const Decoration *d = Decoration::getSpecId(theContext, specId);
  728. theModule.addDecoration(d, targetId);
  729. }
  730. void ModuleBuilder::decorateCentroid(uint32_t targetId) {
  731. const Decoration *d = Decoration::getCentroid(theContext);
  732. theModule.addDecoration(d, targetId);
  733. }
  734. void ModuleBuilder::decorateFlat(uint32_t targetId) {
  735. const Decoration *d = Decoration::getFlat(theContext);
  736. theModule.addDecoration(d, targetId);
  737. }
  738. void ModuleBuilder::decorateNoPerspective(uint32_t targetId) {
  739. const Decoration *d = Decoration::getNoPerspective(theContext);
  740. theModule.addDecoration(d, targetId);
  741. }
  742. void ModuleBuilder::decorateSample(uint32_t targetId) {
  743. const Decoration *d = Decoration::getSample(theContext);
  744. theModule.addDecoration(d, targetId);
  745. }
  746. void ModuleBuilder::decorateBlock(uint32_t targetId) {
  747. const Decoration *d = Decoration::getBlock(theContext);
  748. theModule.addDecoration(d, targetId);
  749. }
  750. void ModuleBuilder::decorateRelaxedPrecision(uint32_t targetId) {
  751. const Decoration *d = Decoration::getRelaxedPrecision(theContext);
  752. theModule.addDecoration(d, targetId);
  753. }
  754. void ModuleBuilder::decoratePatch(uint32_t targetId) {
  755. const Decoration *d = Decoration::getPatch(theContext);
  756. theModule.addDecoration(d, targetId);
  757. }
  758. void ModuleBuilder::decorateNonUniformEXT(uint32_t targetId) {
  759. const Decoration *d = Decoration::getNonUniformEXT(theContext);
  760. theModule.addDecoration(d, targetId);
  761. }
  762. #define IMPL_GET_PRIMITIVE_TYPE(ty) \
  763. \
  764. uint32_t ModuleBuilder::get##ty##Type() { \
  765. const Type *type = Type::get##ty(theContext); \
  766. const uint32_t typeId = theContext.getResultIdForType(type); \
  767. theModule.addType(type, typeId); \
  768. return typeId; \
  769. }
  770. IMPL_GET_PRIMITIVE_TYPE(Void)
  771. IMPL_GET_PRIMITIVE_TYPE(Bool)
  772. IMPL_GET_PRIMITIVE_TYPE(Int32)
  773. IMPL_GET_PRIMITIVE_TYPE(Uint32)
  774. IMPL_GET_PRIMITIVE_TYPE(Float32)
  775. #undef IMPL_GET_PRIMITIVE_TYPE
  776. // Note: At the moment, Float16 capability should not be added for Vulkan 1.0.
  777. // It is not a required capability, and adding the SPV_AMD_gpu_half_float does
  778. // not enable this capability. Any driver that supports float16 in Vulkan 1.0
  779. // should accept this extension.
  780. #define IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(ty, cap) \
  781. \
  782. uint32_t ModuleBuilder::get##ty##Type() { \
  783. if (spv::Capability::cap == spv::Capability::Float16) \
  784. addExtension(Extension::AMD_gpu_shader_half_float, "16-bit float", {}); \
  785. else \
  786. requireCapability(spv::Capability::cap); \
  787. const Type *type = Type::get##ty(theContext); \
  788. const uint32_t typeId = theContext.getResultIdForType(type); \
  789. theModule.addType(type, typeId); \
  790. return typeId; \
  791. }
  792. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Int64, Int64)
  793. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Uint64, Int64)
  794. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Float64, Float64)
  795. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Int16, Int16)
  796. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Uint16, Int16)
  797. IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY(Float16, Float16)
  798. #undef IMPL_GET_PRIMITIVE_TYPE_WITH_CAPABILITY
  799. uint32_t ModuleBuilder::getVecType(uint32_t elemType, uint32_t elemCount) {
  800. const Type *type = nullptr;
  801. switch (elemCount) {
  802. case 2:
  803. type = Type::getVec2(theContext, elemType);
  804. break;
  805. case 3:
  806. type = Type::getVec3(theContext, elemType);
  807. break;
  808. case 4:
  809. type = Type::getVec4(theContext, elemType);
  810. break;
  811. default:
  812. assert(false && "unhandled vector size");
  813. // Error found. Return 0 as the <result-id> directly.
  814. return 0;
  815. }
  816. const uint32_t typeId = theContext.getResultIdForType(type);
  817. theModule.addType(type, typeId);
  818. return typeId;
  819. }
  820. uint32_t ModuleBuilder::getMatType(QualType elemType, uint32_t colType,
  821. uint32_t colCount,
  822. Type::DecorationSet decorations) {
  823. // NOTE: According to Item "Data rules" of SPIR-V Spec 2.16.1 "Universal
  824. // Validation Rules":
  825. // Matrix types can only be parameterized with floating-point types.
  826. //
  827. // So we need special handling of non-fp matrices. We emulate non-fp
  828. // matrices as an array of vectors.
  829. if (!elemType->isFloatingType())
  830. return getArrayType(colType, getConstantUint32(colCount), decorations);
  831. const Type *type = Type::getMatrix(theContext, colType, colCount);
  832. const uint32_t typeId = theContext.getResultIdForType(type);
  833. theModule.addType(type, typeId);
  834. return typeId;
  835. }
  836. uint32_t ModuleBuilder::getPointerType(uint32_t pointeeType,
  837. spv::StorageClass storageClass) {
  838. const Type *type = Type::getPointer(theContext, storageClass, pointeeType);
  839. const uint32_t typeId = theContext.getResultIdForType(type);
  840. theModule.addType(type, typeId);
  841. return typeId;
  842. }
  843. uint32_t
  844. ModuleBuilder::getStructType(llvm::ArrayRef<uint32_t> fieldTypes,
  845. llvm::StringRef structName,
  846. llvm::ArrayRef<llvm::StringRef> fieldNames,
  847. Type::DecorationSet decorations) {
  848. const Type *type =
  849. Type::getStruct(theContext, fieldTypes, structName, decorations);
  850. bool isRegistered = false;
  851. const uint32_t typeId = theContext.getResultIdForType(type, &isRegistered);
  852. theModule.addType(type, typeId);
  853. if (!isRegistered) {
  854. theModule.addDebugName(typeId, structName);
  855. if (!fieldNames.empty()) {
  856. assert(fieldNames.size() == fieldTypes.size());
  857. for (uint32_t i = 0; i < fieldNames.size(); ++i)
  858. theModule.addDebugName(typeId, fieldNames[i],
  859. llvm::Optional<uint32_t>(i));
  860. }
  861. }
  862. return typeId;
  863. }
  864. uint32_t ModuleBuilder::getSparseResidencyStructType(uint32_t type) {
  865. const auto uintType = getUint32Type();
  866. return getStructType({uintType, type}, "SparseResidencyStruct",
  867. {"Residency.Code", "Result.Type"});
  868. }
  869. uint32_t ModuleBuilder::getArrayType(uint32_t elemType, uint32_t count,
  870. Type::DecorationSet decorations) {
  871. const Type *type = Type::getArray(theContext, elemType, count, decorations);
  872. const uint32_t typeId = theContext.getResultIdForType(type);
  873. theModule.addType(type, typeId);
  874. return typeId;
  875. }
  876. uint32_t ModuleBuilder::getRuntimeArrayType(uint32_t elemType,
  877. Type::DecorationSet decorations) {
  878. const Type *type = Type::getRuntimeArray(theContext, elemType, decorations);
  879. const uint32_t typeId = theContext.getResultIdForType(type);
  880. theModule.addType(type, typeId);
  881. return typeId;
  882. }
  883. uint32_t ModuleBuilder::getFunctionType(uint32_t returnType,
  884. llvm::ArrayRef<uint32_t> paramTypes) {
  885. const Type *type = Type::getFunction(theContext, returnType, paramTypes);
  886. const uint32_t typeId = theContext.getResultIdForType(type);
  887. theModule.addType(type, typeId);
  888. return typeId;
  889. }
  890. uint32_t ModuleBuilder::getImageType(uint32_t sampledType, spv::Dim dim,
  891. uint32_t depth, bool isArray, uint32_t ms,
  892. uint32_t sampled,
  893. spv::ImageFormat format) {
  894. const Type *type = Type::getImage(theContext, sampledType, dim, depth,
  895. isArray, ms, sampled, format);
  896. bool isRegistered = false;
  897. const uint32_t typeId = theContext.getResultIdForType(type, &isRegistered);
  898. theModule.addType(type, typeId);
  899. switch (format) {
  900. case spv::ImageFormat::Rg32f:
  901. case spv::ImageFormat::Rg16f:
  902. case spv::ImageFormat::R11fG11fB10f:
  903. case spv::ImageFormat::R16f:
  904. case spv::ImageFormat::Rgba16:
  905. case spv::ImageFormat::Rgb10A2:
  906. case spv::ImageFormat::Rg16:
  907. case spv::ImageFormat::Rg8:
  908. case spv::ImageFormat::R16:
  909. case spv::ImageFormat::R8:
  910. case spv::ImageFormat::Rgba16Snorm:
  911. case spv::ImageFormat::Rg16Snorm:
  912. case spv::ImageFormat::Rg8Snorm:
  913. case spv::ImageFormat::R16Snorm:
  914. case spv::ImageFormat::R8Snorm:
  915. case spv::ImageFormat::Rg32i:
  916. case spv::ImageFormat::Rg16i:
  917. case spv::ImageFormat::Rg8i:
  918. case spv::ImageFormat::R16i:
  919. case spv::ImageFormat::R8i:
  920. case spv::ImageFormat::Rgb10a2ui:
  921. case spv::ImageFormat::Rg32ui:
  922. case spv::ImageFormat::Rg16ui:
  923. case spv::ImageFormat::Rg8ui:
  924. case spv::ImageFormat::R16ui:
  925. case spv::ImageFormat::R8ui:
  926. requireCapability(spv::Capability::StorageImageExtendedFormats);
  927. break;
  928. default:
  929. // Only image formats requiring extended formats are relevant. The rest just
  930. // pass through.
  931. break;
  932. }
  933. if (dim == spv::Dim::Dim1D) {
  934. if (sampled == 2u) {
  935. requireCapability(spv::Capability::Image1D);
  936. } else {
  937. requireCapability(spv::Capability::Sampled1D);
  938. }
  939. } else if (dim == spv::Dim::Buffer) {
  940. requireCapability(spv::Capability::SampledBuffer);
  941. } else if (dim == spv::Dim::SubpassData) {
  942. requireCapability(spv::Capability::InputAttachment);
  943. }
  944. if (isArray && ms) {
  945. requireCapability(spv::Capability::ImageMSArray);
  946. }
  947. // Skip constructing the debug name if we have already done it before.
  948. if (!isRegistered) {
  949. const char *dimStr = "";
  950. switch (dim) {
  951. case spv::Dim::Dim1D:
  952. dimStr = "1d.";
  953. break;
  954. case spv::Dim::Dim2D:
  955. dimStr = "2d.";
  956. break;
  957. case spv::Dim::Dim3D:
  958. dimStr = "3d.";
  959. break;
  960. case spv::Dim::Cube:
  961. dimStr = "cube.";
  962. break;
  963. case spv::Dim::Rect:
  964. dimStr = "rect.";
  965. break;
  966. case spv::Dim::Buffer:
  967. dimStr = "buffer.";
  968. break;
  969. case spv::Dim::SubpassData:
  970. dimStr = "subpass.";
  971. break;
  972. default:
  973. break;
  974. }
  975. std::string name =
  976. std::string("type.") + dimStr + "image" + (isArray ? ".array" : "");
  977. theModule.addDebugName(typeId, name);
  978. }
  979. return typeId;
  980. }
  981. uint32_t ModuleBuilder::getSamplerType() {
  982. const Type *type = Type::getSampler(theContext);
  983. const uint32_t typeId = theContext.getResultIdForType(type);
  984. theModule.addType(type, typeId);
  985. theModule.addDebugName(typeId, "type.sampler");
  986. return typeId;
  987. }
  988. uint32_t ModuleBuilder::getSampledImageType(uint32_t imageType) {
  989. const Type *type = Type::getSampledImage(theContext, imageType);
  990. const uint32_t typeId = theContext.getResultIdForType(type);
  991. theModule.addType(type, typeId);
  992. theModule.addDebugName(typeId, "type.sampled.image");
  993. return typeId;
  994. }
  995. uint32_t ModuleBuilder::getByteAddressBufferType(bool isRW) {
  996. // Create a uint RuntimeArray with Array Stride of 4.
  997. const uint32_t uintType = getUint32Type();
  998. const auto *arrStride4 = Decoration::getArrayStride(theContext, 4u);
  999. const Type *raType =
  1000. Type::getRuntimeArray(theContext, uintType, {arrStride4});
  1001. const uint32_t raTypeId = theContext.getResultIdForType(raType);
  1002. theModule.addType(raType, raTypeId);
  1003. // Create a struct containing the runtime array as its only member.
  1004. // The struct must also be decorated as BufferBlock. The offset decoration
  1005. // should also be applied to the first (only) member. NonWritable decoration
  1006. // should also be applied to the first member if isRW is true.
  1007. llvm::SmallVector<const Decoration *, 3> typeDecs;
  1008. typeDecs.push_back(Decoration::getBufferBlock(theContext));
  1009. typeDecs.push_back(Decoration::getOffset(theContext, 0, 0));
  1010. if (!isRW)
  1011. typeDecs.push_back(Decoration::getNonWritable(theContext, 0));
  1012. const Type *type = Type::getStruct(theContext, {raTypeId}, "", typeDecs);
  1013. const uint32_t typeId = theContext.getResultIdForType(type);
  1014. theModule.addType(type, typeId);
  1015. theModule.addDebugName(typeId, isRW ? "type.RWByteAddressBuffer"
  1016. : "type.ByteAddressBuffer");
  1017. return typeId;
  1018. }
  1019. uint32_t ModuleBuilder::getConstantBool(bool value, bool isSpecConst) {
  1020. if (isSpecConst) {
  1021. const uint32_t constId = theContext.takeNextId();
  1022. if (value) {
  1023. instBuilder.opSpecConstantTrue(getBoolType(), constId).x();
  1024. } else {
  1025. instBuilder.opSpecConstantFalse(getBoolType(), constId).x();
  1026. }
  1027. theModule.addVariable(std::move(constructSite));
  1028. return constId;
  1029. }
  1030. const uint32_t typeId = getBoolType();
  1031. const Constant *constant = value ? Constant::getTrue(theContext, typeId)
  1032. : Constant::getFalse(theContext, typeId);
  1033. const uint32_t constId = theContext.getResultIdForConstant(constant);
  1034. theModule.addConstant(constant, constId);
  1035. return constId;
  1036. }
  1037. #define IMPL_GET_PRIMITIVE_CONST(builderTy, cppTy) \
  1038. \
  1039. uint32_t ModuleBuilder::getConstant##builderTy(cppTy value) { \
  1040. const uint32_t typeId = get##builderTy##Type(); \
  1041. const Constant *constant = \
  1042. Constant::get##builderTy(theContext, typeId, value); \
  1043. const uint32_t constId = theContext.getResultIdForConstant(constant); \
  1044. theModule.addConstant(constant, constId); \
  1045. return constId; \
  1046. }
  1047. #define IMPL_GET_PRIMITIVE_CONST_SPEC_CONST(builderTy, cppTy) \
  1048. \
  1049. uint32_t ModuleBuilder::getConstant##builderTy(cppTy value, \
  1050. bool isSpecConst) { \
  1051. if (isSpecConst) { \
  1052. const uint32_t constId = theContext.takeNextId(); \
  1053. instBuilder \
  1054. .opSpecConstant(get##builderTy##Type(), constId, \
  1055. cast::BitwiseCast<uint32_t>(value)) \
  1056. .x(); \
  1057. theModule.addVariable(std::move(constructSite)); \
  1058. return constId; \
  1059. } \
  1060. \
  1061. const uint32_t typeId = get##builderTy##Type(); \
  1062. const Constant *constant = \
  1063. Constant::get##builderTy(theContext, typeId, value); \
  1064. const uint32_t constId = theContext.getResultIdForConstant(constant); \
  1065. theModule.addConstant(constant, constId); \
  1066. return constId; \
  1067. }
  1068. IMPL_GET_PRIMITIVE_CONST(Int16, int16_t)
  1069. IMPL_GET_PRIMITIVE_CONST_SPEC_CONST(Int32, int32_t)
  1070. IMPL_GET_PRIMITIVE_CONST(Uint16, uint16_t)
  1071. IMPL_GET_PRIMITIVE_CONST_SPEC_CONST(Uint32, uint32_t)
  1072. IMPL_GET_PRIMITIVE_CONST(Float16, int16_t)
  1073. IMPL_GET_PRIMITIVE_CONST_SPEC_CONST(Float32, float)
  1074. IMPL_GET_PRIMITIVE_CONST(Float64, double)
  1075. IMPL_GET_PRIMITIVE_CONST(Int64, int64_t)
  1076. IMPL_GET_PRIMITIVE_CONST(Uint64, uint64_t)
  1077. #undef IMPL_GET_PRIMITIVE_CONST
  1078. #undef IMPL_GET_PRIMITIVE_CONST_SPEC_CONST
  1079. uint32_t
  1080. ModuleBuilder::getConstantComposite(uint32_t typeId,
  1081. llvm::ArrayRef<uint32_t> constituents) {
  1082. const Constant *constant =
  1083. Constant::getComposite(theContext, typeId, constituents);
  1084. const uint32_t constId = theContext.getResultIdForConstant(constant);
  1085. theModule.addConstant(constant, constId);
  1086. return constId;
  1087. }
  1088. uint32_t ModuleBuilder::getConstantNull(uint32_t typeId) {
  1089. const Constant *constant = Constant::getNull(theContext, typeId);
  1090. const uint32_t constId = theContext.getResultIdForConstant(constant);
  1091. theModule.addConstant(constant, constId);
  1092. return constId;
  1093. }
  1094. void ModuleBuilder::debugLine(uint32_t file, uint32_t line, uint32_t column) {
  1095. instBuilder.opLine(file, line, column).x();
  1096. insertPoint->appendInstruction(std::move(constructSite));
  1097. }
  1098. BasicBlock *ModuleBuilder::getBasicBlock(uint32_t labelId) {
  1099. auto it = basicBlocks.find(labelId);
  1100. if (it == basicBlocks.end()) {
  1101. assert(false && "invalid <label-id>");
  1102. return nullptr;
  1103. }
  1104. return it->second.get();
  1105. }
  1106. } // end namespace spirv
  1107. } // end namespace clang