Skip to content

Commit b3602bd

Browse files
committed
[SER] Validate HitObject accessors
Validate: HitObject_GeometryIndex HitObject_HitKind HitObject_InstanceID HitObject_InstanceIndex HitObject_IsHit HitObject_IsMiss HitObject_IsNop HitObject_LoadLocalRootTableConstant HitObject_ObjectRayDirection HitObject_ObjectRayOrigin HitObject_ObjectToWorld3x4 HitObject_PrimitiveIndex HitObject_RayFlags HitObject_RayTCurrent HitObject_RayTMin HitObject_SetShaderTableIndex HitObject_ShaderTableIndex HitObject_WorldRayDirection HitObject_WorldRayOrigin Rules: * No undef parameters (HitObject, RecordIndex, RootTableOffset) * row/col/component indices are constant and in-bounds * If constant, RootTableOffset % 4 == 0 SER implementation tracker: microsoft#7214
1 parent f19b5da commit b3602bd

File tree

5 files changed

+319
-1
lines changed

5 files changed

+319
-1
lines changed

docs/DXIL.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,6 +3161,7 @@ INSTR.OPCODERESERVED Instructions must not refe
31613161
INSTR.OPCONST DXIL intrinsic requires an immediate constant operand
31623162
INSTR.OPCONSTRANGE Constant values must be in-range for operation.
31633163
INSTR.OPERANDRANGE DXIL intrinsic operand must be within defined range
3164+
INSTR.PARAMMULTIPLE Parameter must be a valid multiple
31643165
INSTR.PTRBITCAST Pointer type bitcast must be have same size.
31653166
INSTR.RESOURCECLASSFORLOAD load can only run on UAV/SRV resource.
31663167
INSTR.RESOURCECLASSFORSAMPLERGATHER sample, lod and gather should be on srv resource.

lib/DxilValidation/DxilValidation.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,46 @@ static unsigned getSemanticFlagValidMask(const ShaderModel *pSM) {
16441644
return static_cast<unsigned>(hlsl::DXIL::BarrierSemanticFlag::ValidMask);
16451645
}
16461646

1647+
StringRef GetOpCodeName(DXIL::OpCode OpCode) {
1648+
switch (OpCode) {
1649+
default:
1650+
DXASSERT(false, "Unexpected op code");
1651+
return "";
1652+
case DXIL::OpCode::HitObject_ObjectRayOrigin:
1653+
return "HitObject_ObjectRayOrigin";
1654+
case DXIL::OpCode::HitObject_WorldRayDirection:
1655+
return "HitObject_WorldRayDirection";
1656+
case DXIL::OpCode::HitObject_WorldRayOrigin:
1657+
return "HitObject_WorldRayOrigin";
1658+
case DXIL::OpCode::HitObject_ObjectRayDirection:
1659+
return "HitObject_ObjectRayDirection";
1660+
case DXIL::OpCode::HitObject_WorldToObject3x4:
1661+
return "HitObject_WorldToObject3x4";
1662+
case DXIL::OpCode::HitObject_ObjectToWorld3x4:
1663+
return "HitObject_ObjectToWorld3x4";
1664+
}
1665+
}
1666+
1667+
static void ValidateConstantRangeUnsigned(Value *Val, StringRef Name,
1668+
uint64_t LowerBound,
1669+
uint64_t UpperBound, CallInst *CI,
1670+
DXIL::OpCode OpCode,
1671+
ValidationContext &ValCtx) {
1672+
ConstantInt *C = dyn_cast<ConstantInt>(Val);
1673+
if (!C) {
1674+
ValCtx.EmitInstrFormatError(CI, ValidationRule::InstrOpConst,
1675+
{Name, GetOpCodeName(OpCode)});
1676+
return;
1677+
}
1678+
if (C->uge(UpperBound) || !C->uge(LowerBound)) {
1679+
std::string Range =
1680+
std::to_string(LowerBound) + "~" + std::to_string(UpperBound);
1681+
ValCtx.EmitInstrFormatError(
1682+
CI, ValidationRule::InstrOperandRange,
1683+
{Name, Range, C->getValue().toString(10, false)});
1684+
}
1685+
}
1686+
16471687
static void ValidateDxilOperationCallInProfile(CallInst *CI,
16481688
DXIL::OpCode Opcode,
16491689
const ShaderModel *pSM,
@@ -1910,6 +1950,76 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
19101950
CI, ValidationRule::InstrMayReorderThreadUndefCoherenceHintParam);
19111951
} break;
19121952

1953+
case DXIL::OpCode::HitObject_LoadLocalRootTableConstant: {
1954+
Value *HitObject = CI->getArgOperand(1);
1955+
if (isa<UndefValue>(HitObject))
1956+
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
1957+
Value *Offset = CI->getArgOperand(2);
1958+
if (isa<UndefValue>(Offset))
1959+
ValCtx.EmitInstrError(CI, ValidationRule::InstrNoReadingUninitialized);
1960+
if (ConstantInt *COffset = dyn_cast<ConstantInt>(Offset)) {
1961+
if (COffset->getLimitedValue() % 4 != 0)
1962+
ValCtx.EmitInstrFormatError(
1963+
CI, ValidationRule::InstrParamMultiple,
1964+
{"offset", "4", COffset->getValue().toString(10, false)});
1965+
}
1966+
break;
1967+
}
1968+
case DXIL::OpCode::HitObject_SetShaderTableIndex: {
1969+
Value *HitObject = CI->getArgOperand(1);
1970+
if (isa<UndefValue>(HitObject))
1971+
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
1972+
Value *RecordIndex = CI->getArgOperand(2);
1973+
if (isa<UndefValue>(RecordIndex))
1974+
ValCtx.EmitInstrError(CI, ValidationRule::InstrNoReadingUninitialized);
1975+
break;
1976+
}
1977+
1978+
// Shader Execution Reordering - scalar getters
1979+
case DXIL::OpCode::HitObject_GeometryIndex:
1980+
case DXIL::OpCode::HitObject_HitKind:
1981+
case DXIL::OpCode::HitObject_InstanceID:
1982+
case DXIL::OpCode::HitObject_InstanceIndex:
1983+
case DXIL::OpCode::HitObject_IsHit:
1984+
case DXIL::OpCode::HitObject_IsMiss:
1985+
case DXIL::OpCode::HitObject_IsNop:
1986+
case DXIL::OpCode::HitObject_PrimitiveIndex:
1987+
case DXIL::OpCode::HitObject_RayFlags:
1988+
case DXIL::OpCode::HitObject_RayTCurrent:
1989+
case DXIL::OpCode::HitObject_RayTMin:
1990+
case DXIL::OpCode::HitObject_ShaderTableIndex: {
1991+
Value *HitObject = CI->getArgOperand(1);
1992+
if (isa<UndefValue>(HitObject))
1993+
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
1994+
break;
1995+
}
1996+
1997+
// Shader Execution Reordering - vector getters
1998+
case DXIL::OpCode::HitObject_ObjectRayDirection:
1999+
case DXIL::OpCode::HitObject_ObjectRayOrigin:
2000+
case DXIL::OpCode::HitObject_WorldRayDirection:
2001+
case DXIL::OpCode::HitObject_WorldRayOrigin: {
2002+
Value *HitObject = CI->getArgOperand(1);
2003+
if (isa<UndefValue>(HitObject))
2004+
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
2005+
Value *Col = CI->getArgOperand(2);
2006+
ValidateConstantRangeUnsigned(Col, "component", 0, 2, CI, Opcode, ValCtx);
2007+
break;
2008+
}
2009+
2010+
// Shader Execution Reordering - matrix getters
2011+
case DXIL::OpCode::HitObject_WorldToObject3x4:
2012+
case DXIL::OpCode::HitObject_ObjectToWorld3x4: {
2013+
Value *HitObject = CI->getArgOperand(1);
2014+
if (isa<UndefValue>(HitObject))
2015+
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);
2016+
Value *Row = CI->getArgOperand(2);
2017+
ValidateConstantRangeUnsigned(Row, "row", 0, 2, CI, Opcode, ValCtx);
2018+
Value *Col = CI->getArgOperand(3);
2019+
ValidateConstantRangeUnsigned(Col, "column", 0, 3, CI, Opcode, ValCtx);
2020+
break;
2021+
}
2022+
19132023
case DXIL::OpCode::AtomicBinOp:
19142024
case DXIL::OpCode::AtomicCompareExchange: {
19152025
Type *pOverloadType = OP::GetOverloadType(Opcode, CI->getCalledFunction());

0 commit comments

Comments
 (0)