/home/runner/work/DirectXShaderCompiler/DirectXShaderCompiler/lib/DXIL/DxilResourceProperties.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /////////////////////////////////////////////////////////////////////////////// |
2 | | // // |
3 | | // DxilResourceProperites.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 | | |
10 | | #include "dxc/DXIL/DxilResourceProperties.h" |
11 | | #include "dxc/DXIL/DxilCBuffer.h" |
12 | | #include "dxc/DXIL/DxilInstructions.h" |
13 | | #include "dxc/DXIL/DxilOperations.h" |
14 | | #include "dxc/DXIL/DxilResource.h" |
15 | | #include "dxc/DXIL/DxilResourceBase.h" |
16 | | #include "dxc/DXIL/DxilSampler.h" |
17 | | #include "dxc/DXIL/DxilShaderModel.h" |
18 | | #include "dxc/DXIL/DxilUtil.h" |
19 | | #include "llvm/IR/Constant.h" |
20 | | #include "llvm/IR/Constants.h" |
21 | | #include "llvm/IR/DerivedTypes.h" |
22 | | |
23 | | using namespace llvm; |
24 | | |
25 | | namespace hlsl { |
26 | | |
27 | 1.81M | DxilResourceProperties::DxilResourceProperties() { |
28 | 1.81M | RawDword0 = 0; |
29 | 1.81M | RawDword1 = 0; |
30 | 1.81M | Basic.ResourceKind = (uint8_t)DXIL::ResourceKind::Invalid; |
31 | 1.81M | } |
32 | 110k | bool DxilResourceProperties::isUAV() const { return Basic.IsUAV; } |
33 | 452k | bool DxilResourceProperties::isValid() const { |
34 | 452k | return getResourceKind() != DXIL::ResourceKind::Invalid; |
35 | 452k | } |
36 | | |
37 | 288k | DXIL::ResourceClass DxilResourceProperties::getResourceClass() const { |
38 | 288k | switch (static_cast<DXIL::ResourceKind>(Basic.ResourceKind)) { |
39 | 212k | default: |
40 | 212k | return Basic.IsUAV ? DXIL::ResourceClass::UAV144k : DXIL::ResourceClass::SRV67.5k ; |
41 | 57.1k | case DXIL::ResourceKind::CBuffer: |
42 | 57.1k | return DXIL::ResourceClass::CBuffer; |
43 | 18.8k | case DXIL::ResourceKind::Sampler: |
44 | 18.8k | return DXIL::ResourceClass::Sampler; |
45 | 114 | case DXIL::ResourceKind::Invalid: |
46 | 114 | return DXIL::ResourceClass::Invalid; |
47 | 288k | } |
48 | 288k | } |
49 | | |
50 | 770k | DXIL::ResourceKind DxilResourceProperties::getResourceKind() const { |
51 | 770k | return static_cast<DXIL::ResourceKind>(Basic.ResourceKind); |
52 | 770k | } |
53 | | |
54 | 0 | void DxilResourceProperties::setResourceKind(DXIL::ResourceKind RK) { |
55 | 0 | Basic.ResourceKind = (uint8_t)RK; |
56 | 0 | } |
57 | | |
58 | 2.21k | DXIL::ComponentType DxilResourceProperties::getCompType() const { |
59 | 2.21k | return static_cast<DXIL::ComponentType>(Typed.CompType); |
60 | 2.21k | } |
61 | | |
62 | 0 | unsigned DxilResourceProperties::getElementStride() const { |
63 | 0 | switch (getResourceKind()) { |
64 | 0 | default: |
65 | 0 | return CompType(getCompType()).GetSizeInBits() / 8; |
66 | 0 | case DXIL::ResourceKind::RawBuffer: |
67 | 0 | return 1; |
68 | 0 | case DXIL::ResourceKind::StructuredBuffer: |
69 | 0 | return StructStrideInBytes; |
70 | 0 | case DXIL::ResourceKind::CBuffer: |
71 | 0 | case DXIL::ResourceKind::Sampler: |
72 | 0 | return 0; |
73 | 0 | } |
74 | 0 | } |
75 | | |
76 | | bool DxilResourceProperties::operator==( |
77 | 0 | const DxilResourceProperties &RP) const { |
78 | 0 | return RawDword0 == RP.RawDword0 && RawDword1 == RP.RawDword1; |
79 | 0 | } |
80 | | |
81 | | bool DxilResourceProperties::operator!=( |
82 | 0 | const DxilResourceProperties &RP) const { |
83 | 0 | return !(*this == RP); |
84 | 0 | } |
85 | | |
86 | | namespace resource_helper { |
87 | | |
88 | | // The constant is as struct with int32 fields. |
89 | | // ShaderModel 6.6 has 2 fields. |
90 | | Constant *getAsConstant(const DxilResourceProperties &RP, Type *Ty, |
91 | 61.9k | const ShaderModel &) { |
92 | 61.9k | StructType *ST = cast<StructType>(Ty); |
93 | 61.9k | switch (ST->getNumElements()) { |
94 | 61.9k | case 2: { |
95 | 61.9k | Constant *RawDwords[] = { |
96 | 61.9k | ConstantInt::get(ST->getElementType(0), RP.RawDword0), |
97 | 61.9k | ConstantInt::get(ST->getElementType(1), RP.RawDword1)}; |
98 | 61.9k | return ConstantStruct::get(ST, RawDwords); |
99 | 0 | } break; |
100 | 0 | default: |
101 | 0 | return nullptr; |
102 | 0 | break; |
103 | 61.9k | } |
104 | 0 | return nullptr; |
105 | 61.9k | } |
106 | | |
107 | 114k | DxilResourceProperties loadPropsFromConstant(const Constant &C) { |
108 | 114k | DxilResourceProperties RP; |
109 | | |
110 | | // Ty Should match C.getType(). |
111 | 114k | Type *Ty = C.getType(); |
112 | 114k | StructType *ST = cast<StructType>(Ty); |
113 | 114k | switch (ST->getNumElements()) { |
114 | 114k | case 2: { |
115 | 114k | if (isa<ConstantAggregateZero>(&C)) { |
116 | 0 | RP.RawDword0 = 0; |
117 | 0 | RP.RawDword1 = 0; |
118 | 114k | } else { |
119 | 114k | const ConstantStruct *CS = cast<ConstantStruct>(&C); |
120 | 114k | const Constant *RawDword0 = CS->getOperand(0); |
121 | 114k | const Constant *RawDword1 = CS->getOperand(1); |
122 | 114k | RP.RawDword0 = cast<ConstantInt>(RawDword0)->getLimitedValue(); |
123 | 114k | RP.RawDword1 = cast<ConstantInt>(RawDword1)->getLimitedValue(); |
124 | 114k | } |
125 | 114k | } break; |
126 | 0 | default: |
127 | 0 | break; |
128 | 114k | } |
129 | 114k | return RP; |
130 | 114k | } |
131 | | |
132 | | DxilResourceProperties |
133 | | loadPropsFromAnnotateHandle(DxilInst_AnnotateHandle &annotateHandle, |
134 | 65.0k | const ShaderModel &SM) { |
135 | 65.0k | Constant *ResProp = cast<Constant>(annotateHandle.get_props()); |
136 | 65.0k | return loadPropsFromConstant(*ResProp); |
137 | 65.0k | } |
138 | | |
139 | 159k | DxilResourceProperties loadPropsFromResourceBase(const DxilResourceBase *Res) { |
140 | | |
141 | 159k | DxilResourceProperties RP; |
142 | 159k | if (!Res) { |
143 | 0 | return RP; |
144 | 0 | } |
145 | | |
146 | 159k | auto SetResProperties = [&RP](const DxilResource &Res) { |
147 | 107k | switch (Res.GetKind()) { |
148 | 13.7k | default: |
149 | 13.7k | break; |
150 | 13.7k | case DXIL::ResourceKind::FeedbackTexture2D: |
151 | 692 | case DXIL::ResourceKind::FeedbackTexture2DArray: |
152 | 692 | RP.SamplerFeedbackType = Res.GetSamplerFeedbackType(); |
153 | 692 | break; |
154 | 2.44k | case DXIL::ResourceKind::RTAccelerationStructure: |
155 | | |
156 | 2.44k | break; |
157 | 38.1k | case DXIL::ResourceKind::StructuredBuffer: { |
158 | 38.1k | RP.StructStrideInBytes = Res.GetElementStride(); |
159 | 38.1k | RP.Basic.BaseAlignLog2 = Res.GetBaseAlignLog2(); |
160 | 38.1k | break; |
161 | 386 | } |
162 | 1.30k | case DXIL::ResourceKind::Texture2DMS: |
163 | 2.12k | case DXIL::ResourceKind::Texture2DMSArray: |
164 | 14.7k | case DXIL::ResourceKind::TypedBuffer: |
165 | 20.9k | case DXIL::ResourceKind::Texture1D: |
166 | 48.8k | case DXIL::ResourceKind::Texture2D: |
167 | 49.1k | case DXIL::ResourceKind::TextureCube: |
168 | 49.5k | case DXIL::ResourceKind::Texture1DArray: |
169 | 51.0k | case DXIL::ResourceKind::Texture2DArray: |
170 | 51.3k | case DXIL::ResourceKind::TextureCubeArray: |
171 | 52.0k | case DXIL::ResourceKind::Texture3D: |
172 | 52.0k | Type *Ty = Res.GetRetType(); |
173 | 52.0k | RP.Typed.CompCount = dxilutil::GetResourceComponentCount(Ty); |
174 | 52.0k | RP.Typed.CompType = (uint8_t)Res.GetCompType().GetKind(); |
175 | 52.0k | RP.Typed.SampleCount = (uint8_t)Res.GetSampleCount(); |
176 | 52.0k | break; |
177 | 107k | } |
178 | 107k | }; |
179 | | |
180 | 159k | switch (Res->GetClass()) { |
181 | 13.9k | case DXIL::ResourceClass::Invalid: |
182 | 13.9k | return RP; |
183 | 52.4k | case DXIL::ResourceClass::SRV: { |
184 | 52.4k | const DxilResource *SRV = (const DxilResource *)(Res); |
185 | 52.4k | RP.Basic.ResourceKind = (uint8_t)Res->GetKind(); |
186 | 52.4k | SetResProperties(*SRV); |
187 | 52.4k | } break; |
188 | 54.7k | case DXIL::ResourceClass::UAV: { |
189 | 54.7k | const DxilResource *UAV = (const DxilResource *)(Res); |
190 | 54.7k | RP.Basic.IsUAV = true; |
191 | 54.7k | RP.Basic.ResourceKind = (uint8_t)Res->GetKind(); |
192 | 54.7k | RP.Basic.IsGloballyCoherent = UAV->IsGloballyCoherent(); |
193 | 54.7k | RP.Basic.IsReorderCoherent = UAV->IsReorderCoherent(); |
194 | 54.7k | RP.Basic.SamplerCmpOrHasCounter = UAV->HasCounter(); |
195 | 54.7k | RP.Basic.IsROV = UAV->IsROV(); |
196 | 54.7k | SetResProperties(*UAV); |
197 | 54.7k | } break; |
198 | 8.08k | case DXIL::ResourceClass::Sampler: { |
199 | 8.08k | RP.Basic.ResourceKind = (uint8_t)Res->GetKind(); |
200 | 8.08k | const DxilSampler *Sampler = (const DxilSampler *)Res; |
201 | 8.08k | if (Sampler->GetSamplerKind() == DXIL::SamplerKind::Comparison) |
202 | 774 | RP.Basic.SamplerCmpOrHasCounter = true; |
203 | 7.31k | else if (Sampler->GetSamplerKind() == DXIL::SamplerKind::Invalid) |
204 | 4 | RP.Basic.ResourceKind = (uint8_t)DXIL::ResourceKind::Invalid; |
205 | 8.08k | } break; |
206 | 30.6k | case DXIL::ResourceClass::CBuffer: { |
207 | 30.6k | RP.Basic.ResourceKind = (uint8_t)Res->GetKind(); |
208 | 30.6k | const DxilCBuffer *CB = (const DxilCBuffer *)Res; |
209 | 30.6k | RP.CBufferSizeInBytes = CB->GetSize(); |
210 | 30.6k | } break; |
211 | 159k | } |
212 | 145k | return RP; |
213 | 159k | } |
214 | | |
215 | | // Merge 2 props on a chain of annotateHandle. |
216 | | DxilResourceProperties tryMergeProps(DxilResourceProperties curProps, |
217 | 34 | DxilResourceProperties prevProps) { |
218 | 34 | DxilResourceProperties props; |
219 | 34 | if (curProps.Basic.ResourceKind != prevProps.Basic.ResourceKind) { |
220 | 0 | return props; |
221 | 0 | } |
222 | | |
223 | 34 | if (curProps.Basic.IsUAV != prevProps.Basic.IsUAV) |
224 | 0 | return props; |
225 | | |
226 | 34 | if (curProps.Basic.IsUAV) { |
227 | | // Or hasCounter. |
228 | 34 | if (curProps.Basic.SamplerCmpOrHasCounter != |
229 | 34 | prevProps.Basic.SamplerCmpOrHasCounter) { |
230 | 0 | curProps.Basic.SamplerCmpOrHasCounter = true; |
231 | 0 | prevProps.Basic.SamplerCmpOrHasCounter = true; |
232 | 0 | } |
233 | | // curProps follow prevProps. |
234 | 34 | if (curProps.Basic.IsGloballyCoherent != |
235 | 34 | prevProps.Basic.IsGloballyCoherent) { |
236 | 32 | curProps.Basic.IsGloballyCoherent = prevProps.Basic.IsGloballyCoherent; |
237 | 32 | } |
238 | 34 | if (curProps.Basic.IsReorderCoherent != prevProps.Basic.IsReorderCoherent) |
239 | 2 | curProps.Basic.IsReorderCoherent = prevProps.Basic.IsReorderCoherent; |
240 | 34 | } |
241 | | |
242 | 34 | if (curProps.Basic.ResourceKind == (uint8_t)DXIL::ResourceKind::CBuffer) { |
243 | | // use max cbuffer size. |
244 | 0 | if (curProps.CBufferSizeInBytes != prevProps.CBufferSizeInBytes) { |
245 | 0 | curProps.CBufferSizeInBytes = |
246 | 0 | std::max(curProps.CBufferSizeInBytes, prevProps.CBufferSizeInBytes); |
247 | 0 | prevProps.CBufferSizeInBytes = curProps.CBufferSizeInBytes; |
248 | 0 | } |
249 | 0 | } |
250 | | |
251 | | // If still not match after merge. |
252 | | // return null. |
253 | 34 | if (curProps.RawDword0 != prevProps.RawDword0 || |
254 | 34 | curProps.RawDword1 != prevProps.RawDword1) |
255 | 0 | return props; |
256 | 34 | return curProps; |
257 | 34 | } |
258 | | // Merge 2 props on a chain of annotateHandle. |
259 | | Constant *tryMergeProps(const Constant *curPropsConst, |
260 | | const Constant *prevPropsConst, Type *Ty, |
261 | 50 | const ShaderModel &SM) { |
262 | 50 | if (curPropsConst == prevPropsConst) |
263 | 16 | return const_cast<Constant *>(curPropsConst); |
264 | | |
265 | 34 | DxilResourceProperties curProps = loadPropsFromConstant(*curPropsConst); |
266 | 34 | DxilResourceProperties prevProps = loadPropsFromConstant(*prevPropsConst); |
267 | | |
268 | 34 | DxilResourceProperties props = tryMergeProps(curProps, prevProps); |
269 | | |
270 | 34 | if (!props.isValid()) { |
271 | 0 | return nullptr; |
272 | 0 | } |
273 | | |
274 | 34 | return getAsConstant(props, Ty, SM); |
275 | 34 | } |
276 | | |
277 | | } // namespace resource_helper |
278 | | } // namespace hlsl |