Skip to content

Commit 41f208f

Browse files
Add a Metal implementation.
1 parent d312da4 commit 41f208f

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

lib/API/MTL/MTLDevice.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
86109
class MTLBuffer : public offloadtest::Buffer {
87110
public:
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

Comments
 (0)