Skip to content

Commit

Permalink
Set the resource kind as u32 for boolean resources (#7116)
Browse files Browse the repository at this point in the history
It was producing a validation error previously because they are
represented as u32 and i1 is not valid for output resources. This
preserves the cmp conversions for values read from the resource, but
satisfies the validation requirement. Performs some incidental
consolidation of types that are represented as u32.

Includes a couple incidental NFC fixes as well:

Moves lit filecheck tests into the correct directory. I got CodeGenHLSL
and CodeGenDXIL mixed up.

Remove dead array handing code. The array type checks were for a type
extracted from a vector. Arrays cannot be elements of vectors. This is
leftover from when the type came from more sources. The code shows as
never executed in coverage.

Related to #7079
  • Loading branch information
pow2clk authored Feb 25, 2025
1 parent d5951b7 commit b317f1b
Show file tree
Hide file tree
Showing 8 changed files with 498 additions and 96 deletions.
13 changes: 1 addition & 12 deletions lib/DXIL/DxilResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,7 @@ DxilResource::DxilResource()

CompType DxilResource::GetCompType() const { return m_CompType; }

void DxilResource::SetCompType(const CompType CT) {
// Translate packed types to u32
switch (CT.GetKind()) {
case CompType::Kind::PackedS8x32:
case CompType::Kind::PackedU8x32:
m_CompType = CompType::getU32();
break;
default:
m_CompType = CT;
break;
}
}
void DxilResource::SetCompType(const CompType CT) { m_CompType = CT; }

Type *DxilResource::GetRetType() const {
Type *Ty = GetHLSLType()->getPointerElementType();
Expand Down
123 changes: 43 additions & 80 deletions lib/HLSL/HLOperationLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8368,96 +8368,59 @@ void TranslateStructBufSubscriptUser(Instruction *user, Value *handle,
baseOffset, status, OP, DL);
}
} else if (isa<LoadInst>(user) || isa<StoreInst>(user)) {
LoadInst *ldInst = dyn_cast<LoadInst>(user);
StoreInst *stInst = dyn_cast<StoreInst>(user);
LoadInst *LdInst = dyn_cast<LoadInst>(user);
StoreInst *StInst = dyn_cast<StoreInst>(user);

Type *Ty = isa<LoadInst>(user) ? ldInst->getType()
: stInst->getValueOperand()->getType();
Type *Ty = isa<LoadInst>(user) ? LdInst->getType()
: StInst->getValueOperand()->getType();
Type *pOverloadTy = Ty->getScalarType();
Value *offset = baseOffset;
unsigned arraySize = 1;
Value *eltSize = nullptr;
Value *Offset = baseOffset;

if (pOverloadTy->isArrayTy()) {
arraySize = pOverloadTy->getArrayNumElements();
eltSize = OP->GetU32Const(
DL.getTypeAllocSize(pOverloadTy->getArrayElementType()));
if (LdInst) {
unsigned NumComponents = 0;
Value *NewLd = nullptr;
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
NumComponents = VTy->getNumElements();
else
NumComponents = 1;

pOverloadTy = pOverloadTy->getArrayElementType()->getScalarType();
}
if (ResKind == HLResource::Kind::TypedBuffer) {
// Typed buffer cannot have offsets, they must be loaded all at once
ResRetValueArray ResRet = GenerateTypedBufferLoad(
handle, pOverloadTy, bufIdx, status, OP, Builder);

if (ldInst) {
auto LdElement = [=](Value *offset, IRBuilder<> &Builder) -> Value * {
unsigned numComponents = 0;
if (VectorType *VTy = dyn_cast<VectorType>(Ty)) {
numComponents = VTy->getNumElements();
} else {
numComponents = 1;
}
Constant *alignment =
NewLd = ExtractFromTypedBufferLoad(ResRet, Ty, Offset, Builder);
} else {
Value *ResultElts[4];
Constant *Alignment =
OP->GetI32Const(DL.getTypeAllocSize(Ty->getScalarType()));
if (ResKind == HLResource::Kind::TypedBuffer) {
// Typed buffer cannot have offsets, they must be loaded all at once
ResRetValueArray ResRet = GenerateTypedBufferLoad(
handle, pOverloadTy, bufIdx, status, OP, Builder);

return ExtractFromTypedBufferLoad(ResRet, Ty, offset, Builder);
} else {
Value *ResultElts[4];
GenerateRawBufLd(handle, bufIdx, offset, status, pOverloadTy,
ResultElts, OP, Builder, numComponents, alignment);
return ScalarizeElements(Ty, ResultElts, Builder);
}
};

Value *newLd = LdElement(offset, Builder);
if (arraySize > 1) {
newLd =
Builder.CreateInsertValue(UndefValue::get(Ty), newLd, (uint64_t)0);

for (unsigned i = 1; i < arraySize; i++) {
offset = Builder.CreateAdd(offset, eltSize);
Value *eltLd = LdElement(offset, Builder);
newLd = Builder.CreateInsertValue(newLd, eltLd, i);
}
GenerateRawBufLd(handle, bufIdx, Offset, status, pOverloadTy,
ResultElts, OP, Builder, NumComponents, Alignment);
NewLd = ScalarizeElements(Ty, ResultElts, Builder);
}
ldInst->replaceAllUsesWith(newLd);

LdInst->replaceAllUsesWith(NewLd);
} else {
Value *val = stInst->getValueOperand();
auto StElement = [&](Value *offset, Value *val, IRBuilder<> &Builder) {
Value *undefVal = llvm::UndefValue::get(pOverloadTy);
Value *vals[] = {undefVal, undefVal, undefVal, undefVal};
uint8_t mask = 0;
if (Ty->isVectorTy()) {
unsigned vectorNumElements = Ty->getVectorNumElements();
DXASSERT(vectorNumElements <= 4, "up to 4 elements in vector");
assert(vectorNumElements <= 4);
for (unsigned i = 0; i < vectorNumElements; i++) {
vals[i] = Builder.CreateExtractElement(val, i);
mask |= (1 << i);
}
} else {
vals[0] = val;
mask = DXIL::kCompMask_X;
}
Constant *alignment =
OP->GetI32Const(DL.getTypeAllocSize(Ty->getScalarType()));
GenerateStructBufSt(handle, bufIdx, offset, pOverloadTy, OP, Builder,
vals, mask, alignment);
};
if (arraySize > 1)
val = Builder.CreateExtractValue(val, 0);

StElement(offset, val, Builder);
if (arraySize > 1) {
val = stInst->getValueOperand();

for (unsigned i = 1; i < arraySize; i++) {
offset = Builder.CreateAdd(offset, eltSize);
Value *eltVal = Builder.CreateExtractValue(val, i);
StElement(offset, eltVal, Builder);
Value *val = StInst->getValueOperand();
Value *undefVal = llvm::UndefValue::get(pOverloadTy);
Value *vals[] = {undefVal, undefVal, undefVal, undefVal};
uint8_t mask = 0;
if (Ty->isVectorTy()) {
unsigned vectorNumElements = Ty->getVectorNumElements();
DXASSERT(vectorNumElements <= 4, "up to 4 elements in vector");
assert(vectorNumElements <= 4);
for (unsigned i = 0; i < vectorNumElements; i++) {
vals[i] = Builder.CreateExtractElement(val, i);
mask |= (1 << i);
}
} else {
vals[0] = val;
mask = DXIL::kCompMask_X;
}
Constant *alignment =
OP->GetI32Const(DL.getTypeAllocSize(Ty->getScalarType()));
GenerateStructBufSt(handle, bufIdx, Offset, pOverloadTy, OP, Builder,
vals, mask, alignment);
}
user->eraseFromParent();
} else if (BitCastInst *BCI = dyn_cast<BitCastInst>(user)) {
Expand Down
17 changes: 13 additions & 4 deletions tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3510,11 +3510,20 @@ bool CGMSHLSLRuntime::SetUAVSRV(SourceLocation loc,
if (const BuiltinType *BTy = EltTy->getAs<BuiltinType>()) {
CompType::Kind kind = BuiltinTyToCompTy(BTy, bHasNormAttribute && bSNorm,
bHasNormAttribute && !bSNorm);
// 64bits types are implemented with u32.
if (kind == CompType::Kind::U64 || kind == CompType::Kind::I64 ||
kind == CompType::Kind::SNormF64 ||
kind == CompType::Kind::UNormF64 || kind == CompType::Kind::F64) {
// Boolean, 64-bit, and packed types are implemented with u32.
switch (kind) {
case CompType::Kind::I1:
case CompType::Kind::U64:
case CompType::Kind::I64:
case CompType::Kind::F64:
case CompType::Kind::SNormF64:
case CompType::Kind::UNormF64:
case CompType::Kind::PackedS8x32:
case CompType::Kind::PackedU8x32:
kind = CompType::Kind::U32;
break;
default:
break;
}
hlslRes->SetCompType(kind);
} else {
Expand Down
Loading

0 comments on commit b317f1b

Please sign in to comment.