Coverage Report

Created: 2026-04-01 02:40

/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