DxilShaderFlags.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilShaderFlags.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "dxc/DXIL/DxilModule.h"
  10. #include "dxc/DXIL/DxilShaderFlags.h"
  11. #include "dxc/DXIL/DxilOperations.h"
  12. #include "dxc/DXIL/DxilResource.h"
  13. #include "dxc/Support/Global.h"
  14. #include "llvm/IR/LLVMContext.h"
  15. #include "llvm/IR/Instructions.h"
  16. #include "llvm/IR/Constants.h"
  17. #include "llvm/Support/Casting.h"
  18. #include "dxc/DXIL/DxilEntryProps.h"
  19. #include "dxc/DXIL/DxilInstructions.h"
  20. #include "dxc/DXIL/DxilResourceProperties.h"
  21. #include "dxc/DXIL/DxilUtil.h"
  22. using namespace hlsl;
  23. using namespace llvm;
  24. ShaderFlags::ShaderFlags():
  25. m_bDisableOptimizations(false)
  26. , m_bDisableMathRefactoring(false)
  27. , m_bEnableDoublePrecision(false)
  28. , m_bForceEarlyDepthStencil(false)
  29. , m_bEnableRawAndStructuredBuffers(false)
  30. , m_bLowPrecisionPresent(false)
  31. , m_bEnableDoubleExtensions(false)
  32. , m_bEnableMSAD(false)
  33. , m_bAllResourcesBound(false)
  34. , m_bViewportAndRTArrayIndex(false)
  35. , m_bInnerCoverage(false)
  36. , m_bStencilRef(false)
  37. , m_bTiledResources(false)
  38. , m_bUAVLoadAdditionalFormats(false)
  39. , m_bLevel9ComparisonFiltering(false)
  40. , m_b64UAVs(false)
  41. , m_UAVsAtEveryStage(false)
  42. , m_bCSRawAndStructuredViaShader4X(false)
  43. , m_bROVS(false)
  44. , m_bWaveOps(false)
  45. , m_bInt64Ops(false)
  46. , m_bViewID(false)
  47. , m_bBarycentrics(false)
  48. , m_bUseNativeLowPrecision(false)
  49. , m_bShadingRate(false)
  50. , m_bRaytracingTier1_1(false)
  51. , m_bSamplerFeedback(false)
  52. , m_align0(0)
  53. , m_align1(0)
  54. {}
  55. uint64_t ShaderFlags::GetFeatureInfo() const {
  56. uint64_t Flags = 0;
  57. Flags |= m_bEnableDoublePrecision ? hlsl::DXIL::ShaderFeatureInfo_Doubles : 0;
  58. Flags |= m_bLowPrecisionPresent && !m_bUseNativeLowPrecision
  59. ? hlsl::DXIL::ShaderFeatureInfo_MinimumPrecision
  60. : 0;
  61. Flags |= m_bLowPrecisionPresent && m_bUseNativeLowPrecision
  62. ? hlsl::DXIL::ShaderFeatureInfo_NativeLowPrecision
  63. : 0;
  64. Flags |= m_bEnableDoubleExtensions
  65. ? hlsl::DXIL::ShaderFeatureInfo_11_1_DoubleExtensions
  66. : 0;
  67. Flags |= m_bWaveOps ? hlsl::DXIL::ShaderFeatureInfo_WaveOps : 0;
  68. Flags |= m_bInt64Ops ? hlsl::DXIL::ShaderFeatureInfo_Int64Ops : 0;
  69. Flags |= m_bROVS ? hlsl::DXIL::ShaderFeatureInfo_ROVs : 0;
  70. Flags |=
  71. m_bViewportAndRTArrayIndex
  72. ? hlsl::DXIL::
  73. ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer
  74. : 0;
  75. Flags |= m_bInnerCoverage ? hlsl::DXIL::ShaderFeatureInfo_InnerCoverage : 0;
  76. Flags |= m_bStencilRef ? hlsl::DXIL::ShaderFeatureInfo_StencilRef : 0;
  77. Flags |= m_bTiledResources ? hlsl::DXIL::ShaderFeatureInfo_TiledResources : 0;
  78. Flags |=
  79. m_bEnableMSAD ? hlsl::DXIL::ShaderFeatureInfo_11_1_ShaderExtensions : 0;
  80. Flags |=
  81. m_bCSRawAndStructuredViaShader4X
  82. ? hlsl::DXIL::
  83. ShaderFeatureInfo_ComputeShadersPlusRawAndStructuredBuffersViaShader4X
  84. : 0;
  85. Flags |=
  86. m_UAVsAtEveryStage ? hlsl::DXIL::ShaderFeatureInfo_UAVsAtEveryStage : 0;
  87. Flags |= m_b64UAVs ? hlsl::DXIL::ShaderFeatureInfo_64UAVs : 0;
  88. Flags |= m_bLevel9ComparisonFiltering
  89. ? hlsl::DXIL::ShaderFeatureInfo_LEVEL9ComparisonFiltering
  90. : 0;
  91. Flags |= m_bUAVLoadAdditionalFormats
  92. ? hlsl::DXIL::ShaderFeatureInfo_TypedUAVLoadAdditionalFormats
  93. : 0;
  94. Flags |= m_bViewID ? hlsl::DXIL::ShaderFeatureInfo_ViewID : 0;
  95. Flags |= m_bBarycentrics ? hlsl::DXIL::ShaderFeatureInfo_Barycentrics : 0;
  96. Flags |= m_bShadingRate ? hlsl::DXIL::ShaderFeatureInfo_ShadingRate : 0;
  97. Flags |= m_bRaytracingTier1_1 ? hlsl::DXIL::ShaderFeatureInfo_Raytracing_Tier_1_1 : 0;
  98. Flags |= m_bSamplerFeedback ? hlsl::DXIL::ShaderFeatureInfo_SamplerFeedback : 0;
  99. return Flags;
  100. }
  101. uint64_t ShaderFlags::GetShaderFlagsRaw() const {
  102. union Cast {
  103. Cast(const ShaderFlags &flags) {
  104. shaderFlags = flags;
  105. }
  106. ShaderFlags shaderFlags;
  107. uint64_t rawData;
  108. };
  109. static_assert(sizeof(uint64_t) == sizeof(ShaderFlags),
  110. "size must match to make sure no undefined bits when cast");
  111. Cast rawCast(*this);
  112. return rawCast.rawData;
  113. }
  114. void ShaderFlags::SetShaderFlagsRaw(uint64_t data) {
  115. union Cast {
  116. Cast(uint64_t data) {
  117. rawData = data;
  118. }
  119. ShaderFlags shaderFlags;
  120. uint64_t rawData;
  121. };
  122. Cast rawCast(data);
  123. *this = rawCast.shaderFlags;
  124. }
  125. uint64_t ShaderFlags::GetShaderFlagsRawForCollection() {
  126. // This should be all the flags that can be set by DxilModule::CollectShaderFlags.
  127. ShaderFlags Flags;
  128. Flags.SetEnableDoublePrecision(true);
  129. Flags.SetInt64Ops(true);
  130. Flags.SetLowPrecisionPresent(true);
  131. Flags.SetEnableDoubleExtensions(true);
  132. Flags.SetWaveOps(true);
  133. Flags.SetTiledResources(true);
  134. Flags.SetEnableMSAD(true);
  135. Flags.SetUAVLoadAdditionalFormats(true);
  136. Flags.SetStencilRef(true);
  137. Flags.SetInnerCoverage(true);
  138. Flags.SetViewportAndRTArrayIndex(true);
  139. Flags.Set64UAVs(true);
  140. Flags.SetUAVsAtEveryStage(true);
  141. Flags.SetEnableRawAndStructuredBuffers(true);
  142. Flags.SetCSRawAndStructuredViaShader4X(true);
  143. Flags.SetViewID(true);
  144. Flags.SetBarycentrics(true);
  145. Flags.SetShadingRate(true);
  146. Flags.SetRaytracingTier1_1(true);
  147. Flags.SetSamplerFeedback(true);
  148. return Flags.GetShaderFlagsRaw();
  149. }
  150. unsigned ShaderFlags::GetGlobalFlags() const {
  151. unsigned Flags = 0;
  152. Flags |= m_bDisableOptimizations ? DXIL::kDisableOptimizations : 0;
  153. Flags |= m_bDisableMathRefactoring ? DXIL::kDisableMathRefactoring : 0;
  154. Flags |= m_bEnableDoublePrecision ? DXIL::kEnableDoublePrecision : 0;
  155. Flags |= m_bForceEarlyDepthStencil ? DXIL::kForceEarlyDepthStencil : 0;
  156. Flags |= m_bEnableRawAndStructuredBuffers ? DXIL::kEnableRawAndStructuredBuffers : 0;
  157. Flags |= m_bLowPrecisionPresent && !m_bUseNativeLowPrecision? DXIL::kEnableMinPrecision : 0;
  158. Flags |= m_bEnableDoubleExtensions ? DXIL::kEnableDoubleExtensions : 0;
  159. Flags |= m_bEnableMSAD ? DXIL::kEnableMSAD : 0;
  160. Flags |= m_bAllResourcesBound ? DXIL::kAllResourcesBound : 0;
  161. return Flags;
  162. }
  163. // Given a CreateHandle call, returns arbitrary ConstantInt rangeID
  164. // Note: HLSL is currently assuming that rangeID is a constant value, but this code is assuming
  165. // that it can be either constant, phi node, or select instruction
  166. static ConstantInt *GetArbitraryConstantRangeID(CallInst *handleCall) {
  167. Value *rangeID =
  168. handleCall->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  169. ConstantInt *ConstantRangeID = dyn_cast<ConstantInt>(rangeID);
  170. while (ConstantRangeID == nullptr) {
  171. if (ConstantInt *CI = dyn_cast<ConstantInt>(rangeID)) {
  172. ConstantRangeID = CI;
  173. } else if (PHINode *PN = dyn_cast<PHINode>(rangeID)) {
  174. rangeID = PN->getIncomingValue(0);
  175. } else if (SelectInst *SI = dyn_cast<SelectInst>(rangeID)) {
  176. rangeID = SI->getTrueValue();
  177. } else {
  178. return nullptr;
  179. }
  180. }
  181. return ConstantRangeID;
  182. }
  183. // Given a handle type, find an arbitrary call instructions to create handle
  184. static CallInst *FindCallToCreateHandle(Value *handleType) {
  185. Value *curVal = handleType;
  186. CallInst *CI = dyn_cast<CallInst>(handleType);
  187. while (CI == nullptr) {
  188. if (PHINode *PN = dyn_cast<PHINode>(curVal)) {
  189. curVal = PN->getIncomingValue(0);
  190. }
  191. else if (SelectInst *SI = dyn_cast<SelectInst>(curVal)) {
  192. curVal = SI->getTrueValue();
  193. }
  194. else {
  195. return nullptr;
  196. }
  197. CI = dyn_cast<CallInst>(curVal);
  198. }
  199. return CI;
  200. }
  201. ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
  202. const hlsl::DxilModule *M) {
  203. ShaderFlags flag;
  204. // Module level options
  205. flag.SetUseNativeLowPrecision(!M->GetUseMinPrecision());
  206. flag.SetDisableOptimizations(M->GetDisableOptimization());
  207. flag.SetAllResourcesBound(M->GetAllResourcesBound());
  208. bool hasDouble = false;
  209. // ddiv dfma drcp d2i d2u i2d u2d.
  210. // fma has dxil op. Others should check IR instruction div/cast.
  211. bool hasDoubleExtension = false;
  212. bool has64Int = false;
  213. bool has16 = false;
  214. bool hasWaveOps = false;
  215. bool hasCheckAccessFully = false;
  216. bool hasMSAD = false;
  217. bool hasStencilRef = false;
  218. bool hasInnerCoverage = false;
  219. bool hasViewID = false;
  220. bool hasMulticomponentUAVLoads = false;
  221. bool hasViewportOrRTArrayIndex = false;
  222. bool hasShadingRate = false;
  223. bool hasSamplerFeedback = false;
  224. bool hasRaytracingTier1_1 = false;
  225. // Try to maintain compatibility with a v1.0 validator if that's what we have.
  226. uint32_t valMajor, valMinor;
  227. M->GetValidatorVersion(valMajor, valMinor);
  228. bool hasMulticomponentUAVLoadsBackCompat = valMajor == 1 && valMinor == 0;
  229. bool hasViewportOrRTArrayIndexBackCombat = valMajor == 1 && valMinor < 4;
  230. Type *int16Ty = Type::getInt16Ty(F->getContext());
  231. Type *int64Ty = Type::getInt64Ty(F->getContext());
  232. for (const BasicBlock &BB : F->getBasicBlockList()) {
  233. for (const Instruction &I : BB.getInstList()) {
  234. // Skip none dxil function call.
  235. if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
  236. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  237. continue;
  238. }
  239. Type *Ty = I.getType();
  240. bool isDouble = Ty->isDoubleTy();
  241. bool isHalf = Ty->isHalfTy();
  242. bool isInt16 = Ty == int16Ty;
  243. bool isInt64 = Ty == int64Ty;
  244. if (isa<ExtractElementInst>(&I) ||
  245. isa<InsertElementInst>(&I))
  246. continue;
  247. for (Value *operand : I.operands()) {
  248. Type *Ty = operand->getType();
  249. isDouble |= Ty->isDoubleTy();
  250. isHalf |= Ty->isHalfTy();
  251. isInt16 |= Ty == int16Ty;
  252. isInt64 |= Ty == int64Ty;
  253. }
  254. if (isDouble) {
  255. hasDouble = true;
  256. switch (I.getOpcode()) {
  257. case Instruction::FDiv:
  258. case Instruction::UIToFP:
  259. case Instruction::SIToFP:
  260. case Instruction::FPToUI:
  261. case Instruction::FPToSI:
  262. hasDoubleExtension = true;
  263. break;
  264. }
  265. }
  266. has16 |= isHalf;
  267. has16 |= isInt16;
  268. has64Int |= isInt64;
  269. if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
  270. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  271. continue;
  272. Value *opcodeArg = CI->getArgOperand(DXIL::OperandIndex::kOpcodeIdx);
  273. ConstantInt *opcodeConst = dyn_cast<ConstantInt>(opcodeArg);
  274. DXASSERT(opcodeConst, "DXIL opcode arg must be immediate");
  275. unsigned opcode = opcodeConst->getLimitedValue();
  276. DXASSERT(opcode < static_cast<unsigned>(DXIL::OpCode::NumOpCodes),
  277. "invalid DXIL opcode");
  278. DXIL::OpCode dxilOp = static_cast<DXIL::OpCode>(opcode);
  279. if (hlsl::OP::IsDxilOpWave(dxilOp))
  280. hasWaveOps = true;
  281. switch (dxilOp) {
  282. case DXIL::OpCode::CheckAccessFullyMapped:
  283. hasCheckAccessFully = true;
  284. break;
  285. case DXIL::OpCode::Msad:
  286. hasMSAD = true;
  287. break;
  288. case DXIL::OpCode::BufferLoad:
  289. case DXIL::OpCode::TextureLoad: {
  290. if (hasMulticomponentUAVLoads) continue;
  291. // This is the old-style computation (overestimating requirements).
  292. Value *resHandle = CI->getArgOperand(DXIL::OperandIndex::kBufferStoreHandleOpIdx);
  293. CallInst *handleCall = FindCallToCreateHandle(resHandle);
  294. // Check if this is a library handle or general create handle
  295. if (handleCall) {
  296. ConstantInt *HandleOpCodeConst = cast<ConstantInt>(
  297. handleCall->getArgOperand(DXIL::OperandIndex::kOpcodeIdx));
  298. DXIL::OpCode handleOp = static_cast<DXIL::OpCode>(HandleOpCodeConst->getLimitedValue());
  299. if (handleOp == DXIL::OpCode::CreateHandle) {
  300. if (ConstantInt *resClassArg =
  301. dyn_cast<ConstantInt>(handleCall->getArgOperand(
  302. DXIL::OperandIndex::kCreateHandleResClassOpIdx))) {
  303. DXIL::ResourceClass resClass = static_cast<DXIL::ResourceClass>(
  304. resClassArg->getLimitedValue());
  305. if (resClass == DXIL::ResourceClass::UAV) {
  306. // Validator 1.0 assumes that all uav load is multi component load.
  307. if (hasMulticomponentUAVLoadsBackCompat) {
  308. hasMulticomponentUAVLoads = true;
  309. continue;
  310. }
  311. else {
  312. ConstantInt *rangeID = GetArbitraryConstantRangeID(handleCall);
  313. if (rangeID) {
  314. DxilResource resource = M->GetUAV(rangeID->getLimitedValue());
  315. if ((resource.IsTypedBuffer() ||
  316. resource.IsAnyTexture()) &&
  317. !dxilutil::IsResourceSingleComponent(resource.GetRetType())) {
  318. hasMulticomponentUAVLoads = true;
  319. }
  320. }
  321. }
  322. }
  323. }
  324. else {
  325. DXASSERT(false, "Resource class must be constant.");
  326. }
  327. }
  328. else if (handleOp == DXIL::OpCode::CreateHandleForLib) {
  329. // If library handle, find DxilResource by checking the name
  330. if (LoadInst *LI = dyn_cast<LoadInst>(handleCall->getArgOperand(
  331. DXIL::OperandIndex::
  332. kCreateHandleForLibResOpIdx))) {
  333. Value *resType = LI->getOperand(0);
  334. for (auto &&res : M->GetUAVs()) {
  335. if (res->GetGlobalSymbol() == resType) {
  336. if ((res->IsTypedBuffer() || res->IsAnyTexture()) &&
  337. !dxilutil::IsResourceSingleComponent(res->GetRetType())) {
  338. hasMulticomponentUAVLoads = true;
  339. }
  340. }
  341. }
  342. }
  343. } else if (handleOp == DXIL::OpCode::AnnotateHandle) {
  344. DxilInst_AnnotateHandle annotateHandle(handleCall);
  345. Type *ResPropTy = M->GetOP()->GetResourcePropertiesType();
  346. DxilResourceProperties RP =
  347. resource_helper::loadFromAnnotateHandle(
  348. annotateHandle, ResPropTy, *M->GetShaderModel());
  349. if (RP.Class == DXIL::ResourceClass::UAV) {
  350. // Validator 1.0 assumes that all uav load is multi component
  351. // load.
  352. if (hasMulticomponentUAVLoadsBackCompat) {
  353. hasMulticomponentUAVLoads = true;
  354. continue;
  355. } else {
  356. if (DXIL::IsTyped(RP.Kind) &&
  357. !RP.Typed.SingleComponent)
  358. hasMulticomponentUAVLoads = true;
  359. }
  360. }
  361. }
  362. }
  363. } break;
  364. case DXIL::OpCode::Fma:
  365. hasDoubleExtension |= isDouble;
  366. break;
  367. case DXIL::OpCode::InnerCoverage:
  368. hasInnerCoverage = true;
  369. break;
  370. case DXIL::OpCode::ViewID:
  371. hasViewID = true;
  372. break;
  373. case DXIL::OpCode::AllocateRayQuery:
  374. case DXIL::OpCode::GeometryIndex:
  375. hasRaytracingTier1_1 = true;
  376. break;
  377. default:
  378. // Normal opcodes.
  379. break;
  380. }
  381. }
  382. }
  383. }
  384. // If this function is a shader, add flags based on signatures
  385. if (M->HasDxilEntryProps(F)) {
  386. const DxilEntryProps &entryProps = M->GetDxilEntryProps(F);
  387. // Val ver < 1.4 has a bug where input case was always clobbered by the
  388. // output check. The only case where it made a difference such that an
  389. // incorrect flag would be set was for the HS and DS input cases.
  390. // It was also checking PS input and output, but PS output could not have
  391. // the semantic, and since it was clobbering the result, it would always
  392. // clear it. Since this flag should not be set for PS at all,
  393. // it produced the correct result for PS by accident.
  394. bool checkInputRTArrayIndex = entryProps.props.IsGS();
  395. if (!hasViewportOrRTArrayIndexBackCombat)
  396. checkInputRTArrayIndex |= entryProps.props.IsDS() ||
  397. entryProps.props.IsHS();
  398. bool checkOutputRTArrayIndex =
  399. entryProps.props.IsVS() || entryProps.props.IsDS() ||
  400. entryProps.props.IsHS();
  401. for (auto &&E : entryProps.sig.InputSignature.GetElements()) {
  402. switch (E->GetKind()) {
  403. case Semantic::Kind::ViewPortArrayIndex:
  404. case Semantic::Kind::RenderTargetArrayIndex:
  405. if (checkInputRTArrayIndex)
  406. hasViewportOrRTArrayIndex = true;
  407. break;
  408. case Semantic::Kind::ShadingRate:
  409. hasShadingRate = true;
  410. break;
  411. default:
  412. break;
  413. }
  414. }
  415. for (auto &&E : entryProps.sig.OutputSignature.GetElements()) {
  416. switch (E->GetKind()) {
  417. case Semantic::Kind::ViewPortArrayIndex:
  418. case Semantic::Kind::RenderTargetArrayIndex:
  419. if (checkOutputRTArrayIndex)
  420. hasViewportOrRTArrayIndex = true;
  421. break;
  422. case Semantic::Kind::StencilRef:
  423. if (entryProps.props.IsPS())
  424. hasStencilRef = true;
  425. break;
  426. case Semantic::Kind::InnerCoverage:
  427. if (entryProps.props.IsPS())
  428. hasInnerCoverage = true;
  429. break;
  430. case Semantic::Kind::ShadingRate:
  431. hasShadingRate = true;
  432. break;
  433. default:
  434. break;
  435. }
  436. }
  437. }
  438. if (!hasRaytracingTier1_1) {
  439. if (const DxilSubobjects *pSubobjects = M->GetSubobjects()) {
  440. for (const auto &it : pSubobjects->GetSubobjects()) {
  441. switch (it.second->GetKind()) {
  442. case DXIL::SubobjectKind::RaytracingPipelineConfig1:
  443. hasRaytracingTier1_1 = true;
  444. break;
  445. case DXIL::SubobjectKind::StateObjectConfig: {
  446. uint32_t Flags;
  447. if (it.second->GetStateObjectConfig(Flags) &&
  448. ((Flags & ~(unsigned)DXIL::StateObjectFlags::ValidMask_1_4) != 0))
  449. hasRaytracingTier1_1 = true;
  450. } break;
  451. default:
  452. break;
  453. }
  454. if (hasRaytracingTier1_1)
  455. break;
  456. }
  457. }
  458. }
  459. flag.SetEnableDoublePrecision(hasDouble);
  460. flag.SetStencilRef(hasStencilRef);
  461. flag.SetInnerCoverage(hasInnerCoverage);
  462. flag.SetInt64Ops(has64Int);
  463. flag.SetLowPrecisionPresent(has16);
  464. flag.SetEnableDoubleExtensions(hasDoubleExtension);
  465. flag.SetWaveOps(hasWaveOps);
  466. flag.SetTiledResources(hasCheckAccessFully);
  467. flag.SetEnableMSAD(hasMSAD);
  468. flag.SetUAVLoadAdditionalFormats(hasMulticomponentUAVLoads);
  469. flag.SetViewID(hasViewID);
  470. flag.SetViewportAndRTArrayIndex(hasViewportOrRTArrayIndex);
  471. flag.SetShadingRate(hasShadingRate);
  472. flag.SetSamplerFeedback(hasSamplerFeedback);
  473. flag.SetRaytracingTier1_1(hasRaytracingTier1_1);
  474. return flag;
  475. }
  476. void ShaderFlags::CombineShaderFlags(const ShaderFlags &other) {
  477. SetShaderFlagsRaw(GetShaderFlagsRaw() | other.GetShaderFlagsRaw());
  478. }