VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
metalComputePipeline.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 05.11.2025.
5//
6
8
9#include "metalShader.h"
11#include "spdlog/spdlog.h"
12
13namespace visutwin::canvas
14{
16 {
17 for (const auto& [_, pipeline] : _cache) {
18 if (pipeline) {
19 pipeline->release();
20 }
21 }
22 _cache.clear();
23 }
24
25 MTL::ComputePipelineState* MetalComputePipeline::get(const std::shared_ptr<Shader>& shader)
26 {
27 if (!shader) {
28 return nullptr;
29 }
30
31 const auto it = _cache.find(shader->id());
32 if (it != _cache.end()) {
33 return it->second;
34 }
35
36 auto* pipeline = create(shader);
37 if (pipeline) {
38 _cache.emplace(shader->id(), pipeline);
39 }
40 return pipeline;
41 }
42
43 MTL::ComputePipelineState* MetalComputePipeline::create(const std::shared_ptr<Shader>& shader)
44 {
45 if (!shader || !_device) {
46 return nullptr;
47 }
48
49 auto* metalDevice = const_cast<MTL::Device*>(_device->raw());
50 if (!metalDevice) {
51 return nullptr;
52 }
53
54 auto* metalShader = dynamic_cast<MetalShader*>(shader.get());
55 if (!metalShader) {
56 spdlog::error("Unsupported shader implementation for Metal compute pipeline. Expected MetalShader.");
57 return nullptr;
58 }
59
60 NS::Error* error = nullptr;
61 const auto* bundle = NS::Bundle::mainBundle();
62 auto* library = metalShader->getLibrary(metalDevice, bundle, &error);
63 if (!library) {
64 spdlog::error("Failed to get Metal library for compute shader: {}",
65 error ? error->localizedDescription()->utf8String() : "unknown");
66 return nullptr;
67 }
68
69 library->retain();
70 const auto& computeEntry = shader->computeEntry().empty() ? std::string("computeMain") : shader->computeEntry();
71 auto* computeFunction = library->newFunction(NS::String::string(computeEntry.c_str(), NS::UTF8StringEncoding));
72 if (!computeFunction) {
73 spdlog::error("Failed to find compute shader entry point '{}'", computeEntry);
74 library->release();
75 return nullptr;
76 }
77
78 auto* pipeline = metalDevice->newComputePipelineState(computeFunction, &error);
79 if (!pipeline) {
80 spdlog::error("Failed to create compute pipeline state: {}",
81 error ? error->localizedDescription()->utf8String() : "unknown");
82 }
83
84 computeFunction->release();
85 library->release();
86 return pipeline;
87 }
88} // visutwin
MTL::ComputePipelineState * get(const std::shared_ptr< Shader > &shader)
const MetalGraphicsDevice * _device