Skip to content

Commit

Permalink
sokol: Use new sg_pass API
Browse files Browse the repository at this point in the history
  • Loading branch information
IonAgorria committed Apr 6, 2024
1 parent a35d84c commit a358a61
Show file tree
Hide file tree
Showing 8 changed files with 1,258 additions and 1,173 deletions.
4 changes: 2 additions & 2 deletions Source/Render/sokol/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ OPTION(OPTION_PROCESS_SHADERS "Re-Process game shaders" OFF)
#Include Sokol
FetchContent_Declare(sokol
GIT_REPOSITORY https://github.com/floooh/sokol
GIT_TAG "004223737d9f6d07a0aa5c63659662480285de29"
GIT_TAG "7f7cd64c6d9d1d4ed08d88a3879b1d69841bf0a4"
GIT_SHALLOW OFF
)
FetchContent_MakeAvailable(sokol)
Expand Down Expand Up @@ -34,7 +34,7 @@ IF (OPTION_PROCESS_SHADERS)
set(SOKOL_SHDC_BIN ${sokol-tools-bin_SOURCE_DIR}/bin/osx/sokol-shdc)
ENDIF()
ELSEIF(PERIMETER_WINDOWS)
set(SOKOL_SHDC_BIN ${sokol-tools-bin_SOURCE_DIR}/bin/win32/sokol-shdc)
set(SOKOL_SHDC_BIN ${sokol-tools-bin_SOURCE_DIR}/bin/win32/sokol-shdc.exe)
ELSE()
set(SOKOL_SHDC_BIN ${sokol-tools-bin_SOURCE_DIR}/bin/linux/sokol-shdc)
ENDIF()
Expand Down
6 changes: 4 additions & 2 deletions Source/Render/sokol/SokolD3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ struct sokol_d3d_context {
ID3D11Device* device = nullptr;
ID3D11DeviceContext* device_context = nullptr;
IDXGISwapChain* swap_chain = nullptr;
ID3D11Texture2D* render_target = nullptr;
ID3D11Texture2D* render_target_texture = nullptr;
ID3D11RenderTargetView* render_target_view = nullptr;
ID3D11Texture2D* depth_stencil_buffer = nullptr;
ID3D11Texture2D* msaa_texture = nullptr;
ID3D11RenderTargetView* msaa_view = nullptr;
ID3D11Texture2D* depth_stencil_texture = nullptr;
ID3D11DepthStencilView* depth_stencil_view = nullptr;
};

Expand Down
93 changes: 71 additions & 22 deletions Source/Render/sokol/SokolImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,83 @@

//ObjC Sokol - SDL2 glue code for Metal
#ifdef SOKOL_METAL
#import <QuartzCore/CAMetalLayer.h>
#import <SDL_metal.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <SDL_syswm.h>

static CAMetalLayer* sokol_metal_layer;
static id<CAMetalDrawable> sokol_metal_drawable;
static MTLRenderPassDescriptor* sokol_metal_render_pass_descriptor;
//TODO This should be stored in a metal_context struct like in d3d11 impl
static id<MTLDevice> mtl_device;
static MTKView* mtk_view;
#if TARGET_OS_IPHONE
static id mtk_view_controller;
#endif

const void* sokol_metal_drawable_cb() {
return (__bridge const void*) sokol_metal_drawable;
void sokol_metal_setup(SDL_Window* sdl_window, sg_desc* desc, sg_swapchain* swapchain, uint32_t ScreenHZ) {
//Get window from SDL which we will use to associate Metal stuff
SDL_SysWMinfo wm_info;
SDL_VERSION(&wm_info.version);
SDL_GetWindowWMInfo(sdl_window, &wm_info);
#if TARGET_OS_IPHONE
UIWindow* window = wm_info.info.uikit.window
#else
NSWindow* window = wm_info.info.cocoa.window;
#endif

// MTKView and Metal device
mtl_device = MTLCreateSystemDefaultDevice();
mtk_view = [[MTKView alloc] init];
mtk_view.paused = true;
mtk_view.enableSetNeedsDisplay = false;
[mtk_view setPreferredFramesPerSecond:ScreenHZ];
[mtk_view setDevice: mtl_device];
[mtk_view setColorPixelFormat:MTLPixelFormatBGRA8Unorm];
[mtk_view setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8];
[mtk_view setSampleCount:(NSUInteger) swapchain->sample_count];
#if TARGET_OS_IPHONE
[mtk_view setContentScaleFactor:1.0f];
[mtk_view setUserInteractionEnabled:YES];
[mtk_view setMultipleTouchEnabled:YES];
[window addSubview:mtk_view];
mtk_view_controller = [[UIViewController<MTKViewDelegate> alloc] init];
[mtk_view_controller setView:mtk_view];
[window setRootViewController:mtk_view_controller];
[window makeKeyAndVisible];
#else
[window setContentView:mtk_view];
CGSize drawable_size = { (CGFloat) swapchain->width, (CGFloat) swapchain->height };
[mtk_view setDrawableSize:drawable_size];
[[mtk_view layer] setMagnificationFilter:kCAFilterNearest];
NSApp.activationPolicy = NSApplicationActivationPolicyRegular;
[NSApp activateIgnoringOtherApps:YES];
[window makeKeyAndOrderFront:nil];
#endif

//Setup Metal specific context
desc->environment.metal.device = (__bridge const void*) mtl_device;
}

const void* sokol_metal_renderpass_descriptor_cb() {
sokol_metal_drawable = [sokol_metal_layer nextDrawable];
void sokol_metal_render(sg_swapchain* swapchain, void (*callback)()) {
@autoreleasepool {
swapchain->metal.current_drawable = (__bridge const void*) [mtk_view currentDrawable];
swapchain->metal.depth_stencil_texture = (__bridge const void*) [mtk_view depthStencilTexture];
swapchain->metal.msaa_color_texture = (__bridge const void*) [mtk_view multisampleColorTexture];
callback();
}
}

sokol_metal_render_pass_descriptor = [[MTLRenderPassDescriptor alloc] init];
sokol_metal_render_pass_descriptor.colorAttachments[0].texture = sokol_metal_drawable.texture;
return (__bridge const void*) sokol_metal_render_pass_descriptor;
void sokol_metal_draw() {
[mtk_view draw];
}

void sokol_metal_setup_desc(SDL_MetalView view, sg_desc* desc) {
//Get Metal layer from SDL and add Metal device
sokol_metal_layer = (__bridge CAMetalLayer*) SDL_Metal_GetLayer(view);
sokol_metal_layer.device = MTLCreateSystemDefaultDevice();

//Setup Metal specific context
sg_metal_context_desc& metalctx = desc->context.metal;
metalctx.device = sokol_metal_layer.device;
metalctx.renderpass_descriptor_cb = sokol_metal_renderpass_descriptor_cb;
metalctx.drawable_cb = sokol_metal_drawable_cb;
void sokol_metal_destroy(sg_swapchain* swapchain) {
swapchain->metal.msaa_color_texture = nullptr;
swapchain->metal.depth_stencil_texture = nullptr;
swapchain->metal.current_drawable = nullptr;
#if TARGET_OS_IPHONE
mtk_view_controller = nullptr;
#endif
mtk_view = nullptr;
mtl_device = nullptr;
}

#endif
105 changes: 63 additions & 42 deletions Source/Render/sokol/SokolRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,11 @@
#define RENDERUTILS_HWND_FROM_SDL_WINDOW
#include "RenderUtils.h"
#include "SokolD3D.h"
#endif

//Callbacks for Sokol with D3D

const void* sokol_d3d_render_target_view_cb() {
cSokolRender* renderer = reinterpret_cast<cSokolRender*>(gb_RenderDevice);
return (const void*) renderer->d3d_context->render_target_view;
}

const void* sokol_d3d_depth_stencil_view_cb() {
cSokolRender* renderer = reinterpret_cast<cSokolRender*>(gb_RenderDevice);
return (const void*) renderer->d3d_context->depth_stencil_view;
}
#ifdef SOKOL_METAL
void sokol_metal_setup(SDL_Window* sdl_window, sg_desc* desc, sg_swapchain* swapchain, uint32_t ScreenHZ);
void sokol_metal_destroy(sg_swapchain* swapchain);
#endif

cSokolRender::cSokolRender() = default;
Expand Down Expand Up @@ -83,10 +76,22 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres
desc.shader_pool_size = 8,
desc.buffer_pool_size = 1024 * 8;
desc.image_pool_size = 1024 * 4; //1024 is enough for PGW+PET game
desc.context.color_format = SG_PIXELFORMAT_RGBA8;
desc.context.depth_format = SG_PIXELFORMAT_DEPTH_STENCIL;
desc.context.sample_count = sample_count;
desc.logger.func = slog_func;

//Setup swapchain pass
swapchain_pass = {};
swapchain_pass.action.colors[0].load_action = SG_LOADACTION_CLEAR;
swapchain_pass.action.colors[0].store_action = SG_STOREACTION_STORE;
swapchain_pass.action.colors[0].clear_value = sg_color { 0.0f, 0.0f, 0.0f, 1.0f };
swapchain_pass.action.depth.load_action = SG_LOADACTION_CLEAR;
swapchain_pass.action.depth.store_action = SG_STOREACTION_DONTCARE;
swapchain_pass.action.depth.clear_value = 1.0f;
swapchain_pass.action.stencil.load_action = SG_LOADACTION_CLEAR;
swapchain_pass.action.stencil.store_action = SG_STOREACTION_DONTCARE;
swapchain_pass.action.stencil.clear_value = 0;
swapchain_pass.swapchain.width = ScreenSize.x;
swapchain_pass.swapchain.height = ScreenSize.y;
swapchain_pass.swapchain.sample_count = 1;

//OpenGL / OpenGLES
#ifdef SOKOL_GL
Expand Down Expand Up @@ -129,6 +134,8 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres
ErrH.Abort("Error creating SDL GL Context", XERR_CRITICAL, 0, SDL_GetError());
}
printf("GPU vendor: %s, renderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDER));

swapchain_pass.swapchain.gl.framebuffer = 0;
#endif //SOKOL_GL

//Direct3D
Expand Down Expand Up @@ -211,6 +218,7 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres
dxgiAdapter->Release();

//Create swap chain
uint32_t sample_count = swapchain_pass.swapchain.sample_count;
DXGI_SWAP_CHAIN_DESC* swap_chain_desc = &d3d_context->swap_chain_desc;
memset(&d3d_context->swap_chain_desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC));
swap_chain_desc->BufferDesc.Width = static_cast<uint32_t>(xScr);
Expand Down Expand Up @@ -238,25 +246,16 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres
d3d_CreateDefaultRenderTarget();

//Setup d3d context
desc.context.d3d11.device = d3d_context->device;
desc.context.d3d11.device_context = d3d_context->device_context;
desc.context.d3d11.render_target_view_cb = sokol_d3d_render_target_view_cb;
desc.context.d3d11.depth_stencil_view_cb = sokol_d3d_depth_stencil_view_cb;

desc.environment.d3d11.device = d3d_context->device;
desc.environment.d3d11.device_context = d3d_context->device_context;
#endif

#ifdef SOKOL_METAL
sokol_backend = "Metal";
SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "metal", SDL_HINT_OVERRIDE);

// Obtain Metal device by creating a SDL Metal View, also useful to retain the Metal device
sdl_metal_view = SDL_Metal_CreateView(sdl_window);
if (sdl_metal_view == nullptr) {
ErrH.Abort("Error creating SDL Metal View", XERR_CRITICAL, 0, SDL_GetError());
}

//Setup metal sokol context
sokol_metal_setup_desc(sdl_metal_view, &desc);
sokol_metal_setup(sdl_window, &desc, &swapchain_pass.swapchain, ScreenHZ);
#endif

const char* render_driver = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
Expand Down Expand Up @@ -321,6 +320,10 @@ bool cSokolRender::ChangeSize(int xScr, int yScr, int mode) {
ScreenSize.y = yScr;
RenderMode &= ~mode_mask;
RenderMode |= mode;

//Update swapchain
swapchain_pass.swapchain.width = ScreenSize.x;
swapchain_pass.swapchain.height = ScreenSize.y;

#ifdef SOKOL_D3D11
if (d3d_context->swap_chain && need_resize) {
Expand Down Expand Up @@ -374,10 +377,9 @@ int cSokolRender::Done() {
}
#endif
#ifdef SOKOL_METAL
if (sdl_metal_view != nullptr) {
if (swapchain_pass.swapchain.metal.current_drawable != nullptr) {
RenderSubmitEvent(RenderEvent::DONE, "Sokol Metal shutdown");
SDL_Metal_DestroyView(sdl_metal_view);
sdl_metal_view = nullptr;
sokol_metal_destroy(&swapchain_pass.swapchain);
}
#endif
#ifdef SOKOL_GL
Expand Down Expand Up @@ -483,11 +485,11 @@ void cSokolRender::d3d_CreateDefaultRenderTarget() {
hr = d3d_context->swap_chain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&d3d_context->render_target)
reinterpret_cast<void**>(&d3d_context->render_target_texture)
);
assert(SUCCEEDED(hr) && d3d_context->render_target);
assert(SUCCEEDED(hr) && d3d_context->render_target_texture);
hr = d3d_context->device->CreateRenderTargetView(
d3d_context->render_target,
d3d_context->render_target_texture,
nullptr,
&d3d_context->render_target_view
);
Expand All @@ -498,25 +500,44 @@ void cSokolRender::d3d_CreateDefaultRenderTarget() {
ds_desc.Height = static_cast<uint32_t>(ScreenSize.y);
ds_desc.MipLevels = 1;
ds_desc.ArraySize = 1;
ds_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
ds_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
ds_desc.SampleDesc = d3d_context->swap_chain_desc.SampleDesc;
ds_desc.Usage = D3D11_USAGE_DEFAULT;
ds_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
hr = d3d_context->device->CreateTexture2D(&ds_desc, nullptr, &d3d_context->depth_stencil_buffer);
assert(SUCCEEDED(hr) && d3d_context->depth_stencil_buffer);
ds_desc.BindFlags = D3D11_BIND_RENDER_TARGET;

// MSAA render target and view
uint32_t sample_count = ds_desc.SampleDesc.Count;
if (1 < sample_count) {
hr = d3d_context->device->CreateTexture2D(&ds_desc, nullptr, &d3d_context->msaa_texture);
assert(SUCCEEDED(hr) && d3d_context->msaa_texture);
hr = d3d_context->device->CreateRenderTargetView(d3d_context->msaa_texture, nullptr, &d3d_context->msaa_view);
assert(SUCCEEDED(hr) && d3d_context->msaa_view);
}

D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
dsv_desc.Format = ds_desc.Format;
dsv_desc.ViewDimension = sample_count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
hr = d3d_context->device->CreateDepthStencilView(d3d_context->depth_stencil_buffer, &dsv_desc, &d3d_context->depth_stencil_view);
// Depth-stencil render target and view
ds_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
ds_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
hr = d3d_context->device->CreateTexture2D(&ds_desc, nullptr, &d3d_context->depth_stencil_texture);
assert(SUCCEEDED(hr) && d3d_context->depth_stencil_texture);
hr = d3d_context->device->CreateDepthStencilView(d3d_context->depth_stencil_texture, nullptr, &d3d_context->depth_stencil_view);
assert(SUCCEEDED(hr) && d3d_context->depth_stencil_view);

//Apply into swapchain pass
swapchain_pass.swapchain.d3d11.render_view = 1 < sample_count ? d3d_context->msaa_view : d3d_context->render_target_view;
swapchain_pass.swapchain.d3d11.resolve_view = 1 < sample_count ? d3d_context->render_target_view : nullptr;
swapchain_pass.swapchain.d3d11.depth_stencil_view = d3d_context->depth_stencil_view;
}

void cSokolRender::d3d_DestroyDefaultRenderTarget() {
RELEASE(d3d_context->render_target);
swapchain_pass.swapchain.d3d11.render_view = nullptr;
swapchain_pass.swapchain.d3d11.resolve_view = nullptr;
swapchain_pass.swapchain.d3d11.depth_stencil_view = nullptr;
RELEASE(d3d_context->render_target_texture);
RELEASE(d3d_context->render_target_view);
RELEASE(d3d_context->depth_stencil_buffer);
RELEASE(d3d_context->depth_stencil_texture);
RELEASE(d3d_context->depth_stencil_view);
RELEASE(d3d_context->msaa_texture);
RELEASE(d3d_context->msaa_view);
}
#endif

Expand Down
18 changes: 6 additions & 12 deletions Source/Render/sokol/SokolRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,10 @@
#include <sokol_gfx.h>
#include <SDL_video.h>

#ifdef SOKOL_METAL
#include <SDL_metal.h>
#endif

#include "SokolTypes.h"

const int PERIMETER_SOKOL_TEXTURES = 8;

#ifdef SOKOL_METAL
void sokol_metal_setup_desc(SDL_MetalView view, sg_desc* desc);
#endif

struct SokolCommand {
SokolCommand();
~SokolCommand();
Expand Down Expand Up @@ -54,7 +46,7 @@ class cSokolRender: public cInterfaceRenderDevice {
SDL_GLContext sdl_gl_context = nullptr;
#endif
#ifdef SOKOL_METAL
SDL_MetalView sdl_metal_view = nullptr;
friend void sokol_metal_render_callback();
#endif
//D3D backend stuff
#ifdef SOKOL_D3D11
Expand All @@ -67,13 +59,12 @@ class cSokolRender: public cInterfaceRenderDevice {
friend const void* sokol_d3d_depth_stencil_view_cb();
#endif

//Samples to use
uint32_t sample_count = 1;
//For swapchain pass that renders into final device
sg_pass swapchain_pass;

//Renderer state
bool ActiveScene = false;
bool isOrthographicProjSet = false;
sg_color fill_color;
std::vector<SokolCommand*> commands;
sg_sampler sampler;

Expand Down Expand Up @@ -124,6 +115,9 @@ class cSokolRender: public cInterfaceRenderDevice {

//Updates internal state after init/resolution change
int UpdateRenderMode();

//Does actual drawing using sokol API
void DoSokolRendering();

//Set common VS/FS parameters
template<typename T_VS, typename T_FS>
Expand Down
Loading

0 comments on commit a358a61

Please sign in to comment.