Skip to content

Instantly share code, notes, and snippets.

@DylanLukes
Last active April 26, 2023 23:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DylanLukes/2907e4ce03d8ceb231d0aea99189810e to your computer and use it in GitHub Desktop.
Save DylanLukes/2907e4ce03d8ceb231d0aea99189810e to your computer and use it in GitHub Desktop.
Small extension to BGFX for embedded shader loading when using (pure) C99.

Usage:

// Include the headers generated by shaderc.
// I am using CMake to automate compilation, loosely based on:
//     https://github.com/Paper-Cranes-Ltd/big2-stack
#include <generated/shaders/demo/all.h>

#include "util/bgfx/c99_embedded_shader.h"

static const bgfx_embedded_shader_t embedded_shaders[] = {
        BGFX_EMBEDDED_SHADER(vs_basic),
        BGFX_EMBEDDED_SHADER(fs_basic),
        BGFX_EMBEDDED_SHADER_END()
};
//
// Created by Dylan Lukes on 4/26/23.
//
#include "c99_embedded_shader.h"
#include <string.h>
bgfx_shader_handle_t bgfx_create_embedded_shader(
const bgfx_embedded_shader_t *_es,
enum bgfx_renderer_type _type,
const char *_name
) {
int _name_len = strlen(_name);
const bgfx_embedded_shader_t *es;
for (es = _es; NULL != es->name; ++es) {
if (0 == strncmp(_name, es->name, _name_len)) {
const bgfx_embedded_shader_data_t *esd = es->data;
for (esd = es->data; BGFX_RENDERER_TYPE_COUNT != esd->type; ++esd) {
if (_type == esd->type && 1 < esd->size) {
bgfx_shader_handle_t shader_handle;
shader_handle = bgfx_create_shader(bgfx_make_ref(esd->data, esd->size));
if (BGFX_HANDLE_IS_VALID(shader_handle)) {
bgfx_set_shader_name(shader_handle, _name, _name_len);
}
return shader_handle;
}
}
}
}
bgfx_shader_handle_t invalid_handle = BGFX_INVALID_HANDLE;
return invalid_handle;
}
/*
* Based on:
* - https://github.com/bkaradzic/bgfx/blob/master/include/bgfx/embedded_shader.h
* - Copyright 2011-2023 Branimir Karadzic. All rights reserved.
* - License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#ifndef BGFX_C99_EMBEDDED_SHADER_H_HEADER_GUARD
#define BGFX_C99_EMBEDDED_SHADER_H_HEADER_GUARD
#include <bx/platform.h>
#include <bgfx/c99/bgfx.h>
// Fills for macros missing from C99 BGFX.
#ifndef BX_CONCATENATE
#define BX_CONCATENATE(_x, _y) BX_CONCATENATE_(_x, _y)
#define BX_CONCATENATE_(_x, _y) _x ## _y
#endif // BX_CONCATENATE
#ifndef BX_COUNTOF
// If on C11 and with GNU statement expr could use this to make it a little less dangerous.
#define ARRAY_ONLY(arr) _Static_assert(_Generic((arr), \
default: \
sizeof(arr) == sizeof(arr[0]) * \
(sizeof(arr)/sizeof(arr[0]))) \
, "Macro only accepts array types");
#define BX_COUNTOF(x) ((sizeof(x) / sizeof(*(x))) - 1)
#endif // BX_COUNTOF
#define BGFX_EMBEDDED_SHADER_DXBC(...)
#define BGFX_EMBEDDED_SHADER_DX9BC(...)
#define BGFX_EMBEDDED_SHADER_PSSL(...)
#define BGFX_EMBEDDED_SHADER_ESSL(...)
#define BGFX_EMBEDDED_SHADER_GLSL(...)
#define BGFX_EMBEDDED_SHADER_METAL(...)
#define BGFX_EMBEDDED_SHADER_NVN(...)
#define BGFX_EMBEDDED_SHADER_SPIRV(...)
#define BGFX_PLATFORM_SUPPORTS_DX9BC (0 \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_WINDOWS \
)
#define BGFX_PLATFORM_SUPPORTS_DXBC (0 \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_WINDOWS \
|| BX_PLATFORM_WINRT \
|| BX_PLATFORM_XBOXONE \
)
#define BGFX_PLATFORM_SUPPORTS_PSSL (0 \
|| BX_PLATFORM_PS4 \
|| BX_PLATFORM_PS5 \
)
#define BGFX_PLATFORM_SUPPORTS_ESSL (0 \
|| BX_PLATFORM_ANDROID \
|| BX_PLATFORM_EMSCRIPTEN \
|| BX_PLATFORM_IOS \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_OSX \
|| BX_PLATFORM_RPI \
|| BX_PLATFORM_WINDOWS \
)
#define BGFX_PLATFORM_SUPPORTS_GLSL (0 \
|| BX_PLATFORM_BSD \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_OSX \
|| BX_PLATFORM_WINDOWS \
)
#define BGFX_PLATFORM_SUPPORTS_METAL (0 \
|| BX_PLATFORM_IOS \
|| BX_PLATFORM_OSX \
)
#define BGFX_PLATFORM_SUPPORTS_NVN (0 \
|| BX_PLATFORM_NX \
)
#define BGFX_PLATFORM_SUPPORTS_SPIRV (0 \
|| BX_PLATFORM_ANDROID \
|| BX_PLATFORM_EMSCRIPTEN \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_WINDOWS \
|| BX_PLATFORM_OSX \
)
#if BGFX_PLATFORM_SUPPORTS_DX9BC
# undef BGFX_EMBEDDED_SHADER_DX9BC
# define BGFX_EMBEDDED_SHADER_DX9BC(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _dx9 ), BX_COUNTOF(BX_CONCATENATE(_name, _dx9 ) ) },
#endif // BGFX_PLATFORM_SUPPORTS_DX9BC
#if BGFX_PLATFORM_SUPPORTS_DXBC
# undef BGFX_EMBEDDED_SHADER_DXBC
# define BGFX_EMBEDDED_SHADER_DXBC(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _dx11), BX_COUNTOF(BX_CONCATENATE(_name, _dx11) ) },
#endif // BGFX_PLATFORM_SUPPORTS_DXBC
#if BGFX_PLATFORM_SUPPORTS_PSSL
# undef BGFX_EMBEDDED_SHADER_PSSL
# define BGFX_EMBEDDED_SHADER_PSSL(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _pssl), BX_CONCATENATE(_name, _pssl_size) },
#endif // BGFX_PLATFORM_SUPPORTS_PSSL
#if BGFX_PLATFORM_SUPPORTS_ESSL
# undef BGFX_EMBEDDED_SHADER_ESSL
# define BGFX_EMBEDDED_SHADER_ESSL(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _essl), BX_COUNTOF(BX_CONCATENATE(_name, _essl) ) },
#endif // BGFX_PLATFORM_SUPPORTS_ESSL
#if BGFX_PLATFORM_SUPPORTS_GLSL
# undef BGFX_EMBEDDED_SHADER_GLSL
# define BGFX_EMBEDDED_SHADER_GLSL(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _glsl), BX_COUNTOF(BX_CONCATENATE(_name, _glsl) ) },
#endif // BGFX_PLATFORM_SUPPORTS_GLSL
#if BGFX_PLATFORM_SUPPORTS_SPIRV
# undef BGFX_EMBEDDED_SHADER_SPIRV
# define BGFX_EMBEDDED_SHADER_SPIRV(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _spv), BX_COUNTOF(BX_CONCATENATE(_name, _spv) ) },
#endif // BGFX_PLATFORM_SUPPORTS_SPIRV
#if BGFX_PLATFORM_SUPPORTS_METAL
# undef BGFX_EMBEDDED_SHADER_METAL
# define BGFX_EMBEDDED_SHADER_METAL(_renderer, _name) \
{ _renderer, BX_CONCATENATE(_name, _mtl), BX_COUNTOF(BX_CONCATENATE(_name, _mtl) ) },
#endif // BGFX_PLATFORM_SUPPORTS_METAL
#define BGFX_EMBEDDED_SHADER(_name) \
{ \
#_name, \
{ \
BGFX_EMBEDDED_SHADER_PSSL (BGFX_RENDERER_TYPE_AGC, _name) \
BGFX_EMBEDDED_SHADER_DX9BC(BGFX_RENDERER_TYPE_DIRECT3D9, _name) \
BGFX_EMBEDDED_SHADER_DXBC (BGFX_RENDERER_TYPE_DIRECT3D11, _name) \
BGFX_EMBEDDED_SHADER_DXBC (BGFX_RENDERER_TYPE_DIRECT3D12, _name) \
BGFX_EMBEDDED_SHADER_PSSL (BGFX_RENDERER_TYPE_GNM, _name) \
BGFX_EMBEDDED_SHADER_METAL(BGFX_RENDERER_TYPE_METAL, _name) \
BGFX_EMBEDDED_SHADER_NVN (BGFX_RENDERER_TYPE_NVN, _name) \
BGFX_EMBEDDED_SHADER_ESSL (BGFX_RENDERER_TYPE_OPENGLES, _name) \
BGFX_EMBEDDED_SHADER_GLSL (BGFX_RENDERER_TYPE_OPENGL, _name) \
BGFX_EMBEDDED_SHADER_SPIRV(BGFX_RENDERER_TYPE_VULKAN, _name) \
BGFX_EMBEDDED_SHADER_SPIRV(BGFX_RENDERER_TYPE_WEBGPU, _name) \
{ BGFX_RENDERER_TYPE_NOOP, (const uint8_t*)"VSH\x5\x0\x0\x0\x0\x0\x0", 10 }, \
{ BGFX_RENDERER_TYPE_COUNT, NULL, 0 } \
} \
}
#define BGFX_EMBEDDED_SHADER_END() \
{ \
NULL, \
{ \
{ BGFX_RENDERER_TYPE_COUNT, NULL, 0 } \
} \
}
typedef struct bgfx_embedded_shader_data_s {
enum bgfx_renderer_type type;
const uint8_t *data;
uint32_t size;
} bgfx_embedded_shader_data_t;
typedef struct bgfx_embedded_shader_s {
const char *name;
bgfx_embedded_shader_data_t data[BGFX_RENDERER_TYPE_COUNT];
} bgfx_embedded_shader_t;
/// Create shader from embedded shader data.
///
/// @param[in] _es Pointer to `BGFX_EMBEDDED_SHADER` data.
/// @param[in] _type Renderer backend type. See: `bgfx_renderer_type`
/// @param[in] _name Shader name.
/// @returns Shader handle.
///
bgfx_shader_handle_t bgfx_create_embedded_shader(
const bgfx_embedded_shader_t *_es,
enum bgfx_renderer_type _type,
const char *_name
);
#endif // BGFX_C99_EMBEDDED_SHADER_H_HEADER_GUARD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment