3333
3434#include " API/Capabilities.h"
3535#include " API/Device.h"
36+ #include " API/Encoder.h"
3637#include " API/FormatConversion.h"
3738#include " DXFeatures.h"
3839#include " Support/Pipeline.h"
4344#include " llvm/ADT/SmallVector.h"
4445#include " llvm/Object/DXContainer.h"
4546#include " llvm/Support/Error.h"
47+ #include " llvm/Support/FormatVariadic.h"
4648#include " llvm/Support/Signals.h"
4749
4850#include < atomic>
@@ -533,6 +535,8 @@ class DXCommandBuffer : public offloadtest::CommandBuffer {
533535public:
534536 ComPtr<ID3D12CommandAllocator> Allocator;
535537 ComPtr<ID3D12GraphicsCommandList> CmdList;
538+ // / Whether a UAV barrier is pending from a prior compute command.
539+ bool PendingUAVBarrier = false ;
536540
537541 static llvm::Expected<std::unique_ptr<DXCommandBuffer>>
538542 create (ComPtr<ID3D12Device> Device) {
@@ -557,6 +561,20 @@ class DXCommandBuffer : public offloadtest::CommandBuffer {
557561 return CB ->getKind () == GPUAPI ::DirectX;
558562 }
559563
564+ void addPendingUAVBarrier () { PendingUAVBarrier = true ; }
565+
566+ void flushBarrier () {
567+ if (!PendingUAVBarrier)
568+ return ;
569+ const D3D12_RESOURCE_BARRIER Barrier =
570+ CD3DX12_RESOURCE_BARRIER::UAV (nullptr );
571+ CmdList->ResourceBarrier (1 , &Barrier);
572+ PendingUAVBarrier = false ;
573+ }
574+
575+ llvm::Expected<std::unique_ptr<offloadtest::ComputeEncoder>>
576+ createComputeEncoder () override ;
577+
560578private:
561579 DXCommandBuffer () : CommandBuffer(GPUAPI ::DirectX) {}
562580};
@@ -606,6 +624,63 @@ struct DescriptorAllocator {
606624 : Heap(Heap), DescIncSize(DescIncSize), Capacity(Capacity) {}
607625};
608626
627+ class DXComputeEncoder : public offloadtest ::ComputeEncoder {
628+ DXCommandBuffer &CB ;
629+
630+ void addUAVBarrier () {
631+ CB .addPendingUAVBarrier ();
632+ CB .flushBarrier ();
633+ }
634+
635+ public:
636+ DXComputeEncoder (DXCommandBuffer &CB )
637+ : ComputeEncoder(GPUAPI ::DirectX), CB (CB ) {}
638+
639+ ~DXComputeEncoder () override { endEncoding (); }
640+
641+ static bool classof (const CommandEncoder *E) {
642+ return E->getAPI () == GPUAPI ::DirectX;
643+ }
644+
645+ // D3D12 debug labels require WinPixEventRuntime for the proper event
646+ // encoding. Without it, BeginEvent/EndEvent/SetMarker with metadata type 0
647+ // crash the D3D12 debug layer, so leave these as no-ops for now.
648+ void pushDebugGroup (llvm::StringRef Label) override {}
649+ void popDebugGroup () override {}
650+ void insertDebugSignpost (llvm::StringRef Label) override {}
651+
652+ llvm::Error dispatch (uint32_t GroupCountX, uint32_t GroupCountY,
653+ uint32_t GroupCountZ) override {
654+ addUAVBarrier ();
655+ insertDebugSignpost (llvm::formatv (" Dispatch [{0},{1},{2}]" , GroupCountX,
656+ GroupCountY, GroupCountZ)
657+ .str ());
658+ CB .CmdList ->Dispatch (GroupCountX, GroupCountY, GroupCountZ);
659+ return llvm::Error::success ();
660+ }
661+
662+ llvm::Error copyBufferToBuffer (offloadtest::Buffer &Src, size_t SrcOffset,
663+ offloadtest::Buffer &Dst, size_t DstOffset,
664+ size_t Size) override {
665+ auto &DXSrc = static_cast <DXBuffer &>(Src);
666+ auto &DXDst = static_cast <DXBuffer &>(Dst);
667+ addUAVBarrier ();
668+ insertDebugSignpost (llvm::formatv (" CopyBuffer {0}B" , Size).str ());
669+ CB .CmdList ->CopyBufferRegion (DXDst.Buffer .Get (), DstOffset,
670+ DXSrc.Buffer .Get (), SrcOffset, Size);
671+ return llvm::Error::success ();
672+ }
673+
674+ void endEncodingImpl () override { popDebugGroup (); }
675+ };
676+
677+ llvm::Expected<std::unique_ptr<offloadtest::ComputeEncoder>>
678+ DXCommandBuffer::createComputeEncoder () {
679+ auto Enc = std::make_unique<DXComputeEncoder>(*this );
680+ Enc->pushDebugGroup (" ComputeEncoder" );
681+ return Enc;
682+ }
683+
609684class DXDevice : public offloadtest ::Device {
610685private:
611686 ComPtr<IDXCoreAdapter> Adapter;
@@ -1594,25 +1669,17 @@ class DXDevice : public offloadtest::Device {
15941669 }
15951670
15961671 void addUploadBeginBarrier (InvocationState &IS , ComPtr<ID3D12Resource> R) {
1597- const D3D12_RESOURCE_BARRIER Barrier = {
1598- D3D12_RESOURCE_BARRIER_TYPE_TRANSITION ,
1599- D3D12_RESOURCE_BARRIER_FLAG_NONE ,
1600- {D3D12_RESOURCE_TRANSITION_BARRIER {
1601- R.Get (), D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES ,
1602- D3D12_RESOURCE_STATE_COMMON , D3D12_RESOURCE_STATE_COPY_DEST }}};
1672+ const D3D12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition (
1673+ R.Get (), D3D12_RESOURCE_STATE_COMMON , D3D12_RESOURCE_STATE_COPY_DEST );
16031674 IS .CB ->CmdList ->ResourceBarrier (1 , &Barrier);
16041675 }
16051676
16061677 void addUploadEndBarrier (InvocationState &IS , ComPtr<ID3D12Resource> R,
16071678 bool IsUAV) {
1608- const D3D12_RESOURCE_BARRIER Barrier = {
1609- D3D12_RESOURCE_BARRIER_TYPE_TRANSITION ,
1610- D3D12_RESOURCE_BARRIER_FLAG_NONE ,
1611- {D3D12_RESOURCE_TRANSITION_BARRIER {
1612- R.Get (), D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES ,
1613- D3D12_RESOURCE_STATE_COPY_DEST ,
1614- IsUAV ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS
1615- : D3D12_RESOURCE_STATE_GENERIC_READ }}};
1679+ const D3D12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition (
1680+ R.Get (), D3D12_RESOURCE_STATE_COPY_DEST ,
1681+ IsUAV ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS
1682+ : D3D12_RESOURCE_STATE_GENERIC_READ );
16161683 IS .CB ->CmdList ->ResourceBarrier (1 , &Barrier);
16171684 }
16181685
@@ -1715,10 +1782,18 @@ class DXDevice : public offloadtest::Device {
17151782 }
17161783 }
17171784
1718- const llvm::ArrayRef<int > DispatchSize =
1719- llvm::ArrayRef<int >(P.Shaders [0 ].DispatchSize );
1720-
1721- IS .CB ->CmdList ->Dispatch (DispatchSize[0 ], DispatchSize[1 ], DispatchSize[2 ]);
1785+ {
1786+ auto EncoderOrErr = IS .CB ->createComputeEncoder ();
1787+ if (!EncoderOrErr)
1788+ return EncoderOrErr.takeError ();
1789+ auto &Encoder = *EncoderOrErr.get ();
1790+ const llvm::ArrayRef<int > DispatchSize =
1791+ llvm::ArrayRef<int >(P.Shaders [0 ].DispatchSize );
1792+ if (auto Err = Encoder.dispatch (DispatchSize[0 ], DispatchSize[1 ],
1793+ DispatchSize[2 ]))
1794+ return Err;
1795+ Encoder.endEncoding ();
1796+ }
17221797
17231798 auto CopyBackResource = [&IS , this ](ResourcePair &R) {
17241799 if (R.first ->isTexture ()) {
0 commit comments