@@ -84,6 +84,29 @@ class MTLQueue : public offloadtest::Queue {
8484 }
8585};
8686
87+ class MTLFence : public offloadtest ::Fence {
88+ public:
89+ std::string Name;
90+ MTL::SharedEvent *Event;
91+
92+ uint64_t getFenceValue () override { return Event->signaledValue (); }
93+
94+ llvm::Error waitForCompletion (uint64_t SignalValue) override {
95+ if (!Event->waitUntilSignaledValue (SignalValue, UINT64_MAX))
96+ return llvm::createStringError (std::errc::timed_out,
97+ " Timed out waiting on shared event." );
98+ return llvm::Error::success ();
99+ }
100+
101+ MTLFence (MTL::SharedEvent *Event, llvm::StringRef Name)
102+ : Name(Name), Event(Event) {}
103+
104+ ~MTLFence () {
105+ if (Event)
106+ Event->release ();
107+ }
108+ };
109+
87110class MTLBuffer : public offloadtest ::Buffer {
88111public:
89112 MTL::Buffer *Buf;
@@ -131,6 +154,7 @@ class MTLDevice : public offloadtest::Device {
131154 llvm::SmallVector<MTL::Buffer *> Buffers;
132155 MTL::Texture *FrameBufferTexture = nullptr ;
133156 MTL::CommandBuffer *CmdBuffer = nullptr ;
157+ std::shared_ptr<offloadtest::Fence> Fence;
134158 };
135159
136160 llvm::Error setupVertexShader (InvocationState &IS, const Pipeline &P,
@@ -488,14 +512,23 @@ class MTLDevice : public offloadtest::Device {
488512 }
489513
490514 llvm::Error executeCommands (InvocationState &IS) {
515+ // This is a hack but it works since this is all single threaded code.
516+ static uint64_t FenceCounter = 0 ;
517+ const uint64_t CurrentCounter = FenceCounter + 1 ;
518+ auto *F = static_cast <MTLFence *>(IS.Fence .get ());
519+
520+ IS.CmdBuffer ->encodeSignalEvent (F->Event , CurrentCounter);
491521 IS.CmdBuffer ->commit ();
492- IS.CmdBuffer ->waitUntilCompleted ();
522+
523+ if (auto Err = IS.Fence ->waitForCompletion (CurrentCounter))
524+ return Err;
493525
494526 // Check and surface any errors that occurred during execution.
495527 NS::Error *CBErr = IS.CmdBuffer ->error ();
496528 if (CBErr)
497529 return toError (CBErr);
498530
531+ FenceCounter = CurrentCounter;
499532 return llvm::Error::success ();
500533 }
501534
@@ -567,6 +600,15 @@ class MTLDevice : public offloadtest::Device {
567600 return std::static_pointer_cast<Queue>(GraphicsQueue);
568601 }
569602
603+ llvm::Expected<std::shared_ptr<offloadtest::Fence>>
604+ createFence (llvm::StringRef Name) override {
605+ MTL::SharedEvent *Event = Device->newSharedEvent ();
606+ if (!Event)
607+ return llvm::createStringError (std::errc::device_or_resource_busy,
608+ " Failed to create shared event." );
609+ return std::make_shared<MTLFence>(Event, Name);
610+ }
611+
570612 llvm::Expected<std::shared_ptr<offloadtest::Buffer>>
571613 createBuffer (llvm::StringRef Name, BufferCreateDesc &Desc,
572614 size_t SizeInBytes) override {
@@ -591,6 +633,11 @@ class MTLDevice : public offloadtest::Device {
591633 llvm::Error executeProgram (Pipeline &P) override {
592634 InvocationState IS;
593635
636+ auto FenceOrErr = this ->createFence (" Fence" );
637+ if (!FenceOrErr)
638+ return FenceOrErr.takeError ();
639+ IS.Fence = *FenceOrErr;
640+
594641 if (auto Err = createBuffers (P, IS))
595642 return Err;
596643
0 commit comments