Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3173,6 +3173,7 @@ INSTR.OPCODERESERVED Instructions must not refe
INSTR.OPCONST DXIL intrinsic requires an immediate constant operand
INSTR.OPCONSTRANGE Constant values must be in-range for operation.
INSTR.OPERANDRANGE DXIL intrinsic operand must be within defined range
INSTR.PARAMMULTIPLE Parameter must be a valid multiple
INSTR.PTRBITCAST Pointer type bitcast must be have same size.
INSTR.RESOURCECLASSFORLOAD load can only run on UAV/SRV resource.
INSTR.RESOURCECLASSFORSAMPLERGATHER sample, lod and gather should be on srv resource.
Expand Down
3 changes: 3 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ The included licenses apply to the following files:

Place release notes for the upcoming release below this line and remove this line upon naming this release.

### Version 1.8.2505

- Typed buffers (including ROV buffers) no longer accept types other than vectors and scalars. Any other types will produce descriptive errors. This removes support for appropriately sized matrices and structs. Though it worked in some contexts, code generated from such types was unreliable.
- By default, the internal validator will be used instead of searching externally for an existing DXIL.dll.

### Version 1.8.2502

Expand Down
2 changes: 1 addition & 1 deletion external/SPIRV-Tools
4 changes: 4 additions & 0 deletions include/dxc/HLSL/HLOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ const unsigned kHitObjectMakeMissRayDescOpIdx = 4;
const unsigned kHitObjectTraceRay_RayDescOpIdx = 8;
const unsigned kHitObjectTraceRay_NumOp = 10;

// HitObject::FromRayQuery
const unsigned kHitObjectFromRayQuery_WithAttrs_AttributeOpIdx = 4;
const unsigned kHitObjectFromRayQuery_WithAttrs_NumOp = 5;

// Linear Algebra Operations

// MatVecMul
Expand Down
2 changes: 1 addition & 1 deletion include/dxc/Support/HLSLOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ struct RewriterOpts {
};

enum class ValidatorSelection : int {
Auto, // Try DXIL.dll; fallback to internal validator
Auto, // Force internal validator (even if DXIL.dll is present)
Internal, // Force internal validator (even if DXIL.dll is present)
External, // Use DXIL.dll, failing compilation if not available
Invalid = -1 // Invalid
Expand Down
119 changes: 119 additions & 0 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,46 @@ static unsigned getSemanticFlagValidMask(const ShaderModel *pSM) {
return static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::ValidMask);
}

StringRef GetOpCodeName(DXIL::OpCode OpCode) {
switch (OpCode) {
default:
DXASSERT(false, "Unexpected op code");
return "";
case DXIL::OpCode::HitObject_ObjectRayOrigin:
return "HitObject_ObjectRayOrigin";
case DXIL::OpCode::HitObject_WorldRayDirection:
return "HitObject_WorldRayDirection";
case DXIL::OpCode::HitObject_WorldRayOrigin:
return "HitObject_WorldRayOrigin";
case DXIL::OpCode::HitObject_ObjectRayDirection:
return "HitObject_ObjectRayDirection";
case DXIL::OpCode::HitObject_WorldToObject3x4:
return "HitObject_WorldToObject3x4";
case DXIL::OpCode::HitObject_ObjectToWorld3x4:
return "HitObject_ObjectToWorld3x4";
}
}

static void ValidateConstantRangeUnsigned(Value *Val, StringRef Name,
uint64_t LowerBound,
uint64_t UpperBound, CallInst *CI,
DXIL::OpCode OpCode,
ValidationContext &ValCtx) {
ConstantInt *C = dyn_cast<ConstantInt>(Val);
if (!C) {
ValCtx.EmitInstrFormatError(CI, ValidationRule::InstrOpConst,
{Name, GetOpCodeName(OpCode)});
return;
}
if (C->uge(UpperBound + 1U) || !C->uge(LowerBound)) {
std::string Range =
std::to_string(LowerBound) + "~" + std::to_string(UpperBound);
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrOperandRange,
{Name, Range, C->getValue().toString(10, false)});
}
}

static void ValidateDxilOperationCallInProfile(CallInst *CI,
DXIL::OpCode Opcode,
const ShaderModel *pSM,
Expand Down Expand Up @@ -2170,6 +2210,82 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
ValCtx.EmitInstrError(
CI, ValidationRule::InstrMayReorderThreadUndefCoherenceHintParam);
} break;
case DXIL::OpCode::HitObject_MakeMiss: {
DxilInst_HitObject_MakeMiss MakeMiss(CI);
if (isa<UndefValue>(MakeMiss.get_RayFlags()) ||
isa<UndefValue>(MakeMiss.get_MissShaderIndex()))
ValCtx.EmitInstrError(CI, ValidationRule::InstrNoReadingUninitialized);
} break;

case DXIL::OpCode::HitObject_LoadLocalRootTableConstant: {
Value *HitObject = CI->getArgOperand(1);
if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
Value *Offset = CI->getArgOperand(2);
if (isa<UndefValue>(Offset))
ValCtx.EmitInstrError(CI, ValidationRule::InstrNoReadingUninitialized);
if (ConstantInt *COffset = dyn_cast<ConstantInt>(Offset)) {
if (COffset->getLimitedValue() % 4 != 0)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrParamMultiple,
{"offset", "4", COffset->getValue().toString(10, false)});
}
break;
}
case DXIL::OpCode::HitObject_SetShaderTableIndex: {
Value *HitObject = CI->getArgOperand(1);
if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
Value *RecordIndex = CI->getArgOperand(2);
if (isa<UndefValue>(RecordIndex))
ValCtx.EmitInstrError(CI, ValidationRule::InstrNoReadingUninitialized);
break;
}

// Shader Execution Reordering - scalar getters
case DXIL::OpCode::HitObject_GeometryIndex:
case DXIL::OpCode::HitObject_HitKind:
case DXIL::OpCode::HitObject_InstanceID:
case DXIL::OpCode::HitObject_InstanceIndex:
case DXIL::OpCode::HitObject_IsHit:
case DXIL::OpCode::HitObject_IsMiss:
case DXIL::OpCode::HitObject_IsNop:
case DXIL::OpCode::HitObject_PrimitiveIndex:
case DXIL::OpCode::HitObject_RayFlags:
case DXIL::OpCode::HitObject_RayTCurrent:
case DXIL::OpCode::HitObject_RayTMin:
case DXIL::OpCode::HitObject_ShaderTableIndex: {
Value *HitObject = CI->getArgOperand(1);
if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
break;
}

// Shader Execution Reordering - vector getters
case DXIL::OpCode::HitObject_ObjectRayDirection:
case DXIL::OpCode::HitObject_ObjectRayOrigin:
case DXIL::OpCode::HitObject_WorldRayDirection:
case DXIL::OpCode::HitObject_WorldRayOrigin: {
Value *HitObject = CI->getArgOperand(1);
if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
Value *Col = CI->getArgOperand(2);
ValidateConstantRangeUnsigned(Col, "component", 0, 2, CI, Opcode, ValCtx);
break;
}

// Shader Execution Reordering - matrix getters
case DXIL::OpCode::HitObject_WorldToObject3x4:
case DXIL::OpCode::HitObject_ObjectToWorld3x4: {
Value *HitObject = CI->getArgOperand(1);
if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
Value *Row = CI->getArgOperand(2);
ValidateConstantRangeUnsigned(Row, "row", 0, 2, CI, Opcode, ValCtx);
Value *Col = CI->getArgOperand(3);
ValidateConstantRangeUnsigned(Col, "column", 0, 3, CI, Opcode, ValCtx);
break;
}

case DXIL::OpCode::AtomicBinOp:
case DXIL::OpCode::AtomicCompareExchange: {
Expand Down Expand Up @@ -2483,6 +2599,9 @@ static bool ValidateType(Type *Ty, ValidationContext &ValCtx,
if (ValCtx.HandleTy == Ty)
return true;
hlsl::OP *HlslOP = ValCtx.DxilMod.GetOP();
// Allow HitObject type.
if (ST == HlslOP->GetHitObjectType())
return true;
if (IsDxilBuiltinStructType(ST, HlslOP)) {
ValCtx.EmitTypeError(Ty, ValidationRule::InstrDxilStructUser);
Result = false;
Expand Down
143 changes: 122 additions & 21 deletions lib/HLSL/HLOperationLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5958,19 +5958,31 @@ Value *TranslateNoArgVectorOperation(CallInst *CI, IntrinsicOp IOP,
return retVal;
}

template <typename ColElemTy>
static void GetMatrixIndices(Constant *&Rows, Constant *&Cols, bool Is3x4,
LLVMContext &Ctx) {
if (Is3x4) {
uint32_t RVals[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2};
Rows = ConstantDataVector::get(Ctx, RVals);
ColElemTy CVals[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3};
Cols = ConstantDataVector::get(Ctx, CVals);
return;
}
uint32_t RVals[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2};
Rows = ConstantDataVector::get(Ctx, RVals);
ColElemTy CVals[] = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3};
Cols = ConstantDataVector::get(Ctx, CVals);
}

Value *TranslateNoArgMatrix3x4Operation(
CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
HLOperationLowerHelper &helper, HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
hlsl::OP *hlslOP = &helper.hlslOP;
VectorType *Ty = cast<VectorType>(CI->getType());
uint32_t rVals[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2};
Constant *rows = ConstantDataVector::get(CI->getContext(), rVals);
uint8_t cVals[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3};
Constant *cols = ConstantDataVector::get(CI->getContext(), cVals);
Value *retVal =
TrivialDxilOperation(opcode, {nullptr, rows, cols}, Ty, CI, hlslOP);
return retVal;
Constant *Rows, *Cols;
GetMatrixIndices<uint8_t>(Rows, Cols, true, CI->getContext());
return TrivialDxilOperation(opcode, {nullptr, Rows, Cols}, Ty, CI, hlslOP);
}

Value *TranslateNoArgTransposedMatrix3x4Operation(
Expand All @@ -5979,13 +5991,9 @@ Value *TranslateNoArgTransposedMatrix3x4Operation(
bool &Translated) {
hlsl::OP *hlslOP = &helper.hlslOP;
VectorType *Ty = cast<VectorType>(CI->getType());
uint32_t rVals[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2};
Constant *rows = ConstantDataVector::get(CI->getContext(), rVals);
uint8_t cVals[] = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3};
Constant *cols = ConstantDataVector::get(CI->getContext(), cVals);
Value *retVal =
TrivialDxilOperation(opcode, {nullptr, rows, cols}, Ty, CI, hlslOP);
return retVal;
Constant *Rows, *Cols;
GetMatrixIndices<uint8_t>(Rows, Cols, false, CI->getContext());
return TrivialDxilOperation(opcode, {nullptr, Rows, Cols}, Ty, CI, hlslOP);
}

/*
Expand Down Expand Up @@ -6304,7 +6312,32 @@ Value *TranslateHitObjectFromRayQuery(CallInst *CI, IntrinsicOp IOP,
HLOperationLowerHelper &Helper,
HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
IRBuilder<> Builder(CI);

unsigned SrcIdx = 1;
Value *HitObjectPtr = CI->getArgOperand(SrcIdx++);
Value *RayQuery = CI->getArgOperand(SrcIdx++);

if (CI->getNumArgOperands() ==
HLOperandIndex::kHitObjectFromRayQuery_WithAttrs_NumOp) {
Value *HitKind = CI->getArgOperand(SrcIdx++);
Value *AttribSrc = CI->getArgOperand(SrcIdx++);
DXASSERT_NOMSG(SrcIdx == CI->getNumArgOperands());
OpCode = DXIL::OpCode::HitObject_FromRayQueryWithAttrs;
Type *AttrTy = AttribSrc->getType();
Value *OutHitObject = TrivialDxilOperation(
OpCode, {nullptr, RayQuery, HitKind, AttribSrc}, AttrTy, CI, OP);
Builder.CreateStore(OutHitObject, HitObjectPtr);
return nullptr;
}

DXASSERT_NOMSG(SrcIdx == CI->getNumArgOperands());
OpCode = DXIL::OpCode::HitObject_FromRayQuery;
Value *OutHitObject =
TrivialDxilOperation(OpCode, {nullptr, RayQuery}, Helper.voidTy, CI, OP);
Builder.CreateStore(OutHitObject, HitObjectPtr);
return nullptr;
}

Value *TranslateHitObjectTraceRay(CallInst *CI, IntrinsicOp IOP,
Expand Down Expand Up @@ -6367,45 +6400,113 @@ Value *TranslateHitObjectGetAttributes(CallInst *CI, IntrinsicOp IOP,
HLOperationLowerHelper &Helper,
HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
IRBuilder<> Builder(CI);

Value *HitObjectPtr = CI->getArgOperand(1);
Value *HitObject = Builder.CreateLoad(HitObjectPtr);

Type *AttrTy = cast<PointerType>(CI->getType())->getPointerElementType();

IRBuilder<> EntryBuilder(
dxilutil::FindAllocaInsertionPt(CI->getParent()->getParent()));
unsigned AttrAlign = Helper.dataLayout.getABITypeAlignment(AttrTy);
AllocaInst *AttrMem = EntryBuilder.CreateAlloca(AttrTy);
AttrMem->setAlignment(AttrAlign);
Constant *opArg = OP->GetU32Const((unsigned)OpCode);
TrivialDxilOperation(OpCode, {opArg, HitObject, AttrMem}, CI->getType(),
Helper.voidTy, OP, Builder);
return AttrMem;
}

Value *TranslateHitObjectScalarGetter(CallInst *CI, IntrinsicOp IOP,
OP::OpCode OpCode,
HLOperationLowerHelper &Helper,
HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
Value *HitObjectPtr = CI->getArgOperand(1);
IRBuilder<> Builder(CI);
Value *HitObject = Builder.CreateLoad(HitObjectPtr);
return TrivialDxilOperation(OpCode, {nullptr, HitObject}, CI->getType(), CI,
OP);
}

Value *TranslateHitObjectVectorGetter(CallInst *CI, IntrinsicOp IOP,
OP::OpCode OpCode,
HLOperationLowerHelper &Helper,
HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
Value *HitObjectPtr = CI->getArgOperand(1);
IRBuilder<> Builder(CI);
Value *HitObject = Builder.CreateLoad(HitObjectPtr);
VectorType *Ty = cast<VectorType>(CI->getType());
uint32_t Vals[] = {0, 1, 2, 3};
Constant *Src = ConstantDataVector::get(CI->getContext(), Vals);
return TrivialDxilOperation(OpCode, {nullptr, HitObject, Src}, Ty, CI, OP);
}

static bool IsHitObject3x4Getter(IntrinsicOp IOP) {
switch (IOP) {
default:
return false;
case IntrinsicOp::MOP_DxHitObject_GetObjectToWorld3x4:
case IntrinsicOp::MOP_DxHitObject_GetWorldToObject3x4:
return true;
}
}

Value *TranslateHitObjectMatrixGetter(CallInst *CI, IntrinsicOp IOP,
OP::OpCode OpCode,
HLOperationLowerHelper &Helper,
HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
Value *HitObjectPtr = CI->getArgOperand(1);
IRBuilder<> Builder(CI);
Value *HitObject = Builder.CreateLoad(HitObjectPtr);

// Create 3x4 matrix indices
bool Is3x4 = IsHitObject3x4Getter(IOP);
Constant *Rows, *Cols;
GetMatrixIndices<uint32_t>(Rows, Cols, Is3x4, CI->getContext());

VectorType *Ty = cast<VectorType>(CI->getType());
return TrivialDxilOperation(OpCode, {nullptr, HitObject, Rows, Cols}, Ty, CI,
OP);
}

Value *TranslateHitObjectLoadLocalRootTableConstant(
CallInst *CI, IntrinsicOp IOP, OP::OpCode OpCode,
HLOperationLowerHelper &Helper, HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
IRBuilder<> Builder(CI);

Value *HitObjectPtr = CI->getArgOperand(1);
Value *Offset = CI->getArgOperand(2);

Value *HitObject = Builder.CreateLoad(HitObjectPtr);
return TrivialDxilOperation(OpCode, {nullptr, HitObject, Offset},
Helper.voidTy, CI, OP);
}

Value *TranslateHitObjectSetShaderTableIndex(
CallInst *CI, IntrinsicOp IOP, OP::OpCode OpCode,
HLOperationLowerHelper &Helper, HLObjectOperationLowerHelper *pObjHelper,
bool &Translated) {
return UndefValue::get(CI->getType()); // TODO: Merge SER DXIL patches
hlsl::OP *OP = &Helper.hlslOP;
IRBuilder<> Builder(CI);

Value *HitObjectPtr = CI->getArgOperand(1);
Value *ShaderTableIndex = CI->getArgOperand(2);

Value *InHitObject = Builder.CreateLoad(HitObjectPtr);
Value *OutHitObject = TrivialDxilOperation(
OpCode, {nullptr, InHitObject, ShaderTableIndex}, Helper.voidTy, CI, OP);
Builder.CreateStore(OutHitObject, HitObjectPtr);
return nullptr;
}

} // namespace
Expand Down
Loading
Loading