Skip to content

Commit

Permalink
[spirv] support [[vk::ext_decorate_id]] attribute
Browse files Browse the repository at this point in the history
As a part of HLSL version of GL_EXT_spirv_intrinsics, this commit adds
vk::ext_decorate_id attribute.

Related to microsoft#3919
  • Loading branch information
jaebaek committed Jan 18, 2022
1 parent de586d3 commit d19d74a
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 55 deletions.
5 changes: 5 additions & 0 deletions tools/clang/include/clang/SPIRV/SpirvBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,11 @@ class SpirvBuilder {
void decorateWithLiterals(SpirvInstruction *targetInst, unsigned decorate,
llvm::ArrayRef<unsigned> literals, SourceLocation);

/// \brief Decorates the given target with result ids of SPIR-V
/// instructions.
void decorateWithIds(SpirvInstruction *targetInst, unsigned decorate,
llvm::ArrayRef<SpirvInstruction *> ids, SourceLocation);

/// \brief Decorates the given target with the given strings.
void decorateWithStrings(SpirvInstruction *target, unsigned decorate,
llvm::ArrayRef<llvm::StringRef> strLiteral,
Expand Down
49 changes: 26 additions & 23 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2474,23 +2474,7 @@ bool DeclResultIdMapper::createStageVars(
stageVar.getStorageClass() == spv::StorageClass::Output) {
stageVar.setEntryPoint(entryFunction);
}

if (decl->hasAttr<VKDecorateExtAttr>()) {
auto checkBuiltInLocationDecoration =
[&stageVar](const VKDecorateExtAttr *decoAttr) {
auto decorate =
static_cast<spv::Decoration>(decoAttr->getDecorate());
if (decorate == spv::Decoration::BuiltIn ||
decorate == spv::Decoration::Location) {
// This information will be used to avoid
// assigning multiple location decorations
// in finalizeStageIOLocations()
stageVar.setIsLocOrBuiltinDecorateAttr();
}
};
decorateWithIntrinsicAttrs(decl, varInstr,
checkBuiltInLocationDecoration);
}
decorateStageVarWithIntrinsicAttrs(decl, &stageVar, varInstr);
stageVars.push_back(stageVar);

// Emit OpDecorate* instructions to link this stage variable with the HLSL
Expand Down Expand Up @@ -3993,14 +3977,13 @@ void DeclResultIdMapper::tryToCreateImplicitConstVar(const ValueDecl *decl) {
astDecls[varDecl].instr = constVal;
}

template <typename Functor>
void DeclResultIdMapper::decorateWithIntrinsicAttrs(
const NamedDecl *decl, SpirvVariable *varInst,
Functor extraFunctionForDecoAttr) {
llvm::function_ref<void(VKDecorateExtAttr *)> extraFunctionForDecoAttr) {
if (!decl->hasAttrs())
return;

// TODO: Handle member field in a struct.
// TODO: Handle member field in a struct and function parameter.
for (auto &attr : decl->getAttrs()) {
if (auto decoAttr = dyn_cast<VKDecorateExtAttr>(attr)) {
spvBuilder.decorateWithLiterals(
Expand All @@ -4010,6 +3993,15 @@ void DeclResultIdMapper::decorateWithIntrinsicAttrs(
extraFunctionForDecoAttr(decoAttr);
continue;
}
if (auto decoAttr = dyn_cast<VKDecorateIdExtAttr>(attr)) {
llvm::SmallVector<SpirvInstruction *, 2> args;
for (Expr *arg : decoAttr->arguments()) {
args.push_back(theEmitter.doExpr(arg));
}
spvBuilder.decorateWithIds(varInst, decoAttr->getDecorate(), args,
varInst->getSourceLocation());
continue;
}
if (auto decoAttr = dyn_cast<VKDecorateStringExtAttr>(attr)) {
llvm::SmallVector<llvm::StringRef, 2> args(decoAttr->arguments_begin(),
decoAttr->arguments_end());
Expand All @@ -4020,9 +4012,20 @@ void DeclResultIdMapper::decorateWithIntrinsicAttrs(
}
}

void DeclResultIdMapper::decorateVariableWithIntrinsicAttrs(
const NamedDecl *decl, SpirvVariable *varInst) {
decorateWithIntrinsicAttrs(decl, varInst, [](VKDecorateExtAttr *) {});
void DeclResultIdMapper::decorateStageVarWithIntrinsicAttrs(
const NamedDecl *decl, StageVar *stageVar, SpirvVariable *varInst) {
auto checkBuiltInLocationDecoration =
[stageVar](const VKDecorateExtAttr *decoAttr) {
auto decorate = static_cast<spv::Decoration>(decoAttr->getDecorate());
if (decorate == spv::Decoration::BuiltIn ||
decorate == spv::Decoration::Location) {
// This information will be used to avoid
// assigning multiple location decorations
// in finalizeStageIOLocations()
stageVar->setIsLocOrBuiltinDecorateAttr();
}
};
decorateWithIntrinsicAttrs(decl, varInst, checkBuiltInLocationDecoration);
}

void DeclResultIdMapper::copyHullOutStageVarsToOutputPatch(
Expand Down
20 changes: 12 additions & 8 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,9 +617,12 @@ class DeclResultIdMapper {
return value;
}

/// \brief Decorate variable with spirv intrinsic attributes
void decorateVariableWithIntrinsicAttrs(const NamedDecl *decl,
SpirvVariable *varInst);
/// Decorate with spirv intrinsic attributes with lamda function variable
/// check
void decorateWithIntrinsicAttrs(
const NamedDecl *decl, SpirvVariable *varInst,
llvm::function_ref<void(VKDecorateExtAttr *)> extraFunctionForDecoAttr =
[](VKDecorateExtAttr *) {});

/// \brief Creates instructions to load the value of output stage variable
/// defined by outputPatchDecl and store it to ptr. Since the output stage
Expand Down Expand Up @@ -848,11 +851,12 @@ class DeclResultIdMapper {
bool getImplicitRegisterType(const ResourceVar &var,
char *registerTypeOut) const;

/// Decorate with spirv intrinsic attributes with lamda function variable
/// check
template <typename Functor>
void decorateWithIntrinsicAttrs(const NamedDecl *decl, SpirvVariable *varInst,
Functor func);
/// \brief Decorates stage variable with spirv intrinsic attributes. If
/// it is BuiltIn or Location decoration, sets locOrBuiltinDecorateAttr
/// of stageVar as true.
void decorateStageVarWithIntrinsicAttrs(const NamedDecl *decl,
StageVar *stageVar,
SpirvVariable *varInst);

private:
SpirvBuilder &spvBuilder;
Expand Down
10 changes: 10 additions & 0 deletions tools/clang/lib/SPIRV/SpirvBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,16 @@ void SpirvBuilder::decorateWithLiterals(SpirvInstruction *targetInst,
mod->addDecoration(decor);
}

void SpirvBuilder::decorateWithIds(SpirvInstruction *targetInst,
unsigned decorate,
llvm::ArrayRef<SpirvInstruction *> ids,
SourceLocation srcLoc) {
SpirvDecoration *decor = new (context) SpirvDecoration(
srcLoc, targetInst, static_cast<spv::Decoration>(decorate), ids);
assert(decor != nullptr);
mod->addDecoration(decor);
}

void SpirvBuilder::decorateWithStrings(
SpirvInstruction *target, unsigned decorate,
llvm::ArrayRef<llvm::StringRef> strLiteral, SourceLocation srcLoc) {
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,7 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) {
}

if (var != nullptr && decl->hasAttrs()) {
declIdMapper.decorateVariableWithIntrinsicAttrs(decl, var);
declIdMapper.decorateWithIntrinsicAttrs(decl, var);
if (auto attr = decl->getAttr<VKStorageClassExtAttr>()) {
var->setStorageClass(static_cast<spv::StorageClass>(attr->getStclass()));
}
Expand Down
31 changes: 31 additions & 0 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11891,6 +11891,37 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
declAttr = ::new (S.Context) HLSLRayPayloadAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
// SPIRV Change Starts
case AttributeList::AT_VKDecorateIdExt: {
if (A.getNumArgs() == 0 || !A.getArg(0).is<clang::Expr *>()) {
Handled = false;
break;
}

unsigned decoration = 0;
if (IntegerLiteral *decorationAsLiteral =
dyn_cast<IntegerLiteral>(A.getArg(0).get<clang::Expr *>())) {
decoration = decorationAsLiteral->getValue().getZExtValue();
} else {
Handled = false;
break;
}

llvm::SmallVector<Expr *, 2> args;
for (unsigned i = 1; i < A.getNumArgs(); ++i) {
if (!A.getArg(i).is<clang::Expr *>()) {
Handled = false;
break;
}
args.push_back(A.getArg(i).get<clang::Expr *>());
}
if (!Handled)
break;
declAttr = ::new (S.Context)
VKDecorateIdExtAttr(A.getRange(), S.Context, decoration, args.data(),
args.size(), A.getAttributeSpellingListIndex());
} break;
// SPIRV Change Ends

default:
Handled = false;
Expand Down
58 changes: 35 additions & 23 deletions tools/clang/test/CodeGenSPIRV/spv.intrinsicDecorate.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
[[vk::ext_decorate(1, 0)]]
bool b0;

[[vk::ext_decorate(30, 23)]]
float4 main(
int getAlignment() {
return 16;
}

//CHECK: OpDecorate {{%\w+}} SpecId 0
//CHECK: OpDecorate {{%\w+}} BuiltIn BaryCoordNoPerspAMD
Expand All @@ -15,25 +16,36 @@ float4 main(
//CHECK: OpDecorate {{%\w+}} BuiltIn BaryCoordSmoothSampleAMD
//CHECK: OpDecorate {{%\w+}} BuiltIn BaryCoordPullModelAMD
//CHECK: OpDecorate {{%\w+}} ExplicitInterpAMD
//CHECK: OpDecorate {{%\w+}} Location 23
//CHECK: OpDecorateString {{%\w+}} UserSemantic "return variable"
//CHECK: OpDecorate {{%\w+}} FPRoundingMode RTE

// spv::Decoration::builtIn = 11
[[vk::ext_decorate(11, 4992)]] float2 b0 : COLOR0,
[[vk::ext_decorate(11, 4993)]] float2 b1 : COLOR1,
[[vk::ext_decorate(11, 4994)]] float2 b2 : COLOR2,
[[vk::ext_decorate(11, 4995)]] float2 b3 : COLOR3,
[[vk::ext_decorate(11, 4996)]] float2 b4 : COLOR4,
[[vk::ext_decorate(11, 4997)]] float2 b5 : COLOR5,
[[vk::ext_decorate(11, 4998)]] float2 b6 : COLOR6,
// ExplicitInterpAMD
[[vk::location(12), vk::ext_decorate(4999)]] float2 b7 : COLOR7
) : SV_Target {

// spv::Decoration::FPRoundingMode = 39, RTZ=0
[[vk::ext_decorate(39, 0), vk::ext_decorate_string(5635, "return variable")]] float4 ret = 1.0;
ret.xy = b0 * b1 + b2 + b3 + b4;
ret.zw = b5 + b6 + b7;
return ret;

//CHECK-DAG: OpDecorate {{%\w+}} Location 23
//CHECK-DAG: OpDecorateString {{%\w+}} UserSemantic "return variable"
//CHECK-DAG: OpDecorate {{%\w+}} FPRoundingMode RTE

//CHECK-DAG: OpDecorateId {{%\w+}} AlignmentId [[alignment:%\w+]]
//CHECK-DAG: OpDecorateId {{%\w+}} UniformId %int_13
//CHECK-DAG: [[alignment]] = OpFunctionCall %int %getAlignment

[[vk::ext_decorate(30, 23)]]
float4 main(
// spv::Decoration::builtIn = 11
[[vk::ext_decorate(11, 4992)]] float2 b0 : COLOR0,
[[vk::ext_decorate(11, 4993)]] float2 b1 : COLOR1,
[[vk::ext_decorate(11, 4994)]] float2 b2 : COLOR2,
[[vk::ext_decorate(11, 4995)]] float2 b3 : COLOR3,
[[vk::ext_decorate(11, 4996)]] float2 b4 : COLOR4,
[[vk::ext_decorate(11, 4997)]] float2 b5 : COLOR5,
[[vk::ext_decorate(11, 4998)]] float2 b6 : COLOR6,
// ExplicitInterpAMD
[[vk::location(12), vk::ext_decorate(4999)]] float2 b7 : COLOR7,
[[vk::location(13), vk::ext_decorate_id(/* AlignmentId */ 46, getAlignment())]]
int foo : FOO
) : SV_Target {
[[vk::ext_decorate_id(/* UniformId */ 27, 13)]]
int bar;

// spv::Decoration::FPRoundingMode = 39, RTZ=0
[[vk::ext_decorate(39, 0), vk::ext_decorate_string(5635, "return variable")]] float4 ret = 1.0;
ret.xy = b0 * b1 + b2 + b3 + b4;
ret.zw = b5 + b6 + b7;
return ret;
}

0 comments on commit d19d74a

Please sign in to comment.