@@ -83,6 +83,29 @@ class MTLQueue : public offloadtest::Queue {
8383 }
8484};
8585
86+ class MTLFence : public offloadtest ::Fence {
87+ public:
88+ std::string Name;
89+ MTL::SharedEvent *Event;
90+
91+ uint64_t getFenceValue () override { return Event->signaledValue (); }
92+
93+ llvm::Error waitForCompletion (uint64_t SignalValue) override {
94+ if (!Event->waitUntilSignaledValue (SignalValue, UINT64_MAX))
95+ return llvm::createStringError (std::errc::timed_out,
96+ " Timed out waiting on shared event." );
97+ return llvm::Error::success ();
98+ }
99+
100+ MTLFence (MTL::SharedEvent *Event, llvm::StringRef Name)
101+ : Name(Name), Event(Event) {}
102+
103+ ~MTLFence () {
104+ if (Event)
105+ Event->release ();
106+ }
107+ };
108+
86109class MTLBuffer : public offloadtest ::Buffer {
87110public:
88111 MTL::Buffer *Buf;
@@ -130,6 +153,7 @@ class MTLDevice : public offloadtest::Device {
130153 llvm::SmallVector<MTL::Buffer *> Buffers;
131154 MTL::Texture *FrameBufferTexture = nullptr ;
132155 MTL::CommandBuffer *CmdBuffer = nullptr ;
156+ std::shared_ptr<offloadtest::Fence> Fence;
133157 };
134158
135159 llvm::Error setupVertexShader (InvocationState &IS, const Pipeline &P,
@@ -487,14 +511,23 @@ class MTLDevice : public offloadtest::Device {
487511 }
488512
489513 llvm::Error executeCommands (InvocationState &IS) {
514+ // This is a hack but it works since this is all single threaded code.
515+ static uint64_t FenceCounter = 0 ;
516+ const uint64_t CurrentCounter = FenceCounter + 1 ;
517+ auto *F = static_cast <MTLFence *>(IS.Fence .get ());
518+
519+ IS.CmdBuffer ->encodeSignalEvent (F->Event , CurrentCounter);
490520 IS.CmdBuffer ->commit ();
491- IS.CmdBuffer ->waitUntilCompleted ();
521+
522+ if (auto Err = IS.Fence ->waitForCompletion (CurrentCounter))
523+ return Err;
492524
493525 // Check and surface any errors that occurred during execution.
494526 NS::Error *CBErr = IS.CmdBuffer ->error ();
495527 if (CBErr)
496528 return toError (CBErr);
497529
530+ FenceCounter = CurrentCounter;
498531 return llvm::Error::success ();
499532 }
500533
@@ -564,6 +597,15 @@ class MTLDevice : public offloadtest::Device {
564597
565598 Queue &getGraphicsQueue () override { return GraphicsQueue; }
566599
600+ llvm::Expected<std::shared_ptr<offloadtest::Fence>>
601+ createFence (llvm::StringRef Name) override {
602+ MTL::SharedEvent *Event = Device->newSharedEvent ();
603+ if (!Event)
604+ return llvm::createStringError (std::errc::device_or_resource_busy,
605+ " Failed to create shared event." );
606+ return std::make_shared<MTLFence>(Event, Name);
607+ }
608+
567609 llvm::Expected<std::shared_ptr<offloadtest::Buffer>>
568610 createBuffer (std::string Name, BufferCreateDesc &Desc,
569611 size_t SizeInBytes) override {
@@ -588,6 +630,11 @@ class MTLDevice : public offloadtest::Device {
588630 llvm::Error executeProgram (Pipeline &P) override {
589631 InvocationState IS;
590632
633+ auto FenceOrErr = this ->createFence (" Fence" );
634+ if (!FenceOrErr)
635+ return FenceOrErr.takeError ();
636+ IS.Fence = *FenceOrErr;
637+
591638 if (auto Err = createBuffers (P, IS))
592639 return Err;
593640
0 commit comments