Skip to content

Commit e07be1c

Browse files
author
Greg Roth
authored
Fix errors in retrieving and assigning load status parameter (microsoft#7513)
There were two problems with processing the status parameter with the reword 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 microsoft#7508
1 parent b390fb1 commit e07be1c

File tree

7 files changed

+280
-74
lines changed

7 files changed

+280
-74
lines changed

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
@@ -3063,10 +3063,10 @@ static Value *ScalarizeResRet(Type *RetTy, Value *ResRet,
30633063
}
30643064

30653065
void UpdateStatus(Value *ResRet, Value *status, IRBuilder<> &Builder,
3066-
hlsl::OP *hlslOp) {
3066+
hlsl::OP *hlslOp,
3067+
unsigned StatusIndex = DXIL::kResRetStatusIndex) {
30673068
if (status && !isa<UndefValue>(status)) {
3068-
Value *statusVal =
3069-
Builder.CreateExtractValue(ResRet, DXIL::kResRetStatusIndex);
3069+
Value *statusVal = Builder.CreateExtractValue(ResRet, StatusIndex);
30703070
Value *checkAccessOp = hlslOp->GetI32Const(
30713071
static_cast<unsigned>(DXIL::OpCode::CheckAccessFullyMapped));
30723072
Function *checkAccessFn = hlslOp->GetOpFunc(
@@ -4028,9 +4028,9 @@ struct ResLoadHelper {
40284028
// Used for some subscript operators that feed the generic HL call inst
40294029
// into a load op and by the matrixload call instruction.
40304030
ResLoadHelper(Instruction *Inst, DxilResource::Kind RK, Value *h, Value *idx,
4031-
Value *Offset, Value *mip = nullptr)
4031+
Value *Offset, Value *status = nullptr, Value *mip = nullptr)
40324032
: intrinsicOpCode(IntrinsicOp::Num_Intrinsics), handle(h), retVal(Inst),
4033-
addr(idx), offset(Offset), status(nullptr), mipLevel(mip) {
4033+
addr(idx), offset(Offset), status(status), mipLevel(mip) {
40344034
opcode = LoadOpFromResKind(RK);
40354035
Type *Ty = Inst->getType();
40364036
if (opcode == OP::OpCode::RawBufferLoad && Ty->isVectorTy() &&
@@ -4304,18 +4304,22 @@ Value *TranslateBufLoad(ResLoadHelper &helper, HLResource::Kind RK,
43044304

43054305
Function *F = OP->GetOpFunc(opcode, EltTy);
43064306
Value *Ld = Builder.CreateCall(F, Args, OP::GetOpCodeName(opcode));
4307+
unsigned StatusIndex;
43074308

43084309
// Extract elements from returned ResRet.
43094310
// Native vector loads just have one vector element in the ResRet.
43104311
// Others have up to four scalars that need to be individually extracted.
4311-
if (opcode == OP::OpCode::RawBufferVectorLoad)
4312+
if (opcode == OP::OpCode::RawBufferVectorLoad) {
43124313
Elts[i++] = Builder.CreateExtractValue(Ld, 0);
4313-
else
4314+
StatusIndex = DXIL::kVecResRetStatusIndex;
4315+
} else {
43144316
for (unsigned j = 0; j < chunkSize; j++, i++)
43154317
Elts[i] = Builder.CreateExtractValue(Ld, j);
4318+
StatusIndex = DXIL::kResRetStatusIndex;
4319+
}
43164320

43174321
// Update status.
4318-
UpdateStatus(Ld, helper.status, Builder, OP);
4322+
UpdateStatus(Ld, helper.status, Builder, OP, StatusIndex);
43194323

43204324
if (!FirstLd)
43214325
FirstLd = Ld;
@@ -8537,7 +8541,7 @@ Value *TranslateStructBufMatLd(CallInst *CI, IRBuilder<> &Builder,
85378541
Value *status, Value *bufIdx, Value *baseOffset,
85388542
const DataLayout &DL) {
85398543

8540-
ResLoadHelper helper(CI, RK, handle, bufIdx, baseOffset);
8544+
ResLoadHelper helper(CI, RK, handle, bufIdx, baseOffset, status);
85418545
#ifndef NDEBUG
85428546
Value *ptr = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx);
85438547
Type *matType = ptr->getType()->getPointerElementType();
@@ -8864,7 +8868,7 @@ void TranslateStructBufSubscriptUser(Instruction *user, Value *handle,
88648868
}
88658869
} else if (LoadInst *LdInst = dyn_cast<LoadInst>(user)) {
88668870
// Load of scalar/vector within a struct or structured raw load.
8867-
ResLoadHelper helper(LdInst, ResKind, handle, bufIdx, baseOffset);
8871+
ResLoadHelper helper(LdInst, ResKind, handle, bufIdx, baseOffset, status);
88688872
TranslateBufLoad(helper, ResKind, Builder, OP, DL);
88698873

88708874
LdInst->eraseFromParent();
@@ -9239,7 +9243,8 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
92399243
IRBuilder<> Builder(CI);
92409244
if (LoadInst *ldInst = dyn_cast<LoadInst>(*U)) {
92419245
Value *Offset = UndefValue::get(Builder.getInt32Ty());
9242-
ResLoadHelper ldHelper(ldInst, RK, handle, coord, Offset, mipLevel);
9246+
ResLoadHelper ldHelper(ldInst, RK, handle, coord, Offset,
9247+
/*status*/ nullptr, mipLevel);
92439248
TranslateBufLoad(ldHelper, RK, Builder, hlslOP, helper.dataLayout);
92449249
ldInst->eraseFromParent();
92459250
} else {

0 commit comments

Comments
 (0)