Last active
February 24, 2025 15:11
-
-
Save gcatlin/b89e0efed78dd91364609ca4095da346 to your computer and use it in GitHub Desktop.
Minimal C SDL2 Metal example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// cc sdl-metal-example.m `sdl2-config --cflags --libs` -framework Metal -framework QuartzCore && ./a.out | |
// | |
#include <SDL.h> | |
#import <Metal/Metal.h> | |
#import <QuartzCore/CAMetalLayer.h> | |
int main (int argc, char *args[]) | |
{ | |
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); | |
SDL_InitSubSystem(SDL_INIT_VIDEO); | |
SDL_Window *window = SDL_CreateWindow("SDL Metal", -1, -1, 640, 480, SDL_WINDOW_ALLOW_HIGHDPI); | |
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC); | |
const CAMetalLayer *swapchain = (__bridge CAMetalLayer *)SDL_RenderGetMetalLayer(renderer); | |
const id<MTLDevice> gpu = swapchain.device; | |
const id<MTLCommandQueue> queue = [gpu newCommandQueue]; | |
MTLClearColor color = MTLClearColorMake(0, 0, 0, 1); | |
bool quit = false; | |
SDL_Event e; | |
while (!quit) { | |
while (SDL_PollEvent(&e) != 0) { | |
switch (e.type) { | |
case SDL_QUIT: quit = true; break; | |
} | |
} | |
@autoreleasepool { | |
id<CAMetalDrawable> surface = [swapchain nextDrawable]; | |
color.red = (color.red > 1.0) ? 0 : color.red + 0.01; | |
MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; | |
pass.colorAttachments[0].clearColor = color; | |
pass.colorAttachments[0].loadAction = MTLLoadActionClear; | |
pass.colorAttachments[0].storeAction = MTLStoreActionStore; | |
pass.colorAttachments[0].texture = surface.texture; | |
id<MTLCommandBuffer> buffer = [queue commandBuffer]; | |
id<MTLRenderCommandEncoder> encoder = [buffer renderCommandEncoderWithDescriptor:pass]; | |
[encoder endEncoding]; | |
[buffer presentDrawable:surface]; | |
[buffer commit]; | |
} | |
} | |
SDL_DestroyRenderer(renderer); | |
SDL_DestroyWindow(window); | |
SDL_Quit(); | |
return 0; | |
} |
For anyone who is stuck here with a black screen, you need to remove the "SDL_DestroyRenderer(renderer);" on line 17. This function in SDL destroys the View as well as the renderer which will prevent you from having anything draw to the screen. SDL_RenderGetMetalLayer will flush all the buffers before returning so there shouldn't be any conflicts.
I haven't tested on iOS, I'm guessing perhaps the UIKit based renderer on iOS behaves differently hence the author adding the destroy?
@slightlybeige thanks for figuring out the issue. It used to work as is -- I'm not sure what changed, maybe something in SDL. I moved SDL_DestroyRenderer
below the loop and updated the gist.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For Reak45, this code is meant to draw a black screen or very dark red. Change the clear colour in the main function to white or something bright, and remove the colour.red line in the render loop, then report your results.