Skip to content
Open
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
6 changes: 6 additions & 0 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/SaveAndRestore.h"

#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
#include "clang/Basic/Version.h"
Expand Down Expand Up @@ -1559,6 +1560,9 @@ bool SpirvEmitter::handleNodePayloadArrayType(const ParmVarDecl *decl,
}

void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
llvm::SaveAndRestore<const FunctionDecl *> savedCurFunctionDecl(
curFunctionDecl, decl);

// Forward declaration of a function inside another.
if (!decl->isThisDeclarationADefinition()) {
addFunctionToWorkQueue(spvContext.getCurrentShaderModelKind(), decl,
Expand Down Expand Up @@ -6658,6 +6662,8 @@ SpirvEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr,
auto *decl = cast<VarDecl>(declRefExpr->getDecl());
auto *var = declIdMapper.createResourceHeap(decl, resourceType);

if (hlsl::HasHLSLGloballyCoherent(resourceType))
spvBuilder.decorateCoherent(var, baseExpr->getExprLoc());
auto *index = doExpr(indexExpr);

if (spirvOptions.useDescriptorHeap) {
Expand Down
4 changes: 4 additions & 0 deletions tools/clang/lib/SPIRV/SpirvEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,10 @@ class SpirvEmitter : public ASTConsumer {

/// ParentMap of the current function.
std::unique_ptr<ParentMap> parentMap = nullptr;

/// AST FunctionDecl currently being lowered. Used by the descriptor-heap
/// access path to detect globallycoherent returning helpers.
const FunctionDecl *curFunctionDecl = nullptr;
};

void SpirvEmitter::doDeclStmt(const DeclStmt *declStmt) {
Expand Down
22 changes: 20 additions & 2 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9589,6 +9589,10 @@ clang::ExprResult HLSLExternalSource::PerformHLSLConversion(
clang::Sema::CheckedConversionKind CCK) {
QualType sourceType = From->getType();
sourceType = GetStructuralForm(sourceType);

// Store off the type attributes that could be accidentially dropped.
const bool targetGloballyCoherent = hlsl::HasHLSLGloballyCoherent(targetType);
const bool targetReorderCoherent = hlsl::HasHLSLReorderCoherent(targetType);
targetType = GetStructuralForm(targetType);
ArTypeInfo SourceInfo, TargetInfo;
CollectInfo(sourceType, &SourceInfo);
Expand All @@ -9605,9 +9609,23 @@ clang::ExprResult HLSLExternalSource::PerformHLSLConversion(
// convert that to an array of casts under a special kind of flat
// flat conversion node? What do component conversion casts cast
// from? We don't have a From expression for individiual components.
QualType flatCastType = targetType.getUnqualifiedType();
// Preserve coherence qualifiers when converting to a resource type so the
// converted expression's type still reflects the coherence of its
// destination.
if (hlsl::IsHLSLResourceType(flatCastType)) {
if (targetGloballyCoherent)
flatCastType = m_context->getAttributedType(
AttributedType::attr_hlsl_globallycoherent, flatCastType,
flatCastType);
else if (targetReorderCoherent)
flatCastType = m_context->getAttributedType(
AttributedType::attr_hlsl_reordercoherent, flatCastType,
flatCastType);
}
From = m_sema
->ImpCastExprToType(From, targetType.getUnqualifiedType(),
CK_FlatConversion, From->getValueKind(),
->ImpCastExprToType(From, flatCastType, CK_FlatConversion,
From->getValueKind(),
/*BasePath=*/0, CCK)
.get();
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %dxc -T lib_6_9 %s | FileCheck %s
// REQUIRES: dxil-1-9

// Initializing a coherent resource from ResourceDescriptorHeap[] goes through a
// flat-conversion. Verify the coherence qualifier of the destination is carried
// through to the annotated handle properties in the generated DXIL.

RWBuffer<float> OutBuf : register(u0);

// CHECK: call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218
// CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %{{.*}}, %dx.types.ResourceProperties { i32 20491, i32 0 })
// CHECK-SAME: resource: globallycoherent RWByteAddressBuffer
[shader("raygeneration")]
void glc_entry()
{
globallycoherent RWByteAddressBuffer buf = ResourceDescriptorHeap[0];
buf.Store(0, 0);
}

// CHECK: call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218
// CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %{{.*}}, %dx.types.ResourceProperties { i32 69642, i32 265 })
// CHECK-SAME: resource: reordercoherent RWTypedBuffer<F32>
[shader("raygeneration")]
void rc_entry()
{
reordercoherent RWBuffer<float> buf = ResourceDescriptorHeap[1];
OutBuf[0] = buf[0];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// RUN: %dxc -T cs_6_6 -E CSMain -spirv -DTYPE=0 %s | FileCheck %s --check-prefix=TYPE0
// RUN: %dxc -T cs_6_6 -E CSMain -spirv -DTYPE=1 %s | FileCheck %s --check-prefix=TYPE1
// RUN: %dxc -T cs_6_6 -E CSMain -spirv -DTYPE=2 %s | FileCheck %s --check-prefix=TYPE2
// RUN: %dxc -T cs_6_6 -E CSMain -spirv -DTYPE=3 %s | FileCheck %s --check-prefix=TYPE3

// TYPE=0: direct ResourceDescriptorHeap[] init of a `globallycoherent` static.
// TYPE0-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} DescriptorSet 0
// TYPE0-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} Binding 0
// TYPE0-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} Coherent

// TYPE=1: bindless array carries the qualifier.
// TYPE1-DAG: OpDecorate %FakeHeapOfA DescriptorSet 0
// TYPE1-DAG: OpDecorate %FakeHeapOfA Binding 0
// TYPE1-DAG: OpDecorate %FakeHeapOfA Coherent

// TYPE=2: stand-alone `globallycoherent` UAV.
// TYPE2-DAG: OpDecorate %A DescriptorSet 0
// TYPE2-DAG: OpDecorate %A Binding 0
// TYPE2-DAG: OpDecorate %A Coherent

// TYPE=3: heap access lives inside a `globallycoherent`-returning helper, and
// a `globallycoherent static` captures the result.
// TYPE3-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} DescriptorSet 0
// TYPE3-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} Binding {{[0-9]+}}
// TYPE3-DAG: OpDecorate %ResourceDescriptorHeap{{(_[0-9]+)?}} Coherent
// TYPE3-NOT: OpDecorate %Buf Coherent

#if TYPE == 0
globallycoherent static RWStructuredBuffer<uint> A = ResourceDescriptorHeap[0];
#elif TYPE == 1
globallycoherent RWStructuredBuffer<uint> FakeHeapOfA[];
globallycoherent static RWStructuredBuffer<uint> A = FakeHeapOfA[0];
#elif TYPE == 2
globallycoherent RWStructuredBuffer<uint> A;
#elif TYPE == 3
uint BindlessUAV_Buf;
typedef RWByteAddressBuffer SafeTypeBuf;
globallycoherent SafeTypeBuf GetBuf() { return ResourceDescriptorHeap[BindlessUAV_Buf]; }
static const globallycoherent SafeTypeBuf A = GetBuf();
#endif

[numthreads(64, 1, 1)]
void CSMain(uint3 ThreadId : SV_DispatchThreadId)
{
#if TYPE == 3
A.InterlockedAdd(0, 1);
AllMemoryBarrierWithGroupSync();
A.Store(0, 42);
#else
InterlockedAdd(A[0], 1);
AllMemoryBarrierWithGroupSync();
InterlockedAdd(A[1], A[0]);
#endif
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %dxc -T lib_6_9 -ast-dump %s | FileCheck %s
// REQUIRES: dxil-1-9

// Initializing a coherent resource from ResourceDescriptorHeap[] produces an
// ICK_Flat_Conversion. Verify the converted expression's type still carries the
// coherence qualifier of its destination instead of dropping it.

[shader("raygeneration")]
void main()
{
// CHECK: VarDecl {{.*}} used glcBuf 'globallycoherent RWByteAddressBuffer':'RWByteAddressBuffer' cinit
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'globallycoherent RWByteAddressBuffer':'RWByteAddressBuffer' <FlatConversion>
globallycoherent RWByteAddressBuffer glcBuf = ResourceDescriptorHeap[0];
glcBuf.Store(0, 0);

// CHECK: VarDecl {{.*}} used rcBuf 'reordercoherent RWBuffer<float4>':'RWBuffer<vector<float, 4> >' cinit
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'reordercoherent RWBuffer<vector<float, 4> >':'RWBuffer<vector<float, 4> >' <FlatConversion>
reordercoherent RWBuffer<float4> rcBuf = ResourceDescriptorHeap[1];
rcBuf[0] = 5;
}
Loading