Program Metal in C++ with metal-cpp

RSS for tag

Discuss the WWDC22 Session Program Metal in C++ with metal-cpp

Posts under wwdc2022-10160 tag

8 Posts

Post

Replies

Boosts

Views

Activity

Input with Metal-CPP, overriding MTK::View
Hi, I am new to Metal and macOS development, and trying to learn Metal with the CPP wrapper for a toy rendering engine. I am mostly following the "Learn Metal with C++" sample code. I am trying to read mouse and keyboard input. It seems like the Objective-C or Swift wrappers allow you to override your own MTK::View class, and then override the respective keyDown(), keyUp() methods. However, when looking at the CPP wrapper, MTK::View doesn't have any virtual functions to override. How can I read mouse and keyboard inputs in my application? Hopefully without having an Objective-C bridge. Thank you, Robin
4
1
3.5k
Apr ’23
Why do developers say Xcode isn't that great?
Hi i am very new to this coding gig. I am an Art Student who happened to develop an interest due to some problems. To a lot of developers shock and disgust i am in fact starting with c/c++ and I am using the humble Xcode, out of lack of better knowledge. I tried to use visual basic however i had an SVN problem because my mac is on Catalina. I just want some intel into what makes Xcode not that great in case i run into problems in the future I would be able to know. Your info will be much appreciated.
0
0
987
Mar ’23
Extending NS::Object removes constructor
Hi! I'm currently trying to convert this Objective-C example project ( https://developer.apple.com/documentation/metal/performing_calculations_on_a_gpu?language=objc ) to one using the metal-cpp wrapper. However when I make the MetalAdder class extend NS::Object (just like in the original codebase) it removes my constructor. class MetalAdder : public NS::Object{ ... } is what I have. When I instantiate this MetalAdder class as: MetalAdder adder; adder.initWithDevice(device); or auto adder = NS::TransferPtr(new MetalAdder); I get the error Call to implicitly-deleted default constructor of 'MetalAdder'. Is there something I'm doing wrong? Should I instantiate in a different way or should my MetalAdder class just not extend the NS::Object class? Thanks in advance!
1
0
1.6k
Feb ’23
Design libraries for Matrix Multiplication
Dear developers, i need support to develop a simple computation on the GPU. I would like to perform matrix multiplication: this will be good with metal-cpp because i need to export as cpp library. Following documentation: file Multiply.metal : kernel void multiply(device float *pMatA, device float *pMatB , device float *pMatC, device float *pMatR) { simdgroup_float8x8 sgMatA; simdgroup_float8x8 sgMatB; simdgroup_float8x8 sgMatR; simdgroup_load(sgMatA, pMatA); simdgroup_load(sgMatB, pMatB); simdgroup_multiply(sgMatR, sgMatA, sgMatB); simdgroup_store(sgMatR, pMatR); } File Multiply.hpp #include <Foundation/Foundation.hpp> #include <Metal/Metal.hpp> class Multiply { public: MTL::Device* m_device; MTL::ComputePipelineState *m_add_function_pso; MTL::CommandQueue *m_command_queue; MTL::Buffer *m_buffer_A; MTL::Buffer *m_buffer_B; MTL::Buffer *m_buffer_result; void init_with_device(MTL::Device*); void prepare_data(); void send_compute_command(); private: void generate_random_float_data(MTL::Buffer* buffer); void encode_dot_command(MTL::ComputeCommandEncoder* compute_encoder); void verify_results(); }; File Multiply.cpp #include <iostream> #include "Multiply.hpp" const unsigned int array_length = 1 << 5; const unsigned int buffer_size = array_length * sizeof(float); void Multiply::init_with_device(MTL::Device* device){ m_device = device; NS::Error* error; auto default_library = m_device->newDefaultLibrary(); if(!default_library){ std::cerr << "Failed to load default library."; std::exit(-1); } auto function_name = NS::String::string("multiply", NS::ASCIIStringEncoding); auto dot_function = default_library->newFunction(function_name); if(!dot_function){ std::cerr << "Failed to find the dot function."; } m_dot_function_pso = m_device->newComputePipelineState(dot_function, &error); m_command_queue = m_device->newCommandQueue(); }; void Multiply::prepare_data(){ m_buffer_A = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); m_buffer_B = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); m_buffer_result = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); generate_random_float_data(m_buffer_A); generate_random_float_data(m_buffer_B); } void Multiply::generate_random_float_data(MTL::Buffer* buffer) { float* data_ptr = (float*)buffer->contents(); for (unsigned long index = 0; index < array_length; index++) { for(unsigned long index2 =0; index2 < array_length; index2++) { data_ptr[index][index2] = (float)rand() / (float)(RAND_MAX); } } void Multiply::send_compute_command() { MTL::CommandBuffer* command_buffer = m_command_queue->commandBuffer(); // assert(command_buffer != nullptr); MTL::ComputeCommandEncoder* compute_encoder = command_buffer->computeCommandEncoder(); encode_dot_command(compute_encoder); compute_encoder->endEncoding();// MTL::CommandBufferStatus status = command_buffer->status(); // std::cout << status << std::endl; command_buffer->commit(); command_buffer->waitUntilCompleted(); verify_results(); } void Multiply::encode_dot_command(MTL::ComputeCommandEncoder* compute_encoder){ compute_encoder->setComputePipelineState(m_dot_function_pso); compute_encoder->setBuffer(m_buffer_A, 0, 0); compute_encoder->setBuffer(m_buffer_B, 0, 1); compute_encoder->setBuffer(m_buffer_result, 0, 2); MTL::Size grid_size = MTL::Size(array_length, 1, 1); NS::UInteger thread_group_size_ = m_dot_function_pso->maxTotalThreadsPerThreadgroup(); if(thread_group_size_ > array_length){ thread_group_size_ = array_length; } MTL::Size thread_group_size = MTL::Size(thread_group_size_, 1, 1); compute_encoder->dispatchThreads(grid_size, thread_group_size); } void Multiply::verify_results(){ auto a = (float*) m_buffer_A->contents(); auto b = (float*) m_buffer_B->contents(); auto result = (float*) m_buffer_result->contents(); for (unsigned long index = 0; index < array_length; index++) { for (unsigned long index2 = 0; index < array_length; index2++) { if (result[index][index2] != (a[index][index2] * b[index][index2])) { std::cout << "Comput ERROR: index=" << index << "result=" << result[index][index2] << "vs " << a[index][index2] + b[index][index2] << "=a*b\n"; assert(result[index][index2] == (a[index][index2] * b[index][index2])); } } std::cout << "Compute results as expected\n";}} Is all this implementation correct? Can someone kindly give suggestions about speed improvement or other solutions? Thank you in advance.
1
0
1.9k
Nov ’22
NSBundle Redeclaration Error for Multiple Functions In Metal CPP
Hi I am trying to get started using Metal CPP after viewing the documentation and defining the constants below: #ifndef MTL_PRIVATE_IMPLEMENTATION #define NS_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION //#define MTK_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #endif I commented out the MTK macro since it was not in the getting started video although it was in the fundamentals projects for metal cpp. I am defining this in a Objective C++ header along with including: #import <Foundation/Foundation.hpp> #import <Metal/Metal.hpp> #import <QuartzCore/QuartzCore.hpp> #import <MetalKit/MetalKit.h> #import <simd/simd.h> I get the error: redeclaration of 'NSPOSIXErrorDomain' with a different type: 'const NSErrorDomain  _Nonnull __strong' (aka 'NSString *const __strong') vs 'const NS::ErrorDomain' (aka 'NS::String *const') along with other errors similar to that one. These errors all seem to do with <Foundation/Foundation.h>. I can see that the NS prefix is being declared rather than the C++ version of NS:: but I am sure I implemented this correctly. I have a header set up in Objective C for this file along with things being @implementation rather than pure C++: #pragma once #include "../../../src/state/config.h" #ifdef __PEN_IOS__ //#import <cassert> #ifndef MTL_PRIVATE_IMPLEMENTATION #define NS_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION //#define MTK_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #endif #ifdef TARGET_IPHONE_SIMULATOR //#import <UIKit/UIKit.h> #elifdef TARGET_OS_IPHONE //#import <UIKit/UIKit.hpp> #elifdef TARGET_OS_IOS //#import <UIKit/UIKit.hpp> #elifdef TARGET_OS_MAC //#import <AppKit/AppKit.hpp> #endif #import <Foundation/Foundation.hpp> #import <Metal/Metal.hpp> //#import <CoreFoundation/CoreFoundation.h> #import <QuartzCore/QuartzCore.hpp> #import <MetalKit/MetalKit.h> #import <simd/simd.h> #import "ios_cpp_objective_c_mapping.h" @class IOSState; @interface IOSState : NSObject @property MTK::View* iosMtkView;     @property MTL::Device* iosDevice;     @property MTL::CommandQueue* iosCommandQueue;     @property MTL::RenderPipelineState* iosPipelineState;     @property NS::Notification* iosLaunchNotification;     @property MTL::ArgumentEncoder* iosArgEncoder;     @property MTL::DepthStencilState* iosDepthStencilState;     @property MTL::Texture* iosPixelBuffer;     @property MTL::Buffer* iosUniformBuffer;     @property MTL::Buffer* iosInstanceBuffer;     @property MTL::RenderCommandEncoder* iosCommandEncoder;     @property MTL::CommandBuffer* iosCommandBuffer;     @property NS::AutoreleasePool* iosAutoReleasePool;     @property dispatch_semaphore_t dispatchSemaphore; + (IOSState*) Get; + (void) Destroy; @end #endif I include this file in multiple places although the headers should be able to be included more than once.
3
0
1.3k
Aug ’22
MetalKit's drawInMTKView function not called if app is built using cmake/make?
I ran into a strange issue testing Metal cpp. The following project is almost the same as Apple's official Metal Cpp example project (https://developer.apple.com/videos/play/wwdc2022/10160/). https://github.com/shi-yan/testmetal The apple official example contains an Xcode project, whereas my modified version tries to use cmake. My cmake project builds and runs, but the window is empty. I debugged it, the root cause is that the drawInMTKView function never gets called. If I generate an Xcode project using cmake, then build and run my code in Xcode, the resulting app can render to its window just fine. However, if I run the same app binary through the terminal, it will show an empty window again. Any idea what might cause this? Thanks.
1
0
1k
Aug ’22
Any example about using metal-cpp on iOS?
Now the examples of metal-cpp are target on desktop and using AppKit which is not supported on iOS. Is there any tips for developing with metal-cpp on mobile device?
Replies
2
Boosts
0
Views
1.3k
Activity
Feb ’25
Metal & C++
What is the best source for information/tutorial material on using Metal with C++? metal-cpp?
Replies
1
Boosts
0
Views
1.7k
Activity
May ’23
Input with Metal-CPP, overriding MTK::View
Hi, I am new to Metal and macOS development, and trying to learn Metal with the CPP wrapper for a toy rendering engine. I am mostly following the "Learn Metal with C++" sample code. I am trying to read mouse and keyboard input. It seems like the Objective-C or Swift wrappers allow you to override your own MTK::View class, and then override the respective keyDown(), keyUp() methods. However, when looking at the CPP wrapper, MTK::View doesn't have any virtual functions to override. How can I read mouse and keyboard inputs in my application? Hopefully without having an Objective-C bridge. Thank you, Robin
Replies
4
Boosts
1
Views
3.5k
Activity
Apr ’23
Why do developers say Xcode isn't that great?
Hi i am very new to this coding gig. I am an Art Student who happened to develop an interest due to some problems. To a lot of developers shock and disgust i am in fact starting with c/c++ and I am using the humble Xcode, out of lack of better knowledge. I tried to use visual basic however i had an SVN problem because my mac is on Catalina. I just want some intel into what makes Xcode not that great in case i run into problems in the future I would be able to know. Your info will be much appreciated.
Replies
0
Boosts
0
Views
987
Activity
Mar ’23
Extending NS::Object removes constructor
Hi! I'm currently trying to convert this Objective-C example project ( https://developer.apple.com/documentation/metal/performing_calculations_on_a_gpu?language=objc ) to one using the metal-cpp wrapper. However when I make the MetalAdder class extend NS::Object (just like in the original codebase) it removes my constructor. class MetalAdder : public NS::Object{ ... } is what I have. When I instantiate this MetalAdder class as: MetalAdder adder; adder.initWithDevice(device); or auto adder = NS::TransferPtr(new MetalAdder); I get the error Call to implicitly-deleted default constructor of 'MetalAdder'. Is there something I'm doing wrong? Should I instantiate in a different way or should my MetalAdder class just not extend the NS::Object class? Thanks in advance!
Replies
1
Boosts
0
Views
1.6k
Activity
Feb ’23
Design libraries for Matrix Multiplication
Dear developers, i need support to develop a simple computation on the GPU. I would like to perform matrix multiplication: this will be good with metal-cpp because i need to export as cpp library. Following documentation: file Multiply.metal : kernel void multiply(device float *pMatA, device float *pMatB , device float *pMatC, device float *pMatR) { simdgroup_float8x8 sgMatA; simdgroup_float8x8 sgMatB; simdgroup_float8x8 sgMatR; simdgroup_load(sgMatA, pMatA); simdgroup_load(sgMatB, pMatB); simdgroup_multiply(sgMatR, sgMatA, sgMatB); simdgroup_store(sgMatR, pMatR); } File Multiply.hpp #include <Foundation/Foundation.hpp> #include <Metal/Metal.hpp> class Multiply { public: MTL::Device* m_device; MTL::ComputePipelineState *m_add_function_pso; MTL::CommandQueue *m_command_queue; MTL::Buffer *m_buffer_A; MTL::Buffer *m_buffer_B; MTL::Buffer *m_buffer_result; void init_with_device(MTL::Device*); void prepare_data(); void send_compute_command(); private: void generate_random_float_data(MTL::Buffer* buffer); void encode_dot_command(MTL::ComputeCommandEncoder* compute_encoder); void verify_results(); }; File Multiply.cpp #include <iostream> #include "Multiply.hpp" const unsigned int array_length = 1 << 5; const unsigned int buffer_size = array_length * sizeof(float); void Multiply::init_with_device(MTL::Device* device){ m_device = device; NS::Error* error; auto default_library = m_device->newDefaultLibrary(); if(!default_library){ std::cerr << "Failed to load default library."; std::exit(-1); } auto function_name = NS::String::string("multiply", NS::ASCIIStringEncoding); auto dot_function = default_library->newFunction(function_name); if(!dot_function){ std::cerr << "Failed to find the dot function."; } m_dot_function_pso = m_device->newComputePipelineState(dot_function, &error); m_command_queue = m_device->newCommandQueue(); }; void Multiply::prepare_data(){ m_buffer_A = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); m_buffer_B = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); m_buffer_result = m_device->newBuffer(buffer_size, MTL::ResourceStorageModeShared); generate_random_float_data(m_buffer_A); generate_random_float_data(m_buffer_B); } void Multiply::generate_random_float_data(MTL::Buffer* buffer) { float* data_ptr = (float*)buffer->contents(); for (unsigned long index = 0; index < array_length; index++) { for(unsigned long index2 =0; index2 < array_length; index2++) { data_ptr[index][index2] = (float)rand() / (float)(RAND_MAX); } } void Multiply::send_compute_command() { MTL::CommandBuffer* command_buffer = m_command_queue->commandBuffer(); // assert(command_buffer != nullptr); MTL::ComputeCommandEncoder* compute_encoder = command_buffer->computeCommandEncoder(); encode_dot_command(compute_encoder); compute_encoder->endEncoding();// MTL::CommandBufferStatus status = command_buffer->status(); // std::cout << status << std::endl; command_buffer->commit(); command_buffer->waitUntilCompleted(); verify_results(); } void Multiply::encode_dot_command(MTL::ComputeCommandEncoder* compute_encoder){ compute_encoder->setComputePipelineState(m_dot_function_pso); compute_encoder->setBuffer(m_buffer_A, 0, 0); compute_encoder->setBuffer(m_buffer_B, 0, 1); compute_encoder->setBuffer(m_buffer_result, 0, 2); MTL::Size grid_size = MTL::Size(array_length, 1, 1); NS::UInteger thread_group_size_ = m_dot_function_pso->maxTotalThreadsPerThreadgroup(); if(thread_group_size_ > array_length){ thread_group_size_ = array_length; } MTL::Size thread_group_size = MTL::Size(thread_group_size_, 1, 1); compute_encoder->dispatchThreads(grid_size, thread_group_size); } void Multiply::verify_results(){ auto a = (float*) m_buffer_A->contents(); auto b = (float*) m_buffer_B->contents(); auto result = (float*) m_buffer_result->contents(); for (unsigned long index = 0; index < array_length; index++) { for (unsigned long index2 = 0; index < array_length; index2++) { if (result[index][index2] != (a[index][index2] * b[index][index2])) { std::cout << "Comput ERROR: index=" << index << "result=" << result[index][index2] << "vs " << a[index][index2] + b[index][index2] << "=a*b\n"; assert(result[index][index2] == (a[index][index2] * b[index][index2])); } } std::cout << "Compute results as expected\n";}} Is all this implementation correct? Can someone kindly give suggestions about speed improvement or other solutions? Thank you in advance.
Replies
1
Boosts
0
Views
1.9k
Activity
Nov ’22
NSBundle Redeclaration Error for Multiple Functions In Metal CPP
Hi I am trying to get started using Metal CPP after viewing the documentation and defining the constants below: #ifndef MTL_PRIVATE_IMPLEMENTATION #define NS_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION //#define MTK_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #endif I commented out the MTK macro since it was not in the getting started video although it was in the fundamentals projects for metal cpp. I am defining this in a Objective C++ header along with including: #import <Foundation/Foundation.hpp> #import <Metal/Metal.hpp> #import <QuartzCore/QuartzCore.hpp> #import <MetalKit/MetalKit.h> #import <simd/simd.h> I get the error: redeclaration of 'NSPOSIXErrorDomain' with a different type: 'const NSErrorDomain  _Nonnull __strong' (aka 'NSString *const __strong') vs 'const NS::ErrorDomain' (aka 'NS::String *const') along with other errors similar to that one. These errors all seem to do with <Foundation/Foundation.h>. I can see that the NS prefix is being declared rather than the C++ version of NS:: but I am sure I implemented this correctly. I have a header set up in Objective C for this file along with things being @implementation rather than pure C++: #pragma once #include "../../../src/state/config.h" #ifdef __PEN_IOS__ //#import <cassert> #ifndef MTL_PRIVATE_IMPLEMENTATION #define NS_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION //#define MTK_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #endif #ifdef TARGET_IPHONE_SIMULATOR //#import <UIKit/UIKit.h> #elifdef TARGET_OS_IPHONE //#import <UIKit/UIKit.hpp> #elifdef TARGET_OS_IOS //#import <UIKit/UIKit.hpp> #elifdef TARGET_OS_MAC //#import <AppKit/AppKit.hpp> #endif #import <Foundation/Foundation.hpp> #import <Metal/Metal.hpp> //#import <CoreFoundation/CoreFoundation.h> #import <QuartzCore/QuartzCore.hpp> #import <MetalKit/MetalKit.h> #import <simd/simd.h> #import "ios_cpp_objective_c_mapping.h" @class IOSState; @interface IOSState : NSObject @property MTK::View* iosMtkView;     @property MTL::Device* iosDevice;     @property MTL::CommandQueue* iosCommandQueue;     @property MTL::RenderPipelineState* iosPipelineState;     @property NS::Notification* iosLaunchNotification;     @property MTL::ArgumentEncoder* iosArgEncoder;     @property MTL::DepthStencilState* iosDepthStencilState;     @property MTL::Texture* iosPixelBuffer;     @property MTL::Buffer* iosUniformBuffer;     @property MTL::Buffer* iosInstanceBuffer;     @property MTL::RenderCommandEncoder* iosCommandEncoder;     @property MTL::CommandBuffer* iosCommandBuffer;     @property NS::AutoreleasePool* iosAutoReleasePool;     @property dispatch_semaphore_t dispatchSemaphore; + (IOSState*) Get; + (void) Destroy; @end #endif I include this file in multiple places although the headers should be able to be included more than once.
Replies
3
Boosts
0
Views
1.3k
Activity
Aug ’22
MetalKit's drawInMTKView function not called if app is built using cmake/make?
I ran into a strange issue testing Metal cpp. The following project is almost the same as Apple's official Metal Cpp example project (https://developer.apple.com/videos/play/wwdc2022/10160/). https://github.com/shi-yan/testmetal The apple official example contains an Xcode project, whereas my modified version tries to use cmake. My cmake project builds and runs, but the window is empty. I debugged it, the root cause is that the drawInMTKView function never gets called. If I generate an Xcode project using cmake, then build and run my code in Xcode, the resulting app can render to its window just fine. However, if I run the same app binary through the terminal, it will show an empty window again. Any idea what might cause this? Thanks.
Replies
1
Boosts
0
Views
1k
Activity
Aug ’22