Skip to content

Commit 49f5419

Browse files
author
Greg Roth
authored
Fix errors in retrieving and assigning load status parameter (#7589)
Cherry-picked to release-1.8.2505 from #7513 There were two problems with processing the status parameter with the rework of the buffer load code. The first was that the status was not being passed down to the load instruction generation for aggregate types in any shader model version. The second was that the status retrieval from the resret returned by the raw buffer loads was using the wrong index for native vectors supported by shader model 6.9. The status Value was not getting passed all the way down to the load instruction generation for aggregate types because the refactored helper constructor would always set it to null. It needs to be explicitly stated since by that point, the original call instruction it came from has been lost amidst subsequent GEPs, bitcasts, and/or loads that aggregate types (arrays and structs) will use on the results of the original call instruction to get the exact element required. This changes the constructor to take an optional status parameter allowing the locations where it might be set to pass it along. In other cases, it will be null and be appropriately ignored. Modified aggregate tests to verify this behavior. This required keeping track of the return of the last load operation involved in a raw buffer load, which made arrays more complicated. Rather than give them their own CHECK prefix, I lumped them in with large matrices requiring three loads. This did require making all the array lengths 3 to match. The loss in test variability is worth the convenience as there is no known distinction when it comes to array sizes over 1. The status retrieval from the ResRet returned by the raw buffer loads was using the wrong index for native vectors supported by shader model 6.9. Adjusting the index according to the opcode ensures that the index will be correct. This also required a change to validation that allows checkAccessFullyMapped to operate on the second element extracted from a ResRet where applicable and some corresponding null tolerance in related code. Adds status retrieving overloads to the relevant load/store tests for sm6.9, aggregates, and other loads though the last category exhibited no issues. At least I got some statuses right! Fixes #7508 (cherry picked from commit e07be1c)
1 parent 4a98867 commit 49f5419

7 files changed

Lines changed: 280 additions & 74 deletions

File tree

include/dxc/DXIL/DxilConstants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ const float kMaxMipLodBias = 15.99f;
154154
const float kMinMipLodBias = -16.0f;
155155

156156
const unsigned kResRetStatusIndex = 4;
157+
const unsigned kVecResRetStatusIndex = 1;
157158

158159
/* <py::lines('OLOAD_DIMS-TEXT')>hctdb_instrhelp.get_max_oload_dims()</py>*/
159160
// OLOAD_DIMS-TEXT:BEGIN

lib/DXIL/DxilOperations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6438,7 +6438,7 @@ Type *OP::GetFourI32Type() const { return m_pFourI32Type; }
64386438
Type *OP::GetFourI16Type() const { return m_pFourI16Type; }
64396439

64406440
bool OP::IsResRetType(llvm::Type *Ty) {
6441-
if (!Ty->isStructTy())
6441+
if (!Ty || !Ty->isStructTy())
64426442
return false;
64436443
for (Type *ResTy : m_pResRetType) {
64446444
if (Ty == ResTy)

lib/DxilValidation/DxilValidation.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,9 +1573,15 @@ static void ValidateResourceDxilOp(CallInst *CI, DXIL::OpCode Opcode,
15731573
ValCtx.EmitInstrError(CI, ValidationRule::InstrCheckAccessFullyMapped);
15741574
} else {
15751575
Value *V = EVI->getOperand(0);
1576+
StructType *StrTy = dyn_cast<StructType>(V->getType());
1577+
unsigned ExtractIndex = EVI->getIndices()[0];
1578+
// Ensure parameter is a single value that is extracted from the correct
1579+
// ResRet struct location.
15761580
bool IsLegal = EVI->getNumIndices() == 1 &&
1577-
EVI->getIndices()[0] == DXIL::kResRetStatusIndex &&
1578-
ValCtx.DxilMod.GetOP()->IsResRetType(V->getType());
1581+
(ExtractIndex == DXIL::kResRetStatusIndex ||
1582+
ExtractIndex == DXIL::kVecResRetStatusIndex) &&
1583+
ValCtx.DxilMod.GetOP()->IsResRetType(StrTy) &&
1584+
ExtractIndex == StrTy->getNumElements() - 1;
15791585
if (!IsLegal) {
15801586
ValCtx.EmitInstrError(CI, ValidationRule::InstrCheckAccessFullyMapped);
15811587
}

lib/HLSL/HLOperationLower.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,10 +3066,10 @@ static Value *ScalarizeResRet(Type *RetTy, Value *ResRet,
30663066
}
30673067

30683068
void UpdateStatus(Value *ResRet, Value *status, IRBuilder<> &Builder,
3069-
hlsl::OP *hlslOp) {
3069+
hlsl::OP *hlslOp,
3070+
unsigned StatusIndex = DXIL::kResRetStatusIndex) {
30703071
if (status && !isa<UndefValue>(status)) {
3071-
Value *statusVal =
3072-
Builder.CreateExtractValue(ResRet, DXIL::kResRetStatusIndex);
3072+
Value *statusVal = Builder.CreateExtractValue(ResRet, StatusIndex);
30733073
Value *checkAccessOp = hlslOp->GetI32Const(
30743074
static_cast<unsigned>(DXIL::OpCode::CheckAccessFullyMapped));
30753075
Function *checkAccessFn = hlslOp->GetOpFunc(
@@ -4031,9 +4031,9 @@ struct ResLoadHelper {
40314031
// Used for some subscript operators that feed the generic HL call inst
40324032
// into a load op and by the matrixload call instruction.
40334033
ResLoadHelper(Instruction *Inst, DxilResource::Kind RK, Value *h, Value *idx,
4034-
Value *Offset, Value *mip = nullptr)
4034+
Value *Offset, Value *status = nullptr, Value *mip = nullptr)
40354035
: intrinsicOpCode(IntrinsicOp::Num_Intrinsics), handle(h), retVal(Inst),
4036-
addr(idx), offset(Offset), status(nullptr), mipLevel(mip) {
4036+
addr(idx), offset(Offset), status(status), mipLevel(mip) {
40374037
opcode = LoadOpFromResKind(RK);
40384038
Type *Ty = Inst->getType();
40394039
if (opcode == OP::OpCode::RawBufferLoad && Ty->isVectorTy() &&
@@ -4307,18 +4307,22 @@ Value *TranslateBufLoad(ResLoadHelper &helper, HLResource::Kind RK,
43074307

43084308
Function *F = OP->GetOpFunc(opcode, EltTy);
43094309
Value *Ld = Builder.CreateCall(F, Args, OP::GetOpCodeName(opcode));
4310+
unsigned StatusIndex;
43104311

43114312
// Extract elements from returned ResRet.
43124313
// Native vector loads just have one vector element in the ResRet.
43134314
// Others have up to four scalars that need to be individually extracted.
4314-
if (opcode == OP::OpCode::RawBufferVectorLoad)
4315+
if (opcode == OP::OpCode::RawBufferVectorLoad) {
43154316
Elts[i++] = Builder.CreateExtractValue(Ld, 0);
4316-
else
4317+
StatusIndex = DXIL::kVecResRetStatusIndex;
4318+
} else {
43174319
for (unsigned j = 0; j < chunkSize; j++, i++)
43184320
Elts[i] = Builder.CreateExtractValue(Ld, j);
4321+
StatusIndex = DXIL::kResRetStatusIndex;
4322+
}
43194323

43204324
// Update status.
4321-
UpdateStatus(Ld, helper.status, Builder, OP);
4325+
UpdateStatus(Ld, helper.status, Builder, OP, StatusIndex);
43224326

43234327
if (!FirstLd)
43244328
FirstLd = Ld;
@@ -8540,7 +8544,7 @@ Value *TranslateStructBufMatLd(CallInst *CI, IRBuilder<> &Builder,
85408544
Value *status, Value *bufIdx, Value *baseOffset,
85418545
const DataLayout &DL) {
85428546

8543-
ResLoadHelper helper(CI, RK, handle, bufIdx, baseOffset);
8547+
ResLoadHelper helper(CI, RK, handle, bufIdx, baseOffset, status);
85448548
#ifndef NDEBUG
85458549
Value *ptr = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx);
85468550
Type *matType = ptr->getType()->getPointerElementType();
@@ -8867,7 +8871,7 @@ void TranslateStructBufSubscriptUser(Instruction *user, Value *handle,
88678871
}
88688872
} else if (LoadInst *LdInst = dyn_cast<LoadInst>(user)) {
88698873
// Load of scalar/vector within a struct or structured raw load.
8870-
ResLoadHelper helper(LdInst, ResKind, handle, bufIdx, baseOffset);
8874+
ResLoadHelper helper(LdInst, ResKind, handle, bufIdx, baseOffset, status);
88718875
TranslateBufLoad(helper, ResKind, Builder, OP, DL);
88728876

88738877
LdInst->eraseFromParent();
@@ -9242,7 +9246,8 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
92429246
IRBuilder<> Builder(CI);
92439247
if (LoadInst *ldInst = dyn_cast<LoadInst>(*U)) {
92449248
Value *Offset = UndefValue::get(Builder.getInt32Ty());
9245-
ResLoadHelper ldHelper(ldInst, RK, handle, coord, Offset, mipLevel);
9249+
ResLoadHelper ldHelper(ldInst, RK, handle, coord, Offset,
9250+
/*status*/ nullptr, mipLevel);
92469251
TranslateBufLoad(ldHelper, RK, Builder, hlslOP, helper.dataLayout);
92479252
ldInst->eraseFromParent();
92489253
} else {

0 commit comments

Comments
 (0)