Skip to content

Commit 53f5b21

Browse files
author
Greg Roth
committed
Introduce native vector DXIL load/store intrinsics
Add new raw buffer vector load/store intrinsics using the new vector overload types. Include them in validation associated with similar load/stores
1 parent cdaca3f commit 53f5b21

5 files changed

Lines changed: 229 additions & 8 deletions

File tree

include/dxc/DXIL/DxilConstants.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,11 @@ enum class OpCode : unsigned {
898898
GetDimensions = 72, // gets texture size information
899899
RawBufferLoad = 139, // reads from a raw buffer and structured buffer
900900
RawBufferStore = 140, // writes to a RWByteAddressBuffer or RWStructuredBuffer
901-
TextureLoad = 66, // reads texel data without any filtering or sampling
902-
TextureStore = 67, // reads texel data without any filtering or sampling
901+
RawBufferVectorLoad = 303, // reads from a raw buffer and structured buffer
902+
RawBufferVectorStore =
903+
304, // writes to a RWByteAddressBuffer or RWStructuredBuffer
904+
TextureLoad = 66, // reads texel data without any filtering or sampling
905+
TextureStore = 67, // reads texel data without any filtering or sampling
903906
TextureStoreSample = 225, // stores texel data at specified sample index
904907

905908
// Sampler Feedback
@@ -1043,8 +1046,9 @@ enum class OpCode : unsigned {
10431046
NumOpCodes_Dxil_1_6 = 222,
10441047
NumOpCodes_Dxil_1_7 = 226,
10451048
NumOpCodes_Dxil_1_8 = 258,
1049+
NumOpCodes_Dxil_1_9 = 305,
10461050

1047-
NumOpCodes = 303 // exclusive last value of enumeration
1051+
NumOpCodes = 305 // exclusive last value of enumeration
10481052
};
10491053
// OPCODE-ENUM:END
10501054

@@ -1278,6 +1282,8 @@ enum class OpCodeClass : unsigned {
12781282
GetDimensions,
12791283
RawBufferLoad,
12801284
RawBufferStore,
1285+
RawBufferVectorLoad,
1286+
RawBufferVectorStore,
12811287
TextureLoad,
12821288
TextureStore,
12831289
TextureStoreSample,
@@ -1355,8 +1361,9 @@ enum class OpCodeClass : unsigned {
13551361
NumOpClasses_Dxil_1_6 = 149,
13561362
NumOpClasses_Dxil_1_7 = 153,
13571363
NumOpClasses_Dxil_1_8 = 174,
1364+
NumOpClasses_Dxil_1_9 = 179,
13581365

1359-
NumOpClasses = 177 // exclusive last value of enumeration
1366+
NumOpClasses = 179 // exclusive last value of enumeration
13601367
};
13611368
// OPCODECLASS-ENUM:END
13621369

include/dxc/DXIL/DxilInstructions.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8923,5 +8923,98 @@ struct DxilInst_HitObject_MakeNop {
89238923
// Metadata
89248924
bool requiresUniformInputs() const { return false; }
89258925
};
8926+
8927+
/// This instruction reads from a raw buffer and structured buffer
8928+
struct DxilInst_RawBufferVectorLoad {
8929+
llvm::Instruction *Instr;
8930+
// Construction and identification
8931+
DxilInst_RawBufferVectorLoad(llvm::Instruction *pInstr) : Instr(pInstr) {}
8932+
operator bool() const {
8933+
return hlsl::OP::IsDxilOpFuncCallInst(
8934+
Instr, hlsl::OP::OpCode::RawBufferVectorLoad);
8935+
}
8936+
// Validation support
8937+
bool isAllowed() const { return true; }
8938+
bool isArgumentListValid() const {
8939+
if (5 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
8940+
return false;
8941+
return true;
8942+
}
8943+
// Metadata
8944+
bool requiresUniformInputs() const { return false; }
8945+
// Operand indexes
8946+
enum OperandIdx {
8947+
arg_buf = 1,
8948+
arg_index = 2,
8949+
arg_elementOffset = 3,
8950+
arg_alignment = 4,
8951+
};
8952+
// Accessors
8953+
llvm::Value *get_buf() const { return Instr->getOperand(1); }
8954+
void set_buf(llvm::Value *val) { Instr->setOperand(1, val); }
8955+
llvm::Value *get_index() const { return Instr->getOperand(2); }
8956+
void set_index(llvm::Value *val) { Instr->setOperand(2, val); }
8957+
llvm::Value *get_elementOffset() const { return Instr->getOperand(3); }
8958+
void set_elementOffset(llvm::Value *val) { Instr->setOperand(3, val); }
8959+
llvm::Value *get_alignment() const { return Instr->getOperand(4); }
8960+
void set_alignment(llvm::Value *val) { Instr->setOperand(4, val); }
8961+
int32_t get_alignment_val() const {
8962+
return (int32_t)(llvm::dyn_cast<llvm::ConstantInt>(Instr->getOperand(4))
8963+
->getZExtValue());
8964+
}
8965+
void set_alignment_val(int32_t val) {
8966+
Instr->setOperand(4, llvm::Constant::getIntegerValue(
8967+
llvm::IntegerType::get(Instr->getContext(), 32),
8968+
llvm::APInt(32, (uint64_t)val)));
8969+
}
8970+
};
8971+
8972+
/// This instruction writes to a RWByteAddressBuffer or RWStructuredBuffer
8973+
struct DxilInst_RawBufferVectorStore {
8974+
llvm::Instruction *Instr;
8975+
// Construction and identification
8976+
DxilInst_RawBufferVectorStore(llvm::Instruction *pInstr) : Instr(pInstr) {}
8977+
operator bool() const {
8978+
return hlsl::OP::IsDxilOpFuncCallInst(
8979+
Instr, hlsl::OP::OpCode::RawBufferVectorStore);
8980+
}
8981+
// Validation support
8982+
bool isAllowed() const { return true; }
8983+
bool isArgumentListValid() const {
8984+
if (6 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
8985+
return false;
8986+
return true;
8987+
}
8988+
// Metadata
8989+
bool requiresUniformInputs() const { return false; }
8990+
// Operand indexes
8991+
enum OperandIdx {
8992+
arg_uav = 1,
8993+
arg_index = 2,
8994+
arg_elementOffset = 3,
8995+
arg_value0 = 4,
8996+
arg_alignment = 5,
8997+
};
8998+
// Accessors
8999+
llvm::Value *get_uav() const { return Instr->getOperand(1); }
9000+
void set_uav(llvm::Value *val) { Instr->setOperand(1, val); }
9001+
llvm::Value *get_index() const { return Instr->getOperand(2); }
9002+
void set_index(llvm::Value *val) { Instr->setOperand(2, val); }
9003+
llvm::Value *get_elementOffset() const { return Instr->getOperand(3); }
9004+
void set_elementOffset(llvm::Value *val) { Instr->setOperand(3, val); }
9005+
llvm::Value *get_value0() const { return Instr->getOperand(4); }
9006+
void set_value0(llvm::Value *val) { Instr->setOperand(4, val); }
9007+
llvm::Value *get_alignment() const { return Instr->getOperand(5); }
9008+
void set_alignment(llvm::Value *val) { Instr->setOperand(5, val); }
9009+
int32_t get_alignment_val() const {
9010+
return (int32_t)(llvm::dyn_cast<llvm::ConstantInt>(Instr->getOperand(5))
9011+
->getZExtValue());
9012+
}
9013+
void set_alignment_val(int32_t val) {
9014+
Instr->setOperand(5, llvm::Constant::getIntegerValue(
9015+
llvm::IntegerType::get(Instr->getContext(), 32),
9016+
llvm::APInt(32, (uint64_t)val)));
9017+
}
9018+
};
89269019
// INSTR-HELPER:END
89279020
} // namespace hlsl

lib/DXIL/DxilOperations.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,6 +2633,24 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
26332633
0,
26342634
{},
26352635
{}}, // Overloads: v
2636+
2637+
// Resources
2638+
{OC::RawBufferVectorLoad,
2639+
"RawBufferVectorLoad",
2640+
OCC::RawBufferVectorLoad,
2641+
"rawBufferVectorLoad",
2642+
Attribute::ReadOnly,
2643+
1,
2644+
{{0x4e7}},
2645+
{{0xe7}}}, // Overloads: hfwidl<hfwidl
2646+
{OC::RawBufferVectorStore,
2647+
"RawBufferVectorStore",
2648+
OCC::RawBufferVectorStore,
2649+
"rawBufferVectorStore",
2650+
Attribute::None,
2651+
1,
2652+
{{0x4e7}},
2653+
{{0xe7}}}, // Overloads: hfwidl<hfwidl
26362654
};
26372655
// OPCODE-OLOADS:END
26382656

@@ -3390,8 +3408,9 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
33903408
}
33913409
return;
33923410
}
3393-
// Instructions: AllocateRayQuery2=258
3394-
if (op == 258) {
3411+
// Instructions: AllocateRayQuery2=258, RawBufferVectorLoad=303,
3412+
// RawBufferVectorStore=304
3413+
if (op == 258 || (303 <= op && op <= 304)) {
33953414
major = 6;
33963415
minor = 9;
33973416
return;
@@ -5739,6 +5758,25 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
57395758
A(pV);
57405759
A(pI32);
57415760
break;
5761+
5762+
// Resources
5763+
case OpCode::RawBufferVectorLoad:
5764+
RRT(pETy);
5765+
A(pI32);
5766+
A(pRes);
5767+
A(pI32);
5768+
A(pI32);
5769+
A(pI32);
5770+
break;
5771+
case OpCode::RawBufferVectorStore:
5772+
A(pV);
5773+
A(pI32);
5774+
A(pRes);
5775+
A(pI32);
5776+
A(pI32);
5777+
A(pETy);
5778+
A(pI32);
5779+
break;
57425780
// OPCODE-OLOAD-FUNCS:END
57435781
default:
57445782
DXASSERT(false, "otherwise unhandled case");
@@ -5888,6 +5926,7 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) {
58885926
case OpCode::StoreVertexOutput:
58895927
case OpCode::StorePrimitiveOutput:
58905928
case OpCode::DispatchMesh:
5929+
case OpCode::RawBufferVectorStore:
58915930
if (FT->getNumParams() <= 4)
58925931
return nullptr;
58935932
return FT->getParamType(4);
@@ -6134,7 +6173,8 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) {
61346173
case OpCode::TextureGatherRaw:
61356174
case OpCode::SampleCmpLevel:
61366175
case OpCode::SampleCmpGrad:
6137-
case OpCode::SampleCmpBias: {
6176+
case OpCode::SampleCmpBias:
6177+
case OpCode::RawBufferVectorLoad: {
61386178
StructType *ST = cast<StructType>(Ty);
61396179
return ST->getElementType(0);
61406180
}

lib/DxilValidation/DxilValidation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,8 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
16841684
case DXIL::OpCode::CBufferLoadLegacy:
16851685
case DXIL::OpCode::RawBufferLoad:
16861686
case DXIL::OpCode::RawBufferStore:
1687+
case DXIL::OpCode::RawBufferVectorLoad:
1688+
case DXIL::OpCode::RawBufferVectorStore:
16871689
ValidateResourceDxilOp(CI, opcode, ValCtx);
16881690
break;
16891691
// Input output.

utils/hct/hctdb.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ def populate_categories_and_models(self):
477477
self.name_idx[i].category = "Dot"
478478
for (
479479
i
480-
) in "CreateHandle,CBufferLoad,CBufferLoadLegacy,TextureLoad,TextureStore,TextureStoreSample,BufferLoad,BufferStore,BufferUpdateCounter,CheckAccessFullyMapped,GetDimensions,RawBufferLoad,RawBufferStore".split(
480+
) in "CreateHandle,CBufferLoad,CBufferLoadLegacy,TextureLoad,TextureStore,TextureStoreSample,BufferLoad,BufferStore,BufferUpdateCounter,CheckAccessFullyMapped,GetDimensions,RawBufferLoad,RawBufferStore,RawBufferVectorLoad,RawBufferVectorStore".split(
481481
","
482482
):
483483
self.name_idx[i].category = "Resources"
@@ -604,6 +604,8 @@ def populate_categories_and_models(self):
604604
for i in "RawBufferLoad,RawBufferStore".split(","):
605605
self.name_idx[i].shader_model = 6, 2
606606
self.name_idx[i].shader_model_translated = 6, 0
607+
for i in "RawBufferVectorLoad,RawBufferVectorStore".split(","):
608+
self.name_idx[i].shader_model = 6, 9
607609
for i in "DispatchRaysIndex,DispatchRaysDimensions".split(","):
608610
self.name_idx[i].category = "Ray Dispatch Arguments"
609611
self.name_idx[i].shader_model = 6, 3
@@ -5776,6 +5778,83 @@ def UFI(name, **mappings):
57765778
# Reserved block C
57775779
next_op_idx = self.reserve_dxil_op_range("ReservedC", next_op_idx, 10)
57785780

5781+
# Long Vectors
5782+
self.add_dxil_op(
5783+
"RawBufferVectorLoad",
5784+
next_op_idx,
5785+
"RawBufferVectorLoad",
5786+
"reads from a raw buffer and structured buffer",
5787+
"hfwidl<",
5788+
"ro",
5789+
[
5790+
db_dxil_param(0, "$r", "", "the loaded value"),
5791+
db_dxil_param(2, "res", "buf", "handle of Raw Buffer to load from"),
5792+
db_dxil_param(
5793+
3,
5794+
"i32",
5795+
"index",
5796+
"element index for StructuredBuffer, or byte offset for ByteAddressBuffer",
5797+
),
5798+
db_dxil_param(
5799+
4,
5800+
"i32",
5801+
"elementOffset",
5802+
"offset into element for StructuredBuffer, or undef for ByteAddressBuffer",
5803+
),
5804+
db_dxil_param(
5805+
5,
5806+
"i32",
5807+
"alignment",
5808+
"relative load access alignment",
5809+
is_const=True,
5810+
),
5811+
],
5812+
counters=("tex_load",),
5813+
)
5814+
next_op_idx += 1
5815+
5816+
self.add_dxil_op(
5817+
"RawBufferVectorStore",
5818+
next_op_idx,
5819+
"RawBufferVectorStore",
5820+
"writes to a RWByteAddressBuffer or RWStructuredBuffer",
5821+
"hfwidl<",
5822+
"",
5823+
[
5824+
db_dxil_param(0, "v", "", ""),
5825+
db_dxil_param(2, "res", "uav", "handle of UAV to store to"),
5826+
db_dxil_param(
5827+
3,
5828+
"i32",
5829+
"index",
5830+
"element index for StructuredBuffer, or byte offset for ByteAddressBuffer",
5831+
),
5832+
db_dxil_param(
5833+
4,
5834+
"i32",
5835+
"elementOffset",
5836+
"offset into element for StructuredBuffer, or undef for ByteAddressBuffer",
5837+
),
5838+
db_dxil_param(5, "$o", "value0", "value"),
5839+
db_dxil_param(
5840+
6,
5841+
"i32",
5842+
"alignment",
5843+
"relative store access alignment",
5844+
is_const=True,
5845+
),
5846+
],
5847+
counters=("tex_store",),
5848+
)
5849+
next_op_idx += 1
5850+
5851+
# End of DXIL 1.9 opcodes.
5852+
self.set_op_count_for_version(1, 9, next_op_idx)
5853+
assert next_op_idx == 305, (
5854+
"305 is expected next operation index but encountered %d and thus opcodes are broken"
5855+
% next_op_idx
5856+
)
5857+
57795858
# Set interesting properties.
57805859
self.build_indices()
57815860
for (

0 commit comments

Comments
 (0)