Skip to content

Commit 552b11b

Browse files
authored
[SPIRV] Add support vk::ext_execution_mode (#4086)
Add support * vk::ext_execution_mode * [[vk::ext_storage_class(uint storage_class)]] This is part of PRs for the #3919
1 parent f836555 commit 552b11b

11 files changed

Lines changed: 97 additions & 9 deletions

File tree

include/dxc/HlslIntrinsicOp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ enum class IntrinsicOp { IOP_AcceptHitAndEndSearch,
226226
#endif // ENABLE_SPIRV_CODEGEN
227227
#ifdef ENABLE_SPIRV_CODEGEN
228228
IOP_VkReadClock,
229+
#endif // ENABLE_SPIRV_CODEGEN
230+
#ifdef ENABLE_SPIRV_CODEGEN
231+
IOP_Vkext_execution_mode,
229232
#endif // ENABLE_SPIRV_CODEGEN
230233
MOP_Append,
231234
MOP_RestartStrip,

lib/HLSL/HLOperationLower.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5662,6 +5662,7 @@ IntrinsicLower gLowerTable[] = {
56625662
#ifdef ENABLE_SPIRV_CODEGEN
56635663
{ IntrinsicOp::IOP_VkReadClock, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes },
56645664
{ IntrinsicOp::IOP_VkRawBufferLoad, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes },
5665+
{ IntrinsicOp::IOP_Vkext_execution_mode, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes },
56655666
#endif // ENABLE_SPIRV_CODEGEN
56665667
{IntrinsicOp::MOP_Append, StreamOutputLower, DXIL::OpCode::EmitStream},
56675668
{IntrinsicOp::MOP_RestartStrip, StreamOutputLower, DXIL::OpCode::CutStream},

tools/clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,14 @@ def VKExtensionExt : InheritableAttr {
10501050
let Documentation = [Undocumented];
10511051
}
10521052

1053+
def VKStorageClassExt : InheritableAttr {
1054+
let Spellings = [CXX11<"vk", "ext_storage_class">];
1055+
let Subjects = SubjectList<[Var, ParmVar], ErrorDiag>;
1056+
let Args = [UnsignedArgument<"stclass">];
1057+
let LangOpts = [SPIRV];
1058+
let Documentation = [Undocumented];
1059+
}
1060+
10531061
// Global variables that are of struct type
10541062
def StructGlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage() && S->getType()->isStructureType()}]>;
10551063

tools/clang/include/clang/SPIRV/SpirvBuilder.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,10 @@ class SpirvBuilder {
554554
llvm::StringRef content = "");
555555

556556
/// \brief Adds an execution mode to the module under construction.
557-
inline void addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em,
558-
llvm::ArrayRef<uint32_t> params, SourceLocation);
557+
inline SpirvInstruction *addExecutionMode(SpirvFunction *entryPoint,
558+
spv::ExecutionMode em,
559+
llvm::ArrayRef<uint32_t> params,
560+
SourceLocation);
559561

560562
/// \brief Adds an OpModuleProcessed instruction to the module under
561563
/// construction.
@@ -854,12 +856,15 @@ SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor,
854856
return mainSource->getFile();
855857
}
856858

857-
void SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint,
858-
spv::ExecutionMode em,
859-
llvm::ArrayRef<uint32_t> params,
860-
SourceLocation loc) {
861-
mod->addExecutionMode(
862-
new (context) SpirvExecutionMode(loc, entryPoint, em, params, false));
859+
SpirvInstruction *
860+
SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em,
861+
llvm::ArrayRef<uint32_t> params,
862+
SourceLocation loc) {
863+
auto mode =
864+
new (context) SpirvExecutionMode(loc, entryPoint, em, params, false);
865+
mod->addExecutionMode(mode);
866+
867+
return mode;
863868
}
864869

865870
} // end namespace spirv

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1659,8 +1659,11 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) {
16591659
needsLegalization = true;
16601660
}
16611661

1662-
if (var != nullptr) {
1662+
if (var != nullptr && decl->hasAttrs()) {
16631663
declIdMapper.decorateVariableWithIntrinsicAttrs(decl, var);
1664+
if (auto attr = decl->getAttr<VKStorageClassExtAttr>()) {
1665+
var->setStorageClass(static_cast<spv::StorageClass>(attr->getStclass()));
1666+
}
16641667
}
16651668

16661669
// All variables that are of opaque struct types should request legalization.
@@ -7637,6 +7640,9 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
76377640
case hlsl::IntrinsicOp::IOP_VkRawBufferLoad:
76387641
retVal = processRawBufferLoad(callExpr);
76397642
break;
7643+
case hlsl::IntrinsicOp::IOP_Vkext_execution_mode:
7644+
retVal = processIntrinsicExecutionMode(callExpr);
7645+
break;
76407646
case hlsl::IntrinsicOp::IOP_saturate:
76417647
retVal = processIntrinsicSaturate(callExpr);
76427648
break;
@@ -12569,6 +12575,32 @@ SpirvInstruction *SpirvEmitter::processRawBufferLoad(const CallExpr *callExpr) {
1256912575
return loadInst;
1257012576
}
1257112577

12578+
SpirvInstruction *
12579+
SpirvEmitter::processIntrinsicExecutionMode(const CallExpr *expr) {
12580+
llvm::SmallVector<uint32_t, 2> execModesParams;
12581+
uint32_t exeMode = 0;
12582+
const auto args = expr->getArgs();
12583+
for (uint32_t i = 0; i < expr->getNumArgs(); ++i) {
12584+
SpirvConstantInteger *argInst =
12585+
dyn_cast<SpirvConstantInteger>(doExpr(args[i]));
12586+
if (argInst == nullptr) {
12587+
emitError("argument should be constant interger", expr->getExprLoc());
12588+
return nullptr;
12589+
}
12590+
unsigned argInteger = argInst->getValue().getZExtValue();
12591+
if (i > 0)
12592+
execModesParams.push_back(argInteger);
12593+
else
12594+
exeMode = argInteger;
12595+
}
12596+
assert(entryFunction != nullptr);
12597+
assert(exeMode != 0);
12598+
12599+
return spvBuilder.addExecutionMode(entryFunction,
12600+
static_cast<spv::ExecutionMode>(exeMode),
12601+
execModesParams, expr->getExprLoc());
12602+
}
12603+
1257212604
bool SpirvEmitter::spirvToolsValidate(std::vector<uint32_t> *mod,
1257312605
std::string *messages) {
1257412606
spvtools::SpirvTools tools(featureManager.getTargetEnv());

tools/clang/lib/SPIRV/SpirvEmitter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,8 @@ class SpirvEmitter : public ASTConsumer {
599599

600600
/// Custom intrinsic to support basic buffer_reference use case
601601
SpirvInstruction *processRawBufferLoad(const CallExpr *callExpr);
602+
/// Process vk::ext_execution_mode intrinsic
603+
SpirvInstruction *processIntrinsicExecutionMode(const CallExpr *expr);
602604

603605
private:
604606
/// Returns the <result-id> for constant value 0 of the given type.

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12090,6 +12090,11 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
1209012090
ValidateAttributeStringArg(S, A, nullptr, 1),
1209112091
A.getAttributeSpellingListIndex());
1209212092
break;
12093+
case AttributeList::AT_VKStorageClassExt:
12094+
declAttr = ::new (S.Context) VKStorageClassExtAttr(
12095+
A.getRange(), S.Context, unsigned(ValidateAttributeIntArg(S, A)),
12096+
A.getAttributeSpellingListIndex());
12097+
break;
1209312098
default:
1209412099
Handled = false;
1209512100
return;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %dxc -T ps_6_0 -E main -spirv
2+
3+
4+
// CHECK: OpExecutionMode {{%\w+}} StencilRefReplacingEXT
5+
// CHECK: OpExecutionMode {{%\w+}} SubgroupSize 32
6+
// CHECK: OpDecorate {{%\w+}} BuiltIn FragStencilRefEXT
7+
8+
[[vk::ext_decorate(11, 5014)]]
9+
int main() : SV_Target0 {
10+
11+
vk::ext_execution_mode(/*StencilRefReplacingEXT*/5027);
12+
vk::ext_execution_mode(/*SubgroupSize*/35, 32);
13+
return 3;
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %dxc -T ps_6_0 -E main -spirv -Vd
2+
3+
//CHECK: [[payloadTy:%\w+]] = OpTypeStruct %v4float
4+
//CHECK-NEXT: [[payloadTyPtr:%\w+]] = OpTypePointer RayPayloadNV [[payloadTy]]
5+
//CHECK: [[crossTy:%\w+]] = OpTypePointer CrossWorkgroup %int
6+
//CHECK: {{%\w+}} = OpVariable [[payloadTyPtr]] RayPayloadNV
7+
//CHECK: {{%\w+}} = OpVariable [[crossTy]] CrossWorkgroup
8+
9+
[[vk::ext_storage_class(/*RayPayloadNV*/5338)]]
10+
float4 payload;
11+
12+
int main() : SV_Target0 {
13+
[[vk::ext_storage_class(/* CrossWorkgroup */ 5)]] int foo = 3;
14+
return foo;
15+
}

tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,8 @@ TEST_F(FileTest, IntrinsicsSpirv) {
13461346
runFileTest("spv.intrinsicInstruction.hlsl");
13471347
runFileTest("spv.intrinsicLiteral.hlsl");
13481348
runFileTest("spv.intrinsicDecorate.hlsl", Expect::Success, false);
1349+
runFileTest("spv.intrinsicExecutionMode.hlsl", Expect::Success, false);
1350+
runFileTest("spv.intrinsicStorageClass.hlsl", Expect::Success, false);
13491351
runFileTest("spv.intrinsic.reference.error.hlsl", Expect::Failure);
13501352
}
13511353
TEST_F(FileTest, IntrinsicsVkReadClock) {

0 commit comments

Comments
 (0)