OpenGL ES added for handhelds.
This commit is contained in:
parent
d73966c1e6
commit
ffc1d54a89
17 changed files with 3446 additions and 310 deletions
21
CHANGELOG
21
CHANGELOG
|
|
@ -1245,6 +1245,27 @@ SINGE 2.10
|
|||
New Features
|
||||
------------
|
||||
|
||||
- Texture samplers now walk the whole mipmap chain. SDL hands max_lod
|
||||
straight to Vulkan's maxLod and Direct3D 12's MaxLOD, and the scene
|
||||
and GUI left it at the zero a memset gives, which clamps every lookup
|
||||
to mip level 0. Mipmapping was therefore off on every backend:
|
||||
distant surfaces aliased, the 8x anisotropy did far less than it
|
||||
looked, and the sky cube could not pick a level by roughness.
|
||||
|
||||
- An OpenGL ES 3.1 backend for the 3D scene and the GUI. SDL_GPU has
|
||||
Vulkan, Direct3D 12 and Metal and no OpenGL of any kind, which left the
|
||||
cheap Linux handhelds and the Raspberry Pi with 2D only: their Mali and
|
||||
VideoCore parts have a mature GLES driver and either no Vulkan or an
|
||||
immature one. The subset of SDL_GPU the scene and the GUI use is now
|
||||
behind one table of function pointers with two implementations, so both
|
||||
files stay the single description of what Singe draws, and the backend is
|
||||
chosen at run time -- one aarch64 binary serves a board with Vulkan and one
|
||||
without. The ES shaders come from the same HLSL through SPIRV-Cross, and
|
||||
the GL entry points are loaded through SDL rather than linked, so a machine
|
||||
with no GLES driver simply keeps its 2D renderer. The Raspberry Pi 4
|
||||
remains the minimum for 3D: the Pi 3 has only OpenGL ES 2.0, which cannot
|
||||
express the scene's skinning or morph targets.
|
||||
|
||||
- spriteDraw() now has two more forms. In addition to being able to draw
|
||||
regular sprites and stretched sprites it can now draw both using the
|
||||
sprite's center as the anchor instead of the upper left. This is highly
|
||||
|
|
|
|||
|
|
@ -327,6 +327,12 @@ set(SINGE_SOURCE
|
|||
src/midiIo.h
|
||||
thirdparty/tinysoundfont/tsf.h
|
||||
thirdparty/tinysoundfont/tml.h
|
||||
src/render.c
|
||||
src/render.h
|
||||
src/renderGles.c
|
||||
src/renderGlesApi.h
|
||||
src/renderGlesLoad.c
|
||||
src/renderGpu.c
|
||||
src/scene.c
|
||||
src/scene.h
|
||||
src/singe.c
|
||||
|
|
@ -755,10 +761,19 @@ if(NOT SINGE_SHADERCROSS)
|
|||
message(FATAL_ERROR "SDL_shadercross is needed to compile the scene shaders; build through the superbuild (cmake --preset ...) or set SINGE_SHADERCROSS.")
|
||||
endif()
|
||||
endif()
|
||||
# SPIRV-Cross turns the same SPIR-V into GLSL ES for the GLES backend (PLAN.md section 56). Unlike
|
||||
# shadercross this one is not fatal when missing: the header then carries null ES strings, the GLES
|
||||
# backend declines to start, and every other platform builds exactly as before.
|
||||
if(NOT SINGE_SPIRV_CROSS)
|
||||
find_program(SINGE_SPIRV_CROSS spirv-cross)
|
||||
endif()
|
||||
if(NOT SINGE_SPIRV_CROSS)
|
||||
message(WARNING "spirv-cross was not found; this build will have no OpenGL ES shaders and so no GLES backend.")
|
||||
endif()
|
||||
set(shaderHeader ${CMAKE_BINARY_DIR}/generated/shaders/sceneShaders.h)
|
||||
add_custom_command(
|
||||
OUTPUT ${shaderHeader}
|
||||
COMMAND ${CMAKE_COMMAND} -DSHADERCROSS=${SINGE_SHADERCROSS} -DSOURCE=${CMAKE_SOURCE_DIR}/src/shaders/scene.hlsl -DOUTPUT=${shaderHeader} -P ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DSHADERCROSS=${SINGE_SHADERCROSS} -DSPIRVCROSS=${SINGE_SPIRV_CROSS} -DSOURCE=${CMAKE_SOURCE_DIR}/src/shaders/scene.hlsl -DOUTPUT=${shaderHeader} -P ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/src/shaders/scene.hlsl ${CMAKE_SOURCE_DIR}/src/sceneShared.h ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
COMMENT "Compiling the scene shaders"
|
||||
)
|
||||
|
|
@ -769,7 +784,7 @@ set(guiShaderHeader ${CMAKE_BINARY_DIR}/generated/shaders/guiShaders.h)
|
|||
set(guiShaderEntries "guiVertex:vertex;guiFragmentColor:fragment;guiFragmentTexture:fragment;guiFragmentFilter:fragment;guiFragmentBlur:fragment;guiFragmentColorMatrix:fragment;guiFragmentGradient:fragment")
|
||||
add_custom_command(
|
||||
OUTPUT ${guiShaderHeader}
|
||||
COMMAND ${CMAKE_COMMAND} -DSHADERCROSS=${SINGE_SHADERCROSS} -DSOURCE=${CMAKE_SOURCE_DIR}/src/shaders/gui.hlsl -DOUTPUT=${guiShaderHeader} "-DENTRIES=${guiShaderEntries}" -DPREFIX=guiShader -DTYPE=GuiShaderT -P ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DSHADERCROSS=${SINGE_SHADERCROSS} -DSPIRVCROSS=${SINGE_SPIRV_CROSS} -DSOURCE=${CMAKE_SOURCE_DIR}/src/shaders/gui.hlsl -DOUTPUT=${guiShaderHeader} "-DENTRIES=${guiShaderEntries}" -DPREFIX=guiShader -DTYPE=GuiShaderT -P ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/src/shaders/gui.hlsl ${CMAKE_SOURCE_DIR}/cmake/shaderHeader.cmake
|
||||
COMMENT "Compiling the GUI shaders"
|
||||
VERBATIM
|
||||
|
|
|
|||
3
INSTALL
3
INSTALL
|
|
@ -122,7 +122,8 @@ newer, the 64-bit Raspberry Pi OS among them. It is not Pi specific: the
|
|||
decoder it builds talks to any V4L2 memory-to-memory device, so one binary
|
||||
also serves Amlogic, Exynos, Qualcomm and other boards whose kernel offers
|
||||
one, and it carries Rockchip's own decoders besides. 3D games need a Pi 4
|
||||
or later; the Pi 3 has no Vulkan driver and plays 2D games only. The build
|
||||
or later, which has OpenGL ES 3.1 (and Vulkan); the Pi 3 has only OpenGL
|
||||
ES 2.0 and plays 2D games only. The build
|
||||
uses zig. The platform headers and libraries it links against are Debian
|
||||
bookworm arm64 packages listed in cmake/zig/arm64Packages.cmake, fetched
|
||||
from snapshot.debian.org and unpacked with dpkg-deb into
|
||||
|
|
|
|||
|
|
@ -58,9 +58,13 @@ endfunction()
|
|||
|
||||
# SDL3 for the host, shared, with nothing SDL_shadercross's tool does not use.
|
||||
singeHostProject(hostSDL3 ${SB_THIRDPARTY}/SDL3 "" "-DSDL_SHARED=ON;-DSDL_STATIC=OFF;-DSDL_TESTS=OFF;-DSDL_EXAMPLES=OFF;-DSDL_AUDIO=OFF;-DSDL_VIDEO=OFF;-DSDL_GPU=OFF;-DSDL_RENDER=OFF;-DSDL_CAMERA=OFF;-DSDL_JOYSTICK=OFF;-DSDL_HAPTIC=OFF;-DSDL_HIDAPI=OFF;-DSDL_POWER=OFF;-DSDL_SENSOR=OFF;-DSDL_DIALOG=OFF;-DSDL_UNIX_CONSOLE_BUILD=ON")
|
||||
# SPIRV-Cross as the shared C library SDL_shadercross looks for.
|
||||
singeHostProject(spirvCross ${SB_THIRDPARTY}/SPIRV-Cross "" "-DSPIRV_CROSS_SHARED=ON;-DSPIRV_CROSS_STATIC=OFF;-DSPIRV_CROSS_CLI=OFF;-DSPIRV_CROSS_ENABLE_TESTS=OFF")
|
||||
# SPIRV-Cross as the shared C library SDL_shadercross looks for, and as the command line tool that
|
||||
# turns SPIR-V into GLSL ES for the GLES backend -- SDL_shadercross emits DXBC, DXIL, MSL, SPIRV,
|
||||
# HLSL and JSON and no GLSL of any kind, so the ES shaders come from this one (PLAN.md section 56).
|
||||
# The CLI needs the static library as well as the shared one.
|
||||
singeHostProject(spirvCross ${SB_THIRDPARTY}/SPIRV-Cross "" "-DSPIRV_CROSS_SHARED=ON;-DSPIRV_CROSS_STATIC=ON;-DSPIRV_CROSS_CLI=ON;-DSPIRV_CROSS_ENABLE_TESTS=OFF")
|
||||
# SDL_shadercross, unvendored: SPIRV-Cross and SDL3 from the host prefix, DXC from its download.
|
||||
singeHostProject(shadercross ${SB_THIRDPARTY}/SDL_shadercross "hostSDL3;spirvCross" "-DSDLSHADERCROSS_VENDORED=OFF;-DSDLSHADERCROSS_DXC=ON;-DSDLSHADERCROSS_SHARED=OFF;-DSDLSHADERCROSS_STATIC=ON;-DSDLSHADERCROSS_CLI=ON;-DSDLSHADERCROSS_INSTALL=ON;-DSDLSHADERCROSS_INSTALL_CPACK=OFF;-DCMAKE_PREFIX_PATH=${hostPrefix}|${hostDxc};-DSDL3_DIR=${hostPrefix}/lib/cmake/SDL3")
|
||||
|
||||
set(SINGE_SHADERCROSS ${hostPrefix}/bin/shadercross)
|
||||
set(SINGE_SPIRV_CROSS ${hostPrefix}/bin/spirv-cross)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
# Compiles src/shaders/scene.hlsl (which includes src/sceneShared.h) into a C header of SPIR-V, DXIL and MSL blobs with
|
||||
# SDL_shadercross. Run by the build as
|
||||
# cmake -DSHADERCROSS=<tool> -DSOURCE=<scene.hlsl> -DOUTPUT=<sceneShaders.h> -P shaderHeader.cmake
|
||||
# Compiles src/shaders/scene.hlsl (which includes src/sceneShared.h) into a C header of SPIR-V, DXIL, MSL and GLSL ES
|
||||
# with SDL_shadercross and SPIRV-Cross. Run by the build as
|
||||
# cmake -DSHADERCROSS=<tool> -DSPIRVCROSS=<tool> -DSOURCE=<scene.hlsl> -DOUTPUT=<sceneShaders.h> -P shaderHeader.cmake
|
||||
# so the header is generated into the build tree like the icon and the other embedded files.
|
||||
#
|
||||
# SDL_shadercross has no GLSL destination (DXBC, DXIL, MSL, SPIRV, HLSL, JSON), so the ES form is a second step over the
|
||||
# SPIR-V it already produced: one pipeline, four outputs. SPIRVCROSS may be empty, and then the ES strings are null and
|
||||
# the GLES backend refuses to start -- which is what a build without the host tool should do rather than fail.
|
||||
|
||||
# Invoked in script mode: -DSHADERCROSS -DSOURCE=<file.hlsl> -DOUTPUT=<header> -DENTRIES=<name:stage;...>
|
||||
# -DPREFIX=<lowerCamel prefix> -DTYPE=<struct name>. ENTRIES, PREFIX and TYPE default to the scene's.
|
||||
|
|
@ -19,6 +23,28 @@ string(TOUPPER "${PREFIX}" guard)
|
|||
string(REPLACE "SHADER" "_SHADERS_H" guard "${guard}")
|
||||
set(entries ${ENTRIES})
|
||||
set(formats SPIRV DXIL MSL)
|
||||
|
||||
# GLSL ES 3.10 for the GLES backend. Three switches matter and each is load bearing:
|
||||
# --es --version 310 ES 3.1, the floor the scene needs; its storage buffers are ES 3.1 only.
|
||||
# --combined-samplers-inherit-bindings
|
||||
# HLSL's separate Texture2D and SamplerState have no ES equivalent, so SPIRV-Cross folds
|
||||
# each pair into one sampler and keeps the HLSL t-register as the binding, which is the
|
||||
# slot the engine already binds by.
|
||||
# --remove-unused-variables Without it every entry point declares every cbuffer and both storage buffers in the file:
|
||||
# fragmentMain came out with twelve blocks instead of two, and a fragment shader that
|
||||
# merely declares an unused SSBO can fail to link where MAX_FRAGMENT_SHADER_STORAGE_BLOCKS
|
||||
# is zero, which ES 3.1 permits.
|
||||
# --flip-vert-y SDL_GPU puts the framebuffer origin at the top left, as Vulkan, D3D12 and Metal do, and
|
||||
# GL puts it at the bottom left. Without this every render to a texture arrives upside
|
||||
# down -- the GUI came out mirrored the first time this ran. Inverting gl_Position.y is
|
||||
# the same fix as a negative viewport height, and it also reverses triangle winding, which
|
||||
# renderGles.c undoes by flipping the front face it sets.
|
||||
# --fixup-clipspace HLSL puts clip-space Z in [0, w] and GL in [-w, w], and GL then stores (z/w + 1) / 2.
|
||||
# Without the rewrite a depth written as d lands in the buffer as (d + 1) / 2, while the
|
||||
# shader's own shadow comparison still computes d -- so everything in the near half of a
|
||||
# light's range read as lit. Sponza showed it as a 2.6x too bright mid-shadow band with
|
||||
# correct highlights and correct deep shadow, which is what a half-range comparison does.
|
||||
set(esslFlags --es --version 310 --combined-samplers-inherit-bindings --remove-unused-variables --flip-vert-y --fixup-clipspace)
|
||||
get_filename_component(sourceDir ${SOURCE} DIRECTORY)
|
||||
get_filename_component(includeDir ${sourceDir} DIRECTORY)
|
||||
get_filename_component(outputDir ${OUTPUT} DIRECTORY)
|
||||
|
|
@ -26,10 +52,10 @@ set(work ${outputDir}/work)
|
|||
file(MAKE_DIRECTORY ${work})
|
||||
|
||||
set(header "// Generated from ${sourceName} by cmake/shaderHeader.cmake with SDL_shadercross; do not edit.\n")
|
||||
string(APPEND header "// SPIR-V for Vulkan, DXIL for Direct3D 12, MSL for Metal, one set per entry point.\n\n")
|
||||
string(APPEND header "#ifndef ${guard}\n#define ${guard}\n\n#include <stddef.h>\n\n")
|
||||
string(APPEND header "// SPIR-V for Vulkan, DXIL for Direct3D 12, MSL for Metal, GLSL ES for OpenGL ES, one set per entry point.\n\n")
|
||||
string(APPEND header "#ifndef ${guard}\n#define ${guard}\n\n#include <stddef.h>\n#include <stdlib.h>\n\n")
|
||||
string(REGEX REPLACE "T$" "S" structName "${TYPE}")
|
||||
string(APPEND header "typedef struct ${structName} {\n\tconst char *entryPoint;\n\tconst unsigned char *spirv;\n\tsize_t spirvSize;\n\tconst unsigned char *dxil;\n\tsize_t dxilSize;\n\tconst unsigned char *msl;\n\tsize_t mslSize;\n} ${TYPE};\n\n")
|
||||
string(APPEND header "typedef struct ${structName} {\n\tconst char *entryPoint;\n\tconst unsigned char *spirv;\n\tsize_t spirvSize;\n\tconst unsigned char *dxil;\n\tsize_t dxilSize;\n\tconst unsigned char *msl;\n\tsize_t mslSize;\n\tconst char *essl; // GLSL ES 3.10 source, or NULL when the host tool was absent\n} ${TYPE};\n\n")
|
||||
foreach(entry IN LISTS entries)
|
||||
string(REPLACE ":" ";" parts ${entry})
|
||||
list(GET parts 0 name)
|
||||
|
|
@ -45,10 +71,31 @@ foreach(entry IN LISTS entries)
|
|||
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," bytes "${hex}")
|
||||
string(APPEND header "static const unsigned char _${name}${format}[] = {\n\t${bytes}\n};\n\n")
|
||||
endforeach()
|
||||
# The ES form, cross compiled from the SPIR-V above. Emitted as a C string rather than bytes because that is what
|
||||
# glShaderSource takes; the escaping is only quotes and backslashes, neither of which GLSL ES has a use for.
|
||||
set(esslSymbol "NULL")
|
||||
if(SPIRVCROSS)
|
||||
set(essl ${work}/${name}.essl)
|
||||
execute_process(COMMAND ${SPIRVCROSS} ${esslFlags} ${work}/${name}.spirv --output ${essl} RESULT_VARIABLE code OUTPUT_VARIABLE out ERROR_VARIABLE err)
|
||||
if(NOT code EQUAL 0)
|
||||
message(FATAL_ERROR "Shader ${name} (GLSL ES) failed to cross compile:\n${out}\n${err}")
|
||||
endif()
|
||||
file(READ ${essl} esslText)
|
||||
# SPIRV-Cross defaults an ES fragment shader to "precision mediump float", and a struct
|
||||
# declared inside a uniform block carries no qualifier of its own, so Light's members inherit
|
||||
# mediump -- fp16 on a real tiler. The scene's own values do not fit that: a camera or a
|
||||
# light tens of units from the origin loses whole units of position. Ask for highp instead.
|
||||
string(REPLACE "precision mediump float;" "precision highp float;" esslText "${esslText}")
|
||||
string(REPLACE "\\" "\\\\" esslText "${esslText}")
|
||||
string(REPLACE "\"" "\\\"" esslText "${esslText}")
|
||||
string(REPLACE "\n" "\\n\"\n\t\"" esslText "${esslText}")
|
||||
string(APPEND header "static const char _${name}ESSL[] =\n\t\"${esslText}\";\n\n")
|
||||
set(esslSymbol "_${name}ESSL")
|
||||
endif()
|
||||
string(SUBSTRING ${name} 0 1 initial)
|
||||
string(SUBSTRING ${name} 1 -1 rest)
|
||||
string(TOUPPER ${initial} initial)
|
||||
string(APPEND header "static const ${TYPE} ${PREFIX}${initial}${rest} = { \"${name}\", _${name}SPIRV, sizeof(_${name}SPIRV), _${name}DXIL, sizeof(_${name}DXIL), _${name}MSL, sizeof(_${name}MSL) };\n\n")
|
||||
string(APPEND header "static const ${TYPE} ${PREFIX}${initial}${rest} = { \"${name}\", _${name}SPIRV, sizeof(_${name}SPIRV), _${name}DXIL, sizeof(_${name}DXIL), _${name}MSL, sizeof(_${name}MSL), ${esslSymbol} };\n\n")
|
||||
endforeach()
|
||||
string(APPEND header "#endif\n")
|
||||
file(WRITE ${OUTPUT} "${header}")
|
||||
|
|
|
|||
|
|
@ -840,10 +840,13 @@ do not allow you to use stereo, you can use Virtual Audio Cable to fix this:
|
|||
|
||||
*Does 3D work on a Raspberry Pi?*
|
||||
|
||||
On a Raspberry Pi 4 or later, yes: they have the Vulkan driver the 3D scene
|
||||
needs. The Pi 3 and earlier do not, so they run 2D games (2D physics included)
|
||||
exactly as before and refuse the first 3D call. The Pi 4 is the minimum for
|
||||
any game that uses the 3D Scenes chapter.
|
||||
On a Raspberry Pi 4 or later, yes. They have both a Vulkan driver and OpenGL
|
||||
ES 3.1, and Singe uses whichever it finds. The Pi 3 has only OpenGL ES 2.0,
|
||||
which cannot express the scene's skinning or morph targets, so it runs 2D games
|
||||
(2D physics included) exactly as before and refuses the first 3D call. The Pi 4
|
||||
is the minimum for any game that uses the 3D Scenes chapter. The same applies to
|
||||
the cheap handhelds: a Mali-G31 or G610 has the ES 3.1 the scene needs, whether
|
||||
or not it has Vulkan.
|
||||
|
||||
*Why does my audio stutter on the Raspberry Pi?*
|
||||
|
||||
|
|
@ -2557,11 +2560,15 @@ end
|
|||
==== Performance and Requirements
|
||||
|
||||
The scene needs a GPU that speaks Vulkan (Linux), Direct3D 12 (Windows 10
|
||||
and later) or Metal (macOS). The Raspberry Pi 4 is the minimum Pi for 3D:
|
||||
it and every later model have a Vulkan driver, the Pi 3 and earlier do not.
|
||||
On a machine without a suitable GPU, 2D games run exactly as before (2D
|
||||
physics included) and the first 3D call ends the game with an error naming
|
||||
the problem.
|
||||
and later), Metal (macOS) or OpenGL ES 3.1. The ES backend is what brings in
|
||||
the cheap Linux handhelds and the Raspberry Pi, whose Mali and VideoCore parts
|
||||
have a mature GLES driver and either no Vulkan at all or an immature one; it is
|
||||
chosen automatically when none of the other three is available, and it draws
|
||||
the same picture from the same shaders. The Raspberry Pi 4 remains the minimum
|
||||
Pi for 3D: the Pi 3 has only OpenGL ES 2.0, which cannot express the scene's
|
||||
skinning or morph targets. On a machine without any of them, 2D games run
|
||||
exactly as before (2D physics included) and the first 3D call ends the game
|
||||
with an error naming the problem.
|
||||
|
||||
Meshes outside the camera's view are skipped, and copies of the same mesh
|
||||
with the same material draw as one instanced call, so a forest of one tree
|
||||
|
|
|
|||
29
src/gui.cpp
29
src/gui.cpp
|
|
@ -39,6 +39,7 @@
|
|||
#include <RmlUi/Lua.h>
|
||||
#include "gui.h"
|
||||
#include "guiRender.h"
|
||||
#include "render.h"
|
||||
extern "C" {
|
||||
#include "util.h"
|
||||
#include "vfs.h"
|
||||
|
|
@ -459,10 +460,10 @@ static void _releaseContext(GuiContextT *context) {
|
|||
SDL_DestroyTexture(context->wrap);
|
||||
}
|
||||
if (context->target != nullptr) {
|
||||
SDL_ReleaseGPUTexture(_device, context->target);
|
||||
rgpuReleaseTexture(_device, context->target);
|
||||
}
|
||||
if (context->stencil != nullptr) {
|
||||
SDL_ReleaseGPUTexture(_device, context->stencil);
|
||||
rgpuReleaseTexture(_device, context->stencil);
|
||||
}
|
||||
_render->ReleaseLayers((uint32_t)context->width, (uint32_t)context->height);
|
||||
memset(context, 0, sizeof(GuiContextT));
|
||||
|
|
@ -478,12 +479,12 @@ static void _renderContext(GuiContextT *context, SDL_GPUCommandBuffer *commands)
|
|||
target.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
target.store_op = SDL_GPU_STOREOP_STORE;
|
||||
target.clear_color = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
pass = SDL_BeginGPURenderPass(commands, &target, 1, nullptr);
|
||||
pass = rgpuBeginRenderPass(commands, &target, 1, nullptr);
|
||||
if (pass == nullptr) {
|
||||
utilTrace("Gui: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
SDL_EndGPURenderPass(pass);
|
||||
rgpuEndRenderPass(pass);
|
||||
_render->BeginFrame(commands, context->target, context->stencil, (uint32_t)context->width, (uint32_t)context->height);
|
||||
context->context->Render();
|
||||
_render->EndFrame();
|
||||
|
|
@ -666,7 +667,7 @@ bool guiInit(SDL_GPUDevice *device, SDL_Renderer *renderer, SDL_Window *window)
|
|||
utilTrace("Gui: no GPU device; the GUI is unavailable");
|
||||
return false;
|
||||
}
|
||||
_targetFormat = SDL_GetGPUSwapchainTextureFormat(device, window);
|
||||
_targetFormat = rgpuGetSwapchainTextureFormat(device, window);
|
||||
_wrapFormat = _pixelFormatOf(_targetFormat);
|
||||
if (_wrapFormat == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
utilTrace("Gui: unsupported swapchain format %d; the GUI is unavailable", (int32_t)_targetFormat);
|
||||
|
|
@ -838,7 +839,6 @@ bool guiMouseWheel(int32_t gui, float delta) {
|
|||
int32_t guiNew(int32_t width, int32_t height) {
|
||||
GuiContextT *context = nullptr;
|
||||
SDL_GPUTextureCreateInfo info = {};
|
||||
SDL_PropertiesID props = 0;
|
||||
int32_t slot = GUI_NO_HANDLE;
|
||||
int32_t i = 0;
|
||||
|
||||
|
|
@ -870,7 +870,7 @@ int32_t guiNew(int32_t width, int32_t height) {
|
|||
info.layer_count_or_depth = 1;
|
||||
info.num_levels = 1;
|
||||
info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
context->target = SDL_CreateGPUTexture(_device, &info);
|
||||
context->target = rgpuCreateTexture(_device, &info);
|
||||
if (context->target == nullptr) {
|
||||
_setError("%s", SDL_GetError());
|
||||
_releaseContext(context);
|
||||
|
|
@ -881,21 +881,14 @@ int32_t guiNew(int32_t width, int32_t height) {
|
|||
if (_render->StencilFormat() != SDL_GPU_TEXTUREFORMAT_INVALID) {
|
||||
info.format = _render->StencilFormat();
|
||||
info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
||||
context->stencil = SDL_CreateGPUTexture(_device, &info);
|
||||
context->stencil = rgpuCreateTexture(_device, &info);
|
||||
if (context->stencil == nullptr) {
|
||||
_setError("%s", SDL_GetError());
|
||||
_releaseContext(context);
|
||||
return GUI_NO_HANDLE;
|
||||
}
|
||||
}
|
||||
props = SDL_CreateProperties();
|
||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER, context->target);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, _wrapFormat);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, height);
|
||||
context->wrap = SDL_CreateTextureWithProperties(_renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
context->wrap = renderWrapTexture(_renderer, context->target, (SDL_PixelFormat)_wrapFormat, width, height);
|
||||
if (context->wrap == nullptr) {
|
||||
_setError("%s", SDL_GetError());
|
||||
_releaseContext(context);
|
||||
|
|
@ -1024,7 +1017,7 @@ void guiUpdate(double seconds) {
|
|||
}
|
||||
}
|
||||
_freeDeadListeners();
|
||||
commands = SDL_AcquireGPUCommandBuffer(_device);
|
||||
commands = rgpuAcquireCommandBuffer(_device);
|
||||
if (commands == nullptr) {
|
||||
utilTrace("Gui: %s", SDL_GetError());
|
||||
return;
|
||||
|
|
@ -1036,7 +1029,7 @@ void guiUpdate(double seconds) {
|
|||
}
|
||||
}
|
||||
_render->GetStats(&_stats);
|
||||
SDL_SubmitGPUCommandBuffer(commands);
|
||||
rgpuSubmitCommandBuffer(commands);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ extern "C" {
|
|||
#include "decode.h"
|
||||
}
|
||||
#include "guiRender.h"
|
||||
#include "render.h"
|
||||
#include "shaders/guiShaders.h"
|
||||
|
||||
#define BYTES_PER_PIXEL 4 // RGBA8, as RmlUi hands textures over and as the layers are
|
||||
|
|
@ -82,6 +83,7 @@ extern "C" {
|
|||
#define UNIFORM_TRANSFORM 0
|
||||
#define UNIFORM_TRANSLATE 1
|
||||
#define PASS_UNIFORMS 1 // The filter, blur and colour matrix shaders' one block each
|
||||
#define GUI_SAMPLER_MAX_LOD 1000.0f // "No clamp": walk the whole mipmap chain
|
||||
#define FILTER_SAMPLERS 2 // guiFragmentFilter: the source and the mask image
|
||||
#define SCREEN_QUAD_VERTICES 4
|
||||
#define SCREEN_QUAD_INDICES 6
|
||||
|
|
@ -185,7 +187,7 @@ static void _blurWeights(float sigma, float *weights) {
|
|||
// A shader from the generated blobs, in whichever format the device takes (as the scene does).
|
||||
static SDL_GPUShader *_createShader(SDL_GPUDevice *device, const GuiShaderT *shader, SDL_GPUShaderStage stage, uint32_t samplers, uint32_t uniforms) {
|
||||
SDL_GPUShaderCreateInfo info;
|
||||
SDL_GPUShaderFormat formats = SDL_GetGPUShaderFormats(device);
|
||||
SDL_GPUShaderFormat formats = rgpuGetShaderFormats(device);
|
||||
SDL_GPUShader *result = nullptr;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
|
@ -201,15 +203,19 @@ static SDL_GPUShader *_createShader(SDL_GPUDevice *device, const GuiShaderT *sha
|
|||
info.code = shader->msl;
|
||||
info.code_size = shader->mslSize;
|
||||
info.format = SDL_GPU_SHADERFORMAT_MSL;
|
||||
} else if (formats & RGPU_SHADERFORMAT_ESSL) {
|
||||
info.code = (const Uint8 *)shader->essl;
|
||||
info.code_size = shader->essl != nullptr ? SDL_strlen(shader->essl) : 0;
|
||||
info.format = RGPU_SHADERFORMAT_ESSL;
|
||||
} else {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "the GPU device accepts none of SPIR-V, DXIL or MSL");
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "the device accepts none of SPIR-V, DXIL, MSL or GLSL ES");
|
||||
return nullptr;
|
||||
}
|
||||
info.entrypoint = shader->entryPoint;
|
||||
info.stage = stage;
|
||||
info.num_samplers = samplers;
|
||||
info.num_uniform_buffers = uniforms;
|
||||
result = SDL_CreateGPUShader(device, &info);
|
||||
result = rgpuCreateShader(device, &info);
|
||||
if (result == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "shader %s: %s", shader->entryPoint, SDL_GetError());
|
||||
}
|
||||
|
|
@ -341,7 +347,7 @@ void GuiRenderT::ReleaseShaderCommandT::Run(GuiRenderT &render) {
|
|||
|
||||
|
||||
void GuiRenderT::ReleaseTextureCommandT::Run(GuiRenderT &render) {
|
||||
SDL_ReleaseGPUTexture(render.device, reinterpret_cast<SDL_GPUTexture *>(handle));
|
||||
rgpuReleaseTexture(render.device, reinterpret_cast<SDL_GPUTexture *>(handle));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -644,11 +650,11 @@ void GuiRenderT::EndFrame() {
|
|||
}
|
||||
commands.clear();
|
||||
if (copyPass != nullptr) {
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
rgpuEndCopyPass(copyPass);
|
||||
copyPass = nullptr;
|
||||
}
|
||||
if (renderPass != nullptr) {
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
rgpuEndRenderPass(renderPass);
|
||||
renderPass = nullptr;
|
||||
}
|
||||
// The stack is balanced by contract; anything left is returned to the pool.
|
||||
|
|
@ -674,19 +680,19 @@ Rml::TextureHandle GuiRenderT::GenerateTexture(Rml::Span<const Rml::byte> source
|
|||
|
||||
transferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
transferInfo.size = size;
|
||||
transfer = SDL_CreateGPUTransferBuffer(device, &transferInfo);
|
||||
transfer = rgpuCreateTransferBuffer(device, &transferInfo);
|
||||
if (transfer == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create transfer buffer: %s", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
destination = SDL_MapGPUTransferBuffer(device, transfer, false);
|
||||
destination = rgpuMapTransferBuffer(device, transfer, false);
|
||||
if (destination == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to map transfer buffer: %s", SDL_GetError());
|
||||
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
||||
rgpuReleaseTransferBuffer(device, transfer);
|
||||
return 0;
|
||||
}
|
||||
memcpy(destination, source.data(), size);
|
||||
SDL_UnmapGPUTransferBuffer(device, transfer);
|
||||
rgpuUnmapTransferBuffer(device, transfer);
|
||||
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
|
|
@ -694,10 +700,10 @@ Rml::TextureHandle GuiRenderT::GenerateTexture(Rml::Span<const Rml::byte> source
|
|||
textureInfo.height = (Uint32)sourceDimensions.y;
|
||||
textureInfo.layer_count_or_depth = 1;
|
||||
textureInfo.num_levels = 1;
|
||||
texture = SDL_CreateGPUTexture(device, &textureInfo);
|
||||
texture = rgpuCreateTexture(device, &textureInfo);
|
||||
if (texture == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create texture: %s", SDL_GetError());
|
||||
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
||||
rgpuReleaseTransferBuffer(device, transfer);
|
||||
return 0;
|
||||
}
|
||||
upload.transfer_buffer = transfer;
|
||||
|
|
@ -705,25 +711,25 @@ Rml::TextureHandle GuiRenderT::GenerateTexture(Rml::Span<const Rml::byte> source
|
|||
region.w = (Uint32)sourceDimensions.x;
|
||||
region.h = (Uint32)sourceDimensions.y;
|
||||
region.d = 1;
|
||||
uploadBuffer = SDL_AcquireGPUCommandBuffer(device);
|
||||
uploadBuffer = rgpuAcquireCommandBuffer(device);
|
||||
if (uploadBuffer == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to acquire command buffer: %s", SDL_GetError());
|
||||
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
||||
SDL_ReleaseGPUTexture(device, texture);
|
||||
rgpuReleaseTransferBuffer(device, transfer);
|
||||
rgpuReleaseTexture(device, texture);
|
||||
return 0;
|
||||
}
|
||||
pass = SDL_BeginGPUCopyPass(uploadBuffer);
|
||||
pass = rgpuBeginCopyPass(uploadBuffer);
|
||||
if (pass == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to begin copy pass: %s", SDL_GetError());
|
||||
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
||||
SDL_ReleaseGPUTexture(device, texture);
|
||||
SDL_CancelGPUCommandBuffer(uploadBuffer);
|
||||
rgpuReleaseTransferBuffer(device, transfer);
|
||||
rgpuReleaseTexture(device, texture);
|
||||
rgpuCancelCommandBuffer(uploadBuffer);
|
||||
return 0;
|
||||
}
|
||||
SDL_UploadToGPUTexture(pass, &upload, ®ion, false);
|
||||
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
||||
SDL_EndGPUCopyPass(pass);
|
||||
SDL_SubmitGPUCommandBuffer(uploadBuffer);
|
||||
rgpuUploadToTexture(pass, &upload, ®ion, false);
|
||||
rgpuReleaseTransferBuffer(device, transfer);
|
||||
rgpuEndCopyPass(pass);
|
||||
rgpuSubmitCommandBuffer(uploadBuffer);
|
||||
return reinterpret_cast<Rml::TextureHandle>(texture);
|
||||
}
|
||||
|
||||
|
|
@ -747,7 +753,7 @@ GuiRenderT::GuiRenderT(SDL_GPUDevice *gpuDevice, SDL_Window *gpuWindow) {
|
|||
linearSampler = nullptr;
|
||||
pointSampler = nullptr;
|
||||
linearClampSampler = nullptr;
|
||||
targetFormat = SDL_GetGPUSwapchainTextureFormat(device, window);
|
||||
targetFormat = rgpuGetSwapchainTextureFormat(device, window);
|
||||
stencilFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
screenQuad = nullptr;
|
||||
recordDepth = 0;
|
||||
|
|
@ -771,27 +777,30 @@ GuiRenderT::GuiRenderT(SDL_GPUDevice *gpuDevice, SDL_Window *gpuWindow) {
|
|||
memset(&stats, 0, sizeof(stats));
|
||||
memset(pipelines, 0, sizeof(pipelines));
|
||||
for (i = 0; i < SDL_arraysize(_stencilFormats); i++) {
|
||||
if (SDL_GPUTextureSupportsFormat(device, _stencilFormats[i], SDL_GPU_TEXTURETYPE_2D, SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
|
||||
if (rgpuTextureSupportsFormat(device, _stencilFormats[i], SDL_GPU_TEXTURETYPE_2D, SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
|
||||
stencilFormat = _stencilFormats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
createPipelines();
|
||||
// See scene.c: a zero max_lod clamps every lookup to mip level 0, because SDL passes it through
|
||||
// to Vulkan and D3D12 unchanged.
|
||||
info.max_lod = GUI_SAMPLER_MAX_LOD;
|
||||
info.min_filter = SDL_GPU_FILTER_LINEAR;
|
||||
info.mag_filter = SDL_GPU_FILTER_LINEAR;
|
||||
info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
|
||||
info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT;
|
||||
info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT;
|
||||
info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_REPEAT;
|
||||
linearSampler = SDL_CreateGPUSampler(device, &info);
|
||||
linearSampler = rgpuCreateSampler(device, &info);
|
||||
info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
linearClampSampler = SDL_CreateGPUSampler(device, &info);
|
||||
linearClampSampler = rgpuCreateSampler(device, &info);
|
||||
info.min_filter = SDL_GPU_FILTER_NEAREST;
|
||||
info.mag_filter = SDL_GPU_FILTER_NEAREST;
|
||||
info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
|
||||
pointSampler = SDL_CreateGPUSampler(device, &info);
|
||||
pointSampler = rgpuCreateSampler(device, &info);
|
||||
if ((linearSampler == nullptr) || (pointSampler == nullptr) || (linearClampSampler == nullptr)) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create sampler: %s", SDL_GetError());
|
||||
}
|
||||
|
|
@ -904,7 +913,7 @@ void GuiRenderT::ReleaseLayers(uint32_t width, uint32_t height) {
|
|||
TargetT *pooled = targets[i].get();
|
||||
|
||||
if (!pooled->inUse && (pooled->width == width) && (pooled->height == height)) {
|
||||
SDL_ReleaseGPUTexture(device, pooled->texture);
|
||||
rgpuReleaseTexture(device, pooled->texture);
|
||||
} else {
|
||||
targets[kept] = std::move(targets[i]);
|
||||
kept++;
|
||||
|
|
@ -983,7 +992,7 @@ Rml::TextureHandle GuiRenderT::SaveLayerAsTexture() {
|
|||
info.height = (Uint32)region.h;
|
||||
info.layer_count_or_depth = 1;
|
||||
info.num_levels = 1;
|
||||
texture = SDL_CreateGPUTexture(device, &info);
|
||||
texture = rgpuCreateTexture(device, &info);
|
||||
if (texture == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create layer texture: %s", SDL_GetError());
|
||||
return 0;
|
||||
|
|
@ -1019,22 +1028,22 @@ void GuiRenderT::Shutdown() {
|
|||
releaseGeometry(screenQuad);
|
||||
screenQuad = nullptr;
|
||||
for (Rml::UniquePtr<BufferT> &buffer : buffers) {
|
||||
SDL_ReleaseGPUTransferBuffer(device, buffer->transfer);
|
||||
SDL_ReleaseGPUBuffer(device, buffer->buffer);
|
||||
rgpuReleaseTransferBuffer(device, buffer->transfer);
|
||||
rgpuReleaseBuffer(device, buffer->buffer);
|
||||
}
|
||||
buffers.clear();
|
||||
for (Rml::UniquePtr<TargetT> &pooled : targets) {
|
||||
SDL_ReleaseGPUTexture(device, pooled->texture);
|
||||
rgpuReleaseTexture(device, pooled->texture);
|
||||
}
|
||||
targets.clear();
|
||||
SDL_ReleaseGPUSampler(device, linearSampler);
|
||||
SDL_ReleaseGPUSampler(device, pointSampler);
|
||||
SDL_ReleaseGPUSampler(device, linearClampSampler);
|
||||
rgpuReleaseSampler(device, linearSampler);
|
||||
rgpuReleaseSampler(device, pointSampler);
|
||||
rgpuReleaseSampler(device, linearClampSampler);
|
||||
linearSampler = nullptr;
|
||||
pointSampler = nullptr;
|
||||
linearClampSampler = nullptr;
|
||||
for (i = 0; i < GUI_PIPELINE_COUNT; i++) {
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, pipelines[i]);
|
||||
rgpuReleaseGraphicsPipeline(device, pipelines[i]);
|
||||
pipelines[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1066,7 +1075,7 @@ GuiRenderT::TargetT *GuiRenderT::acquireTarget() {
|
|||
info.layer_count_or_depth = 1;
|
||||
info.num_levels = 1;
|
||||
made = Rml::MakeUnique<TargetT>();
|
||||
made->texture = SDL_CreateGPUTexture(device, &info);
|
||||
made->texture = rgpuCreateTexture(device, &info);
|
||||
made->width = targetWidth;
|
||||
made->height = targetHeight;
|
||||
made->inUse = true;
|
||||
|
|
@ -1084,10 +1093,10 @@ bool GuiRenderT::beginCopyPass() {
|
|||
return true;
|
||||
}
|
||||
if (renderPass != nullptr) {
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
rgpuEndRenderPass(renderPass);
|
||||
renderPass = nullptr;
|
||||
}
|
||||
copyPass = SDL_BeginGPUCopyPass(commandBuffer);
|
||||
copyPass = rgpuBeginCopyPass(commandBuffer);
|
||||
if (copyPass == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to begin copy pass: %s", SDL_GetError());
|
||||
return false;
|
||||
|
|
@ -1107,7 +1116,7 @@ bool GuiRenderT::beginRenderPass() {
|
|||
return true;
|
||||
}
|
||||
if (copyPass != nullptr) {
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
rgpuEndCopyPass(copyPass);
|
||||
copyPass = nullptr;
|
||||
}
|
||||
colorInfo.texture = target;
|
||||
|
|
@ -1122,7 +1131,7 @@ bool GuiRenderT::beginRenderPass() {
|
|||
stencilInfo.stencil_store_op = SDL_GPU_STOREOP_STORE;
|
||||
stencilInfo.clear_stencil = MASK_OUTSIDE;
|
||||
}
|
||||
renderPass = SDL_BeginGPURenderPass(commandBuffer, &colorInfo, 1, (stencil != nullptr) ? &stencilInfo : nullptr);
|
||||
renderPass = rgpuBeginRenderPass(commandBuffer, &colorInfo, 1, (stencil != nullptr) ? &stencilInfo : nullptr);
|
||||
if (renderPass == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to begin render pass: %s", SDL_GetError());
|
||||
return false;
|
||||
|
|
@ -1144,11 +1153,11 @@ void GuiRenderT::blitTarget(SDL_GPUTexture *source, SDL_Rect from, SDL_GPUTextur
|
|||
return;
|
||||
}
|
||||
if (copyPass != nullptr) {
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
rgpuEndCopyPass(copyPass);
|
||||
copyPass = nullptr;
|
||||
}
|
||||
if (renderPass != nullptr) {
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
rgpuEndRenderPass(renderPass);
|
||||
renderPass = nullptr;
|
||||
}
|
||||
info.source.texture = source;
|
||||
|
|
@ -1163,7 +1172,7 @@ void GuiRenderT::blitTarget(SDL_GPUTexture *source, SDL_Rect from, SDL_GPUTextur
|
|||
info.destination.h = (Uint32)to.h;
|
||||
info.load_op = SDL_GPU_LOADOP_LOAD;
|
||||
info.filter = SDL_GPU_FILTER_LINEAR;
|
||||
SDL_BlitGPUTexture(commandBuffer, &info);
|
||||
rgpuBlitTexture(commandBuffer, &info);
|
||||
stats.filterPasses++;
|
||||
}
|
||||
|
||||
|
|
@ -1240,7 +1249,7 @@ void GuiRenderT::copyTarget(SDL_GPUTexture *source, SDL_Rect region, SDL_GPUText
|
|||
from.x = (Uint32)x;
|
||||
from.y = (Uint32)y;
|
||||
to.texture = destination;
|
||||
SDL_CopyGPUTextureToTexture(copyPass, &from, &to, (Uint32)w, (Uint32)h, 1, false);
|
||||
rgpuCopyTextureToTexture(copyPass, &from, &to, (Uint32)w, (Uint32)h, 1, false);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1269,9 +1278,9 @@ void GuiRenderT::createPipelines() {
|
|||
}
|
||||
if (!complete) {
|
||||
for (i = 0; i < GUI_FRAGMENT_COUNT; i++) {
|
||||
SDL_ReleaseGPUShader(device, fragments[i]);
|
||||
rgpuReleaseShader(device, fragments[i]);
|
||||
}
|
||||
SDL_ReleaseGPUShader(device, vertexShader);
|
||||
rgpuReleaseShader(device, vertexShader);
|
||||
return;
|
||||
}
|
||||
attributes[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
||||
|
|
@ -1320,15 +1329,15 @@ void GuiRenderT::createPipelines() {
|
|||
info.depth_stencil_state.front_stencil_state = stencilOp;
|
||||
info.depth_stencil_state.back_stencil_state = stencilOp;
|
||||
info.fragment_shader = fragments[desc->fragment];
|
||||
pipelines[i] = SDL_CreateGPUGraphicsPipeline(device, &info);
|
||||
pipelines[i] = rgpuCreateGraphicsPipeline(device, &info);
|
||||
if (pipelines[i] == nullptr) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create pipeline %d: %s", i, SDL_GetError());
|
||||
}
|
||||
}
|
||||
for (i = 0; i < GUI_FRAGMENT_COUNT; i++) {
|
||||
SDL_ReleaseGPUShader(device, fragments[i]);
|
||||
rgpuReleaseShader(device, fragments[i]);
|
||||
}
|
||||
SDL_ReleaseGPUShader(device, vertexShader);
|
||||
rgpuReleaseShader(device, vertexShader);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1344,28 +1353,28 @@ void GuiRenderT::drawGeometry(GeometryT *geometry, GuiPipelineE pipeline, SDL_GP
|
|||
if ((geometry == nullptr) || (pipelines[pipeline] == nullptr) || (textureCount > FILTER_SAMPLERS) || !beginRenderPass()) {
|
||||
return;
|
||||
}
|
||||
SDL_BindGPUGraphicsPipeline(renderPass, pipelines[pipeline]);
|
||||
rgpuBindGraphicsPipeline(renderPass, pipelines[pipeline]);
|
||||
if (textureCount > 0) {
|
||||
for (i = 0; i < textureCount; i++) {
|
||||
bindings[i].texture = textures[i];
|
||||
bindings[i].sampler = sampler;
|
||||
}
|
||||
SDL_BindGPUFragmentSamplers(renderPass, 0, bindings, textureCount);
|
||||
rgpuBindFragmentSamplers(renderPass, 0, bindings, textureCount);
|
||||
}
|
||||
vertices.buffer = geometry->vertices->buffer;
|
||||
indices.buffer = geometry->indices->buffer;
|
||||
SDL_BindGPUVertexBuffers(renderPass, 0, &vertices, 1);
|
||||
SDL_BindGPUIndexBuffer(renderPass, &indices, SDL_GPU_INDEXELEMENTSIZE_32BIT);
|
||||
SDL_SetGPUScissor(renderPass, &scissor);
|
||||
rgpuBindVertexBuffers(renderPass, 0, &vertices, 1);
|
||||
rgpuBindIndexBuffer(renderPass, &indices, SDL_GPU_INDEXELEMENTSIZE_32BIT);
|
||||
rgpuSetScissor(renderPass, &scissor);
|
||||
if (stencil != nullptr) {
|
||||
SDL_SetGPUStencilReference(renderPass, reference);
|
||||
rgpuSetStencilReference(renderPass, reference);
|
||||
}
|
||||
SDL_PushGPUVertexUniformData(commandBuffer, UNIFORM_TRANSFORM, &matrix, sizeof(matrix));
|
||||
SDL_PushGPUVertexUniformData(commandBuffer, UNIFORM_TRANSLATE, &translation, sizeof(translation));
|
||||
rgpuPushVertexUniformData(commandBuffer, UNIFORM_TRANSFORM, &matrix, sizeof(matrix));
|
||||
rgpuPushVertexUniformData(commandBuffer, UNIFORM_TRANSLATE, &translation, sizeof(translation));
|
||||
if (uniforms != nullptr) {
|
||||
SDL_PushGPUFragmentUniformData(commandBuffer, 0, uniforms, uniformSize);
|
||||
rgpuPushFragmentUniformData(commandBuffer, 0, uniforms, uniformSize);
|
||||
}
|
||||
SDL_DrawGPUIndexedPrimitives(renderPass, (Uint32)geometry->indexCount, 1, 0, 0, 0);
|
||||
rgpuDrawIndexedPrimitives(renderPass, (Uint32)geometry->indexCount, 1, 0, 0, 0);
|
||||
stats.drawCalls++;
|
||||
if (_pipelineDescs[pipeline].mask) {
|
||||
stats.maskWrites++;
|
||||
|
|
@ -1492,15 +1501,15 @@ GuiRenderT::BufferT *GuiRenderT::requestBuffer(int32_t capacity, SDL_GPUBufferUs
|
|||
transferInfo.size = (Uint32)capacity;
|
||||
bufferInfo.usage = usage;
|
||||
bufferInfo.size = (Uint32)capacity;
|
||||
made->transfer = SDL_CreateGPUTransferBuffer(device, &transferInfo);
|
||||
made->buffer = SDL_CreateGPUBuffer(device, &bufferInfo);
|
||||
made->transfer = rgpuCreateTransferBuffer(device, &transferInfo);
|
||||
made->buffer = rgpuCreateBuffer(device, &bufferInfo);
|
||||
made->usage = usage;
|
||||
made->capacity = capacity;
|
||||
made->inUse = false;
|
||||
if ((made->transfer == nullptr) || (made->buffer == nullptr)) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to create buffer(s): %s", SDL_GetError());
|
||||
SDL_ReleaseGPUTransferBuffer(device, made->transfer);
|
||||
SDL_ReleaseGPUBuffer(device, made->buffer);
|
||||
rgpuReleaseTransferBuffer(device, made->transfer);
|
||||
rgpuReleaseBuffer(device, made->buffer);
|
||||
return nullptr;
|
||||
}
|
||||
return buffers.insert(first, std::move(made))->get();
|
||||
|
|
@ -1511,7 +1520,7 @@ GuiRenderT::BufferT *GuiRenderT::requestBuffer(int32_t capacity, SDL_GPUBufferUs
|
|||
// draw begins one on the new target.
|
||||
void GuiRenderT::setTarget(SDL_GPUTexture *texture, bool clear) {
|
||||
if ((renderPass != nullptr) && ((texture != target) || clear)) {
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
rgpuEndRenderPass(renderPass);
|
||||
renderPass = nullptr;
|
||||
}
|
||||
target = texture;
|
||||
|
|
@ -1538,31 +1547,31 @@ GuiRenderT::GeometryT *GuiRenderT::uploadGeometry(const void *vertexData, uint32
|
|||
delete geometry;
|
||||
return nullptr;
|
||||
}
|
||||
vertexStage = SDL_MapGPUTransferBuffer(device, geometry->vertices->transfer, true);
|
||||
indexStage = SDL_MapGPUTransferBuffer(device, geometry->indices->transfer, true);
|
||||
vertexStage = rgpuMapTransferBuffer(device, geometry->vertices->transfer, true);
|
||||
indexStage = rgpuMapTransferBuffer(device, geometry->indices->transfer, true);
|
||||
if ((vertexStage == nullptr) || (indexStage == nullptr)) {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "failed to map transfer buffer(s): %s", SDL_GetError());
|
||||
if (vertexStage != nullptr) {
|
||||
SDL_UnmapGPUTransferBuffer(device, geometry->vertices->transfer);
|
||||
rgpuUnmapTransferBuffer(device, geometry->vertices->transfer);
|
||||
}
|
||||
if (indexStage != nullptr) {
|
||||
SDL_UnmapGPUTransferBuffer(device, geometry->indices->transfer);
|
||||
rgpuUnmapTransferBuffer(device, geometry->indices->transfer);
|
||||
}
|
||||
delete geometry;
|
||||
return nullptr;
|
||||
}
|
||||
memcpy(vertexStage, vertexData, vertexSize);
|
||||
memcpy(indexStage, indexData, indexSize);
|
||||
SDL_UnmapGPUTransferBuffer(device, geometry->vertices->transfer);
|
||||
SDL_UnmapGPUTransferBuffer(device, geometry->indices->transfer);
|
||||
rgpuUnmapTransferBuffer(device, geometry->vertices->transfer);
|
||||
rgpuUnmapTransferBuffer(device, geometry->indices->transfer);
|
||||
location.transfer_buffer = geometry->vertices->transfer;
|
||||
region.buffer = geometry->vertices->buffer;
|
||||
region.size = vertexSize;
|
||||
SDL_UploadToGPUBuffer(copyPass, &location, ®ion, false);
|
||||
rgpuUploadToBuffer(copyPass, &location, ®ion, false);
|
||||
location.transfer_buffer = geometry->indices->transfer;
|
||||
region.buffer = geometry->indices->buffer;
|
||||
region.size = indexSize;
|
||||
SDL_UploadToGPUBuffer(copyPass, &location, ®ion, false);
|
||||
rgpuUploadToBuffer(copyPass, &location, ®ion, false);
|
||||
geometry->indexCount = (int32_t)(indexSize / sizeof(int32_t));
|
||||
geometry->vertices->inUse = true;
|
||||
geometry->indices->inUse = true;
|
||||
|
|
|
|||
25
src/main.c
25
src/main.c
|
|
@ -64,6 +64,7 @@
|
|||
#include "singe.h"
|
||||
#include "pack.h"
|
||||
#include "vfs.h"
|
||||
#include "render.h"
|
||||
#include "../thirdparty/ffmpeg/libavformat/avformat.h"
|
||||
#include "embedded.h"
|
||||
|
||||
|
|
@ -1249,11 +1250,11 @@ static void _launcher(const char *exeName, ConfigT *conf) {
|
|||
_mainTrace(conf, "Creating renderer");
|
||||
device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, false, NULL);
|
||||
if (device == NULL) {
|
||||
_mainTrace(conf, "No GPU device (%s); 3D is unavailable", SDL_GetError());
|
||||
_mainTrace(conf, "No SDL_GPU device (%s); trying OpenGL ES", SDL_GetError());
|
||||
} else {
|
||||
renderer = SDL_CreateGPURenderer(device, window);
|
||||
if (renderer == NULL) {
|
||||
_mainTrace(conf, "GPU renderer failed (%s); 3D is unavailable", SDL_GetError());
|
||||
_mainTrace(conf, "GPU renderer failed (%s); trying OpenGL ES", SDL_GetError());
|
||||
SDL_DestroyGPUDevice(device);
|
||||
device = NULL;
|
||||
}
|
||||
|
|
@ -1265,6 +1266,22 @@ static void _launcher(const char *exeName, ConfigT *conf) {
|
|||
}
|
||||
}
|
||||
_mainTrace(conf, "Renderer: %s", SDL_GetRendererName(renderer));
|
||||
// Tell the render layer which backend the scene and the GUI will be calling through. SDL_GPU
|
||||
// when the platform has it; otherwise OpenGL ES through the context SDL_Renderer just made,
|
||||
// which is the only one a Pi or a Mali handheld offers. Neither leaves 2D untouched and the
|
||||
// scene and the GUI reporting themselves unavailable, as they already did on such a machine.
|
||||
if (device != NULL) {
|
||||
renderSelect(RENDER_GPU, &renderGpuBackend, renderer);
|
||||
} else if (renderGlesStart()) {
|
||||
renderSelect(RENDER_GLES, &renderGlesBackend, renderer);
|
||||
device = rgpuCreateDevice(RGPU_SHADERFORMAT_ESSL, false, NULL);
|
||||
if (device == NULL) {
|
||||
renderSelect(RENDER_NONE, NULL, renderer);
|
||||
}
|
||||
} else {
|
||||
renderSelect(RENDER_NONE, NULL, renderer);
|
||||
}
|
||||
_mainTrace(conf, "Render backend: %s", renderApiName());
|
||||
|
||||
// Clear screen with black
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
|
|
@ -1308,7 +1325,7 @@ static void _launcher(const char *exeName, ConfigT *conf) {
|
|||
_mainTrace(conf, "Destroying renderer");
|
||||
SDL_DestroyRenderer(renderer);
|
||||
if (device != NULL) {
|
||||
SDL_DestroyGPUDevice(device);
|
||||
rgpuDestroyDevice(device);
|
||||
}
|
||||
_mainTrace(conf, "Destroying window");
|
||||
SDL_DestroyWindow(window);
|
||||
|
|
@ -1761,7 +1778,7 @@ static void _traceHeader(const ConfigT *conf, SDL_Renderer *renderer, SDL_GPUDev
|
|||
utilTrace("Command: %s", (_commandLine != NULL) ? _commandLine : "");
|
||||
utilTrace("OS: %s", os);
|
||||
utilTrace("CPU: %s", cpu);
|
||||
utilTrace("Renderer: %s%s%s", SDL_GetRendererName(renderer), (device != NULL) ? ", GPU driver " : " (no GPU device; 3D is unavailable)", (device != NULL) ? SDL_GetGPUDeviceDriver(device) : "");
|
||||
utilTrace("Renderer: %s%s%s", SDL_GetRendererName(renderer), (device != NULL) ? ", 3D through " : " (no 3D and no GUI on this machine)", (device != NULL) ? rgpuGetDeviceDriver(device) : "");
|
||||
utilTrace("Decoder: %s", videoGetDecoderDescription());
|
||||
utilTrace("Audio: %s", audio);
|
||||
utilTrace("SoundFont: %s", midiSoundfont());
|
||||
|
|
|
|||
356
src/render.c
Normal file
356
src/render.c
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
*
|
||||
* Singe 3
|
||||
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// Backend selection and dispatch.
|
||||
//
|
||||
// One indirect call per entry point. That is nothing beside the work each one goes on to do, and it
|
||||
// buys runtime selection: the same binary runs on a machine with Vulkan and on one with GLES only.
|
||||
|
||||
#include "render.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static const RenderBackendT *_backend = NULL;
|
||||
static SDL_Renderer *_renderer = NULL;
|
||||
static RenderApiT _api = RENDER_NONE;
|
||||
|
||||
|
||||
RenderApiT renderApi(void) {
|
||||
return _api;
|
||||
}
|
||||
|
||||
|
||||
const char *renderApiName(void) {
|
||||
switch (_api) {
|
||||
case RENDER_GPU: return "SDL_GPU";
|
||||
case RENDER_GLES: return "OpenGL ES";
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GLES shares one context with SDL_Renderer, which caches its own drawing state. SDL_FlushRenderer
|
||||
// both flushes the queue and invalidates that cache (SDL_render.c), which is what makes handing the
|
||||
// context over safe rather than merely lucky -- see PLAN.md section 56, phase 0. Under SDL_GPU
|
||||
// there is no shared state and this costs a comparison.
|
||||
void renderBegin(void) {
|
||||
if ((_api == RENDER_GLES) && (_renderer != NULL)) {
|
||||
SDL_FlushRenderer(_renderer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Nothing to undo under SDL_GPU; it owns no state SDL_Renderer can see. GLES shares one context,
|
||||
// so it puts back the bindings SDL does not track for itself.
|
||||
void renderEnd(void) {
|
||||
if (_api == RENDER_GLES) {
|
||||
renderGlesRestore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUTexture *renderTextureFor(SDL_Texture *texture) {
|
||||
if (texture == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (_api == RENDER_GLES) {
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
|
||||
SDL_GetTextureSize(texture, &width, &height);
|
||||
return renderGlesTextureWrap((Uint32)SDL_GetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0), (int32_t)width, (int32_t)height);
|
||||
}
|
||||
return (SDL_GPUTexture *)SDL_GetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_GPU_TEXTURE_POINTER, NULL);
|
||||
}
|
||||
|
||||
|
||||
SDL_Texture *renderWrapTexture(SDL_Renderer *renderer, SDL_GPUTexture *texture, SDL_PixelFormat format, int32_t width, int32_t height) {
|
||||
SDL_PropertiesID props;
|
||||
SDL_Texture *result;
|
||||
|
||||
if ((renderer == NULL) || (texture == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
props = SDL_CreateProperties();
|
||||
if (_api == RENDER_GLES) {
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER, (Sint64)renderGlesTextureName(texture));
|
||||
// Core GLES has no BGRA storage, so a caller asking for BGRA32 -- which the scene does, as
|
||||
// its way of naming the swapchain's layout -- really has an RGBA8 texture. Saying otherwise
|
||||
// leaves SDL drawing nothing at all, which is how this was found.
|
||||
if ((format == SDL_PIXELFORMAT_BGRA32) || (format == SDL_PIXELFORMAT_BGRX32)) {
|
||||
format = SDL_PIXELFORMAT_RGBA32;
|
||||
}
|
||||
} else {
|
||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER, texture);
|
||||
}
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, height);
|
||||
result = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void renderSelect(RenderApiT api, const RenderBackendT *backend, SDL_Renderer *renderer) {
|
||||
_api = backend != NULL ? api : RENDER_NONE;
|
||||
_backend = backend;
|
||||
_renderer = renderer;
|
||||
utilTrace("Render: %s", renderApiName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Every run of rgpu* drawing sits between acquiring a command buffer and submitting it, so that is
|
||||
// where the context is taken and given back. Bracketing here rather than at the callers means
|
||||
// scene.c and guiRender.cpp need to know nothing about it.
|
||||
SDL_GPUCommandBuffer *rgpuAcquireCommandBuffer(SDL_GPUDevice *device) {
|
||||
renderBegin();
|
||||
return _backend->acquireCommandBuffer(device);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUCopyPass *rgpuBeginCopyPass(SDL_GPUCommandBuffer *commandBuffer) {
|
||||
return _backend->beginCopyPass(commandBuffer);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPURenderPass *rgpuBeginRenderPass(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUColorTargetInfo *colorTargetInfos, Uint32 numColorTargets, const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo) {
|
||||
return _backend->beginRenderPass(commandBuffer, colorTargetInfos, numColorTargets, depthStencilTargetInfo);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBindFragmentSamplers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUTextureSamplerBinding *textureSamplerBindings, Uint32 numBindings) {
|
||||
_backend->bindFragmentSamplers(renderPass, firstSlot, textureSamplerBindings, numBindings);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBindGraphicsPipeline(SDL_GPURenderPass *renderPass, SDL_GPUGraphicsPipeline *graphicsPipeline) {
|
||||
_backend->bindGraphicsPipeline(renderPass, graphicsPipeline);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBindIndexBuffer(SDL_GPURenderPass *renderPass, const SDL_GPUBufferBinding *binding, SDL_GPUIndexElementSize indexElementSize) {
|
||||
_backend->bindIndexBuffer(renderPass, binding, indexElementSize);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBindVertexBuffers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUBufferBinding *bindings, Uint32 numBindings) {
|
||||
_backend->bindVertexBuffers(renderPass, firstSlot, bindings, numBindings);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBindVertexStorageBuffers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, SDL_GPUBuffer *const *storageBuffers, Uint32 numBindings) {
|
||||
_backend->bindVertexStorageBuffers(renderPass, firstSlot, storageBuffers, numBindings);
|
||||
}
|
||||
|
||||
|
||||
void rgpuBlitTexture(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUBlitInfo *info) {
|
||||
_backend->blitTexture(commandBuffer, info);
|
||||
}
|
||||
|
||||
|
||||
bool rgpuCancelCommandBuffer(SDL_GPUCommandBuffer *commandBuffer) {
|
||||
bool ok = _backend->cancelCommandBuffer(commandBuffer);
|
||||
|
||||
renderEnd();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void rgpuCopyTextureToTexture(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureLocation *source, const SDL_GPUTextureLocation *destination, Uint32 w, Uint32 h, Uint32 d, bool cycle) {
|
||||
_backend->copyTextureToTexture(copyPass, source, destination, w, h, d, cycle);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUBuffer *rgpuCreateBuffer(SDL_GPUDevice *device, const SDL_GPUBufferCreateInfo *createinfo) {
|
||||
return _backend->createBuffer(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUDevice *rgpuCreateDevice(SDL_GPUShaderFormat formatFlags, bool debugMode, const char *name) {
|
||||
return _backend->createDevice(formatFlags, debugMode, name);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUGraphicsPipeline *rgpuCreateGraphicsPipeline(SDL_GPUDevice *device, const SDL_GPUGraphicsPipelineCreateInfo *createinfo) {
|
||||
return _backend->createGraphicsPipeline(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUSampler *rgpuCreateSampler(SDL_GPUDevice *device, const SDL_GPUSamplerCreateInfo *createinfo) {
|
||||
return _backend->createSampler(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUShader *rgpuCreateShader(SDL_GPUDevice *device, const SDL_GPUShaderCreateInfo *createinfo) {
|
||||
return _backend->createShader(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUTexture *rgpuCreateTexture(SDL_GPUDevice *device, const SDL_GPUTextureCreateInfo *createinfo) {
|
||||
return _backend->createTexture(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUTransferBuffer *rgpuCreateTransferBuffer(SDL_GPUDevice *device, const SDL_GPUTransferBufferCreateInfo *createinfo) {
|
||||
return _backend->createTransferBuffer(device, createinfo);
|
||||
}
|
||||
|
||||
|
||||
void rgpuDestroyDevice(SDL_GPUDevice *device) {
|
||||
_backend->destroyDevice(device);
|
||||
}
|
||||
|
||||
|
||||
void rgpuDrawIndexedPrimitives(SDL_GPURenderPass *renderPass, Uint32 numIndices, Uint32 numInstances, Uint32 firstIndex, Sint32 vertexOffset, Uint32 firstInstance) {
|
||||
_backend->drawIndexedPrimitives(renderPass, numIndices, numInstances, firstIndex, vertexOffset, firstInstance);
|
||||
}
|
||||
|
||||
|
||||
void rgpuDrawPrimitives(SDL_GPURenderPass *renderPass, Uint32 numVertices, Uint32 numInstances, Uint32 firstVertex, Uint32 firstInstance) {
|
||||
_backend->drawPrimitives(renderPass, numVertices, numInstances, firstVertex, firstInstance);
|
||||
}
|
||||
|
||||
|
||||
void rgpuEndCopyPass(SDL_GPUCopyPass *copyPass) {
|
||||
_backend->endCopyPass(copyPass);
|
||||
}
|
||||
|
||||
|
||||
void rgpuEndRenderPass(SDL_GPURenderPass *renderPass) {
|
||||
_backend->endRenderPass(renderPass);
|
||||
}
|
||||
|
||||
|
||||
void rgpuGenerateMipmapsForTexture(SDL_GPUCommandBuffer *commandBuffer, SDL_GPUTexture *texture) {
|
||||
_backend->generateMipmapsForTexture(commandBuffer, texture);
|
||||
}
|
||||
|
||||
|
||||
const char *rgpuGetDeviceDriver(SDL_GPUDevice *device) {
|
||||
return _backend->getDeviceDriver(device);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUShaderFormat rgpuGetShaderFormats(SDL_GPUDevice *device) {
|
||||
return _backend->getShaderFormats(device);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUTextureFormat rgpuGetSwapchainTextureFormat(SDL_GPUDevice *device, SDL_Window *window) {
|
||||
return _backend->getSwapchainTextureFormat(device, window);
|
||||
}
|
||||
|
||||
|
||||
SDL_GPUTextureFormat rgpuGetTextureFormatFromPixelFormat(SDL_PixelFormat format) {
|
||||
return _backend->getTextureFormatFromPixelFormat(format);
|
||||
}
|
||||
|
||||
|
||||
void *rgpuMapTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer, bool cycle) {
|
||||
return _backend->mapTransferBuffer(device, transferBuffer, cycle);
|
||||
}
|
||||
|
||||
|
||||
void rgpuPushFragmentUniformData(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length) {
|
||||
_backend->pushFragmentUniformData(commandBuffer, slotIndex, data, length);
|
||||
}
|
||||
|
||||
|
||||
void rgpuPushVertexUniformData(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length) {
|
||||
_backend->pushVertexUniformData(commandBuffer, slotIndex, data, length);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseBuffer(SDL_GPUDevice *device, SDL_GPUBuffer *buffer) {
|
||||
_backend->releaseBuffer(device, buffer);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseGraphicsPipeline(SDL_GPUDevice *device, SDL_GPUGraphicsPipeline *graphicsPipeline) {
|
||||
_backend->releaseGraphicsPipeline(device, graphicsPipeline);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseSampler(SDL_GPUDevice *device, SDL_GPUSampler *sampler) {
|
||||
_backend->releaseSampler(device, sampler);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseShader(SDL_GPUDevice *device, SDL_GPUShader *shader) {
|
||||
_backend->releaseShader(device, shader);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseTexture(SDL_GPUDevice *device, SDL_GPUTexture *texture) {
|
||||
_backend->releaseTexture(device, texture);
|
||||
}
|
||||
|
||||
|
||||
void rgpuReleaseTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer) {
|
||||
_backend->releaseTransferBuffer(device, transferBuffer);
|
||||
}
|
||||
|
||||
|
||||
void rgpuSetScissor(SDL_GPURenderPass *renderPass, const SDL_Rect *scissor) {
|
||||
_backend->setScissor(renderPass, scissor);
|
||||
}
|
||||
|
||||
|
||||
void rgpuSetStencilReference(SDL_GPURenderPass *renderPass, Uint8 reference) {
|
||||
_backend->setStencilReference(renderPass, reference);
|
||||
}
|
||||
|
||||
|
||||
bool rgpuSubmitCommandBuffer(SDL_GPUCommandBuffer *commandBuffer) {
|
||||
bool ok = _backend->submitCommandBuffer(commandBuffer);
|
||||
|
||||
renderEnd();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
bool rgpuTextureSupportsFormat(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUTextureType type, SDL_GPUTextureUsageFlags usage) {
|
||||
return _backend->textureSupportsFormat(device, format, type, usage);
|
||||
}
|
||||
|
||||
|
||||
bool rgpuTextureSupportsSampleCount(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUSampleCount sampleCount) {
|
||||
return _backend->textureSupportsSampleCount(device, format, sampleCount);
|
||||
}
|
||||
|
||||
|
||||
void rgpuUnmapTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer) {
|
||||
_backend->unmapTransferBuffer(device, transferBuffer);
|
||||
}
|
||||
|
||||
|
||||
void rgpuUploadToBuffer(SDL_GPUCopyPass *copyPass, const SDL_GPUTransferBufferLocation *source, const SDL_GPUBufferRegion *destination, bool cycle) {
|
||||
_backend->uploadToBuffer(copyPass, source, destination, cycle);
|
||||
}
|
||||
|
||||
|
||||
void rgpuUploadToTexture(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureTransferInfo *source, const SDL_GPUTextureRegion *destination, bool cycle) {
|
||||
_backend->uploadToTexture(copyPass, source, destination, cycle);
|
||||
}
|
||||
193
src/render.h
Normal file
193
src/render.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
*
|
||||
* Singe 3
|
||||
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RENDER_H
|
||||
#define RENDER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// The rendering backend, behind one table of function pointers.
|
||||
//
|
||||
// SDL_GPU has Vulkan, Direct3D 12 and Metal and no OpenGL of any kind, which leaves the cheap
|
||||
// handhelds and the Pi with 2D only: they have GLES and nothing else. Rather than grow a second
|
||||
// renderer beside scene.c and guiRender.cpp -- two descriptions of the same picture, drifting apart
|
||||
// -- the subset of SDL_GPU those files actually use is virtualised here and implemented twice. It
|
||||
// is 45 entry points, and nothing exotic is in it: no compute, no indirect draws, no manual
|
||||
// barriers. See PLAN.md section 56.
|
||||
//
|
||||
// The types are NOT reinvented. SDL3 declares SDL_GPUTextureCreateInfo and the rest whether or not
|
||||
// a backend exists on this platform, so both backends share SDL's structures and enumerations and
|
||||
// only the functions are dispatched. That holds this layer to names alone.
|
||||
//
|
||||
// Selection is at run time, not build time: one linux-aarch64 binary ships to an RK3588 that may
|
||||
// have Vulkan and to a Mali-G31 that certainly does not.
|
||||
|
||||
// GLSL ES source, as a shader "format". SDL_GPUShaderFormat is a bit field and SDL uses bits 0 to 5
|
||||
// (PRIVATE, SPIRV, DXBC, DXIL, MSL, METALLIB), so this takes one well clear of them. A shader's
|
||||
// code pointer is then the ES source string rather than a blob, and its size is ignored.
|
||||
#define RGPU_SHADERFORMAT_ESSL (1u << 16)
|
||||
|
||||
|
||||
typedef struct RenderBackendS {
|
||||
SDL_GPUCommandBuffer * (*acquireCommandBuffer)(SDL_GPUDevice *device);
|
||||
SDL_GPUCopyPass * (*beginCopyPass)(SDL_GPUCommandBuffer *commandBuffer);
|
||||
SDL_GPURenderPass * (*beginRenderPass)(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUColorTargetInfo *colorTargetInfos, Uint32 numColorTargets, const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo);
|
||||
void (*bindFragmentSamplers)(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUTextureSamplerBinding *textureSamplerBindings, Uint32 numBindings);
|
||||
void (*bindGraphicsPipeline)(SDL_GPURenderPass *renderPass, SDL_GPUGraphicsPipeline *graphicsPipeline);
|
||||
void (*bindIndexBuffer)(SDL_GPURenderPass *renderPass, const SDL_GPUBufferBinding *binding, SDL_GPUIndexElementSize indexElementSize);
|
||||
void (*bindVertexBuffers)(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUBufferBinding *bindings, Uint32 numBindings);
|
||||
void (*bindVertexStorageBuffers)(SDL_GPURenderPass *renderPass, Uint32 firstSlot, SDL_GPUBuffer *const *storageBuffers, Uint32 numBindings);
|
||||
void (*blitTexture)(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUBlitInfo *info);
|
||||
bool (*cancelCommandBuffer)(SDL_GPUCommandBuffer *commandBuffer);
|
||||
void (*copyTextureToTexture)(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureLocation *source, const SDL_GPUTextureLocation *destination, Uint32 w, Uint32 h, Uint32 d, bool cycle);
|
||||
SDL_GPUBuffer * (*createBuffer)(SDL_GPUDevice *device, const SDL_GPUBufferCreateInfo *createinfo);
|
||||
SDL_GPUDevice * (*createDevice)(SDL_GPUShaderFormat formatFlags, bool debugMode, const char *name);
|
||||
SDL_GPUGraphicsPipeline *(*createGraphicsPipeline)(SDL_GPUDevice *device, const SDL_GPUGraphicsPipelineCreateInfo *createinfo);
|
||||
SDL_GPUSampler * (*createSampler)(SDL_GPUDevice *device, const SDL_GPUSamplerCreateInfo *createinfo);
|
||||
SDL_GPUShader * (*createShader)(SDL_GPUDevice *device, const SDL_GPUShaderCreateInfo *createinfo);
|
||||
SDL_GPUTexture * (*createTexture)(SDL_GPUDevice *device, const SDL_GPUTextureCreateInfo *createinfo);
|
||||
SDL_GPUTransferBuffer * (*createTransferBuffer)(SDL_GPUDevice *device, const SDL_GPUTransferBufferCreateInfo *createinfo);
|
||||
void (*destroyDevice)(SDL_GPUDevice *device);
|
||||
void (*drawIndexedPrimitives)(SDL_GPURenderPass *renderPass, Uint32 numIndices, Uint32 numInstances, Uint32 firstIndex, Sint32 vertexOffset, Uint32 firstInstance);
|
||||
void (*drawPrimitives)(SDL_GPURenderPass *renderPass, Uint32 numVertices, Uint32 numInstances, Uint32 firstVertex, Uint32 firstInstance);
|
||||
void (*endCopyPass)(SDL_GPUCopyPass *copyPass);
|
||||
void (*endRenderPass)(SDL_GPURenderPass *renderPass);
|
||||
void (*generateMipmapsForTexture)(SDL_GPUCommandBuffer *commandBuffer, SDL_GPUTexture *texture);
|
||||
const char * (*getDeviceDriver)(SDL_GPUDevice *device);
|
||||
SDL_GPUShaderFormat (*getShaderFormats)(SDL_GPUDevice *device);
|
||||
SDL_GPUTextureFormat (*getSwapchainTextureFormat)(SDL_GPUDevice *device, SDL_Window *window);
|
||||
SDL_GPUTextureFormat (*getTextureFormatFromPixelFormat)(SDL_PixelFormat format);
|
||||
void * (*mapTransferBuffer)(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer, bool cycle);
|
||||
void (*pushFragmentUniformData)(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length);
|
||||
void (*pushVertexUniformData)(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length);
|
||||
void (*releaseBuffer)(SDL_GPUDevice *device, SDL_GPUBuffer *buffer);
|
||||
void (*releaseGraphicsPipeline)(SDL_GPUDevice *device, SDL_GPUGraphicsPipeline *graphicsPipeline);
|
||||
void (*releaseSampler)(SDL_GPUDevice *device, SDL_GPUSampler *sampler);
|
||||
void (*releaseShader)(SDL_GPUDevice *device, SDL_GPUShader *shader);
|
||||
void (*releaseTexture)(SDL_GPUDevice *device, SDL_GPUTexture *texture);
|
||||
void (*releaseTransferBuffer)(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer);
|
||||
void (*setScissor)(SDL_GPURenderPass *renderPass, const SDL_Rect *scissor);
|
||||
void (*setStencilReference)(SDL_GPURenderPass *renderPass, Uint8 reference);
|
||||
bool (*submitCommandBuffer)(SDL_GPUCommandBuffer *commandBuffer);
|
||||
bool (*textureSupportsFormat)(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUTextureType type, SDL_GPUTextureUsageFlags usage);
|
||||
bool (*textureSupportsSampleCount)(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUSampleCount sampleCount);
|
||||
void (*unmapTransferBuffer)(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer);
|
||||
void (*uploadToBuffer)(SDL_GPUCopyPass *copyPass, const SDL_GPUTransferBufferLocation *source, const SDL_GPUBufferRegion *destination, bool cycle);
|
||||
void (*uploadToTexture)(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureTransferInfo *source, const SDL_GPUTextureRegion *destination, bool cycle);
|
||||
} RenderBackendT;
|
||||
|
||||
|
||||
// Which backend is in use. RENDER_NONE means 3D and the GUI are unavailable and the engine draws
|
||||
// 2D through SDL_Renderer alone, which is what a machine with no usable driver gets.
|
||||
typedef enum RenderApiE {
|
||||
RENDER_NONE = 0,
|
||||
RENDER_GPU, // SDL_GPU: Vulkan, Direct3D 12 or Metal
|
||||
RENDER_GLES // OpenGL ES 3.1, or 2.0 with the GUI only
|
||||
} RenderApiT;
|
||||
|
||||
|
||||
extern const RenderBackendT renderGlesBackend;
|
||||
extern const RenderBackendT renderGpuBackend;
|
||||
|
||||
|
||||
// The engine side. renderBegin and renderEnd bracket every frame's rgpu* calls: under SDL_GPU
|
||||
// they do nothing, and under GLES they hand SDL_Renderer's context over and give it back.
|
||||
RenderApiT renderApi(void);
|
||||
const char *renderApiName(void);
|
||||
void renderBegin(void);
|
||||
void renderEnd(void);
|
||||
void renderSelect(RenderApiT api, const RenderBackendT *backend, SDL_Renderer *renderer);
|
||||
|
||||
// The composite seam. The scene and the GUI do not draw to the swapchain; each renders into its
|
||||
// own texture and hands it to SDL_Renderer to draw as an ordinary layer. Under SDL_GPU that is
|
||||
// SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER and under GLES it is the twin taking a GLuint,
|
||||
// SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER, so the choice lives here rather than at each of
|
||||
// the three call sites. renderTextureFor goes the other way, for a texture SDL made.
|
||||
SDL_Texture *renderWrapTexture(SDL_Renderer *renderer, SDL_GPUTexture *texture, SDL_PixelFormat format, int32_t width, int32_t height);
|
||||
SDL_GPUTexture *renderTextureFor(SDL_Texture *texture);
|
||||
|
||||
// The GLES backend's own two. renderGlesStart looks at the context SDL_Renderer already made and
|
||||
// says whether it is one this backend can use; renderGlesRestore puts that context back as found.
|
||||
void renderGlesRestore(void);
|
||||
bool renderGlesStart(void);
|
||||
Uint32 renderGlesTextureName(SDL_GPUTexture *texture);
|
||||
SDL_GPUTexture *renderGlesTextureWrap(Uint32 name, int32_t width, int32_t height);
|
||||
|
||||
SDL_GPUCommandBuffer * rgpuAcquireCommandBuffer(SDL_GPUDevice *device);
|
||||
SDL_GPUCopyPass * rgpuBeginCopyPass(SDL_GPUCommandBuffer *commandBuffer);
|
||||
SDL_GPURenderPass * rgpuBeginRenderPass(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUColorTargetInfo *colorTargetInfos, Uint32 numColorTargets, const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo);
|
||||
void rgpuBindFragmentSamplers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUTextureSamplerBinding *textureSamplerBindings, Uint32 numBindings);
|
||||
void rgpuBindGraphicsPipeline(SDL_GPURenderPass *renderPass, SDL_GPUGraphicsPipeline *graphicsPipeline);
|
||||
void rgpuBindIndexBuffer(SDL_GPURenderPass *renderPass, const SDL_GPUBufferBinding *binding, SDL_GPUIndexElementSize indexElementSize);
|
||||
void rgpuBindVertexBuffers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, const SDL_GPUBufferBinding *bindings, Uint32 numBindings);
|
||||
void rgpuBindVertexStorageBuffers(SDL_GPURenderPass *renderPass, Uint32 firstSlot, SDL_GPUBuffer *const *storageBuffers, Uint32 numBindings);
|
||||
void rgpuBlitTexture(SDL_GPUCommandBuffer *commandBuffer, const SDL_GPUBlitInfo *info);
|
||||
bool rgpuCancelCommandBuffer(SDL_GPUCommandBuffer *commandBuffer);
|
||||
void rgpuCopyTextureToTexture(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureLocation *source, const SDL_GPUTextureLocation *destination, Uint32 w, Uint32 h, Uint32 d, bool cycle);
|
||||
SDL_GPUBuffer * rgpuCreateBuffer(SDL_GPUDevice *device, const SDL_GPUBufferCreateInfo *createinfo);
|
||||
SDL_GPUDevice * rgpuCreateDevice(SDL_GPUShaderFormat formatFlags, bool debugMode, const char *name);
|
||||
SDL_GPUGraphicsPipeline *rgpuCreateGraphicsPipeline(SDL_GPUDevice *device, const SDL_GPUGraphicsPipelineCreateInfo *createinfo);
|
||||
SDL_GPUSampler * rgpuCreateSampler(SDL_GPUDevice *device, const SDL_GPUSamplerCreateInfo *createinfo);
|
||||
SDL_GPUShader * rgpuCreateShader(SDL_GPUDevice *device, const SDL_GPUShaderCreateInfo *createinfo);
|
||||
SDL_GPUTexture * rgpuCreateTexture(SDL_GPUDevice *device, const SDL_GPUTextureCreateInfo *createinfo);
|
||||
SDL_GPUTransferBuffer * rgpuCreateTransferBuffer(SDL_GPUDevice *device, const SDL_GPUTransferBufferCreateInfo *createinfo);
|
||||
void rgpuDestroyDevice(SDL_GPUDevice *device);
|
||||
void rgpuDrawIndexedPrimitives(SDL_GPURenderPass *renderPass, Uint32 numIndices, Uint32 numInstances, Uint32 firstIndex, Sint32 vertexOffset, Uint32 firstInstance);
|
||||
void rgpuDrawPrimitives(SDL_GPURenderPass *renderPass, Uint32 numVertices, Uint32 numInstances, Uint32 firstVertex, Uint32 firstInstance);
|
||||
void rgpuEndCopyPass(SDL_GPUCopyPass *copyPass);
|
||||
void rgpuEndRenderPass(SDL_GPURenderPass *renderPass);
|
||||
void rgpuGenerateMipmapsForTexture(SDL_GPUCommandBuffer *commandBuffer, SDL_GPUTexture *texture);
|
||||
const char * rgpuGetDeviceDriver(SDL_GPUDevice *device);
|
||||
SDL_GPUShaderFormat rgpuGetShaderFormats(SDL_GPUDevice *device);
|
||||
SDL_GPUTextureFormat rgpuGetSwapchainTextureFormat(SDL_GPUDevice *device, SDL_Window *window);
|
||||
SDL_GPUTextureFormat rgpuGetTextureFormatFromPixelFormat(SDL_PixelFormat format);
|
||||
void * rgpuMapTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer, bool cycle);
|
||||
void rgpuPushFragmentUniformData(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length);
|
||||
void rgpuPushVertexUniformData(SDL_GPUCommandBuffer *commandBuffer, Uint32 slotIndex, const void *data, Uint32 length);
|
||||
void rgpuReleaseBuffer(SDL_GPUDevice *device, SDL_GPUBuffer *buffer);
|
||||
void rgpuReleaseGraphicsPipeline(SDL_GPUDevice *device, SDL_GPUGraphicsPipeline *graphicsPipeline);
|
||||
void rgpuReleaseSampler(SDL_GPUDevice *device, SDL_GPUSampler *sampler);
|
||||
void rgpuReleaseShader(SDL_GPUDevice *device, SDL_GPUShader *shader);
|
||||
void rgpuReleaseTexture(SDL_GPUDevice *device, SDL_GPUTexture *texture);
|
||||
void rgpuReleaseTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer);
|
||||
void rgpuSetScissor(SDL_GPURenderPass *renderPass, const SDL_Rect *scissor);
|
||||
void rgpuSetStencilReference(SDL_GPURenderPass *renderPass, Uint8 reference);
|
||||
bool rgpuSubmitCommandBuffer(SDL_GPUCommandBuffer *commandBuffer);
|
||||
bool rgpuTextureSupportsFormat(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUTextureType type, SDL_GPUTextureUsageFlags usage);
|
||||
bool rgpuTextureSupportsSampleCount(SDL_GPUDevice *device, SDL_GPUTextureFormat format, SDL_GPUSampleCount sampleCount);
|
||||
void rgpuUnmapTransferBuffer(SDL_GPUDevice *device, SDL_GPUTransferBuffer *transferBuffer);
|
||||
void rgpuUploadToBuffer(SDL_GPUCopyPass *copyPass, const SDL_GPUTransferBufferLocation *source, const SDL_GPUBufferRegion *destination, bool cycle);
|
||||
void rgpuUploadToTexture(SDL_GPUCopyPass *copyPass, const SDL_GPUTextureTransferInfo *source, const SDL_GPUTextureRegion *destination, bool cycle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RENDER_H
|
||||
1675
src/renderGles.c
Normal file
1675
src/renderGles.c
Normal file
File diff suppressed because it is too large
Load diff
486
src/renderGlesApi.h
Normal file
486
src/renderGlesApi.h
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
/*
|
||||
*
|
||||
* Singe 3
|
||||
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RENDER_GLES_API_H
|
||||
#define RENDER_GLES_API_H
|
||||
|
||||
// The OpenGL ES entry points renderGles.c uses: declared here, loaded through SDL, linked never.
|
||||
//
|
||||
// Nothing in this file includes a GL header. Linking -lGLESv2 would break the Windows and macOS
|
||||
// builds, and merely *including* <GLES3/gl31.h> breaks them too -- neither platform ships it, and
|
||||
// the first cross build after this backend landed failed on all three non-Linux targets for exactly
|
||||
// that reason. Since every function is fetched at run time through SDL_GL_GetProcAddress anyway,
|
||||
// the types and enumerants below are all the declaration that is needed, and a machine with no GLES
|
||||
// driver simply fails renderGlesStart and keeps its 2D renderer.
|
||||
//
|
||||
// The lists are exactly what renderGles.c uses, so anything it gains that is not here fails to
|
||||
// compile or link rather than crashing on a null pointer.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
|
||||
// The Khronos types, in the one spelling every ES implementation agrees on.
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef signed char GLbyte;
|
||||
typedef short GLshort;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned char GLubyte;
|
||||
typedef unsigned short GLushort;
|
||||
typedef unsigned int GLuint;
|
||||
typedef float GLfloat;
|
||||
typedef char GLchar;
|
||||
typedef void GLvoid;
|
||||
typedef intptr_t GLintptr;
|
||||
typedef intptr_t GLsizeiptr;
|
||||
|
||||
#define GL_APIENTRYP *
|
||||
|
||||
|
||||
// The enumerants used, and only those.
|
||||
#define GL_ALWAYS 0x0207
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_CCW 0x0901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_COLOR 0x1800
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_COMPARE_REF_TO_TEXTURE 0x884E
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_CONSTANT_COLOR 0x8001
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_CW 0x0900
|
||||
#define GL_DECR 0x1E03
|
||||
#define GL_DECR_WRAP 0x8508
|
||||
#define GL_DEPTH24_STENCIL8 0x88F0
|
||||
#define GL_DEPTH32F_STENCIL8 0x8CAD
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_DEPTH_COMPONENT24 0x81A6
|
||||
#define GL_DEPTH_COMPONENT32F 0x8CAC
|
||||
#define GL_DEPTH_STENCIL 0x84F9
|
||||
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_EQUAL 0x0202
|
||||
#define GL_FALSE 0
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
|
||||
#define GL_FUNC_SUBTRACT 0x800A
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_GREATER 0x0204
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#define GL_INCR 0x1E02
|
||||
#define GL_INCR_WRAP 0x8507
|
||||
#define GL_INT 0x1404
|
||||
#define GL_INVALID_INDEX 0xFFFFFFFFu
|
||||
#define GL_INVERT 0x150A
|
||||
#define GL_KEEP 0x1E00
|
||||
#define GL_LEQUAL 0x0203
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#define GL_MAX 0x8008
|
||||
#define GL_MIN 0x8007
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#define GL_MIRRORED_REPEAT 0x8370
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_NONE 0
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_ONE 1
|
||||
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x0301
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_R8 0x8229
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#define GL_RED 0x1903
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_REPLACE 0x1E01
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_RGBA16F 0x881A
|
||||
#define GL_RGBA32F 0x8814
|
||||
#define GL_RGBA8 0x8058
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_SHADER_STORAGE_BUFFER 0x90D2
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
#define GL_SRGB8_ALPHA8 0x8C43
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_TEXTURE_2D_ARRAY 0x8C1A
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
||||
#define GL_TEXTURE_BASE_LEVEL 0x813C
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#define GL_TEXTURE_MAX_LOD 0x813B
|
||||
#define GL_TEXTURE_MIN_LOD 0x813A
|
||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
#define GL_TEXTURE_COMPARE_FUNC 0x884D
|
||||
#define GL_TEXTURE_COMPARE_MODE 0x884C
|
||||
#define GL_TEXTURE_CUBE_MAP 0x8513
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_R 0x8072
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRUE 1
|
||||
#define GL_UNIFORM_BUFFER 0x8A11
|
||||
#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_UNSIGNED_INT_24_8 0x84FA
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_ZERO 0
|
||||
|
||||
|
||||
typedef void (GL_APIENTRYP GlesActiveTextureFn)(GLenum texture);
|
||||
typedef void (GL_APIENTRYP GlesAttachShaderFn)(GLuint program, GLuint shader);
|
||||
typedef void (GL_APIENTRYP GlesBindBufferFn)(GLenum target, GLuint buffer);
|
||||
typedef void (GL_APIENTRYP GlesBindBufferBaseFn)(GLenum target, GLuint index, GLuint buffer);
|
||||
typedef void (GL_APIENTRYP GlesBindBufferRangeFn)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
||||
typedef void (GL_APIENTRYP GlesBindFramebufferFn)(GLenum target, GLuint framebuffer);
|
||||
typedef void (GL_APIENTRYP GlesBindRenderbufferFn)(GLenum target, GLuint renderbuffer);
|
||||
typedef void (GL_APIENTRYP GlesBindSamplerFn)(GLuint unit, GLuint sampler);
|
||||
typedef void (GL_APIENTRYP GlesBindTextureFn)(GLenum target, GLuint texture);
|
||||
typedef void (GL_APIENTRYP GlesBindVertexArrayFn)(GLuint array);
|
||||
typedef void (GL_APIENTRYP GlesBlendEquationSeparateFn)(GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (GL_APIENTRYP GlesBlendFuncSeparateFn)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (GL_APIENTRYP GlesBlitFramebufferFn)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
typedef void (GL_APIENTRYP GlesBufferDataFn)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (GL_APIENTRYP GlesBufferSubDataFn)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
typedef GLenum (GL_APIENTRYP GlesCheckFramebufferStatusFn)(GLenum target);
|
||||
typedef void (GL_APIENTRYP GlesClearFn)(GLbitfield mask);
|
||||
typedef void (GL_APIENTRYP GlesClearBufferfvFn)(GLenum buffer, GLint drawbuffer, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP GlesClearDepthfFn)(GLfloat d);
|
||||
typedef void (GL_APIENTRYP GlesClearStencilFn)(GLint s);
|
||||
typedef void (GL_APIENTRYP GlesColorMaskFn)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
typedef void (GL_APIENTRYP GlesCompileShaderFn)(GLuint shader);
|
||||
typedef void (GL_APIENTRYP GlesCopyTexSubImage2DFn)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef GLuint (GL_APIENTRYP GlesCreateProgramFn)(void);
|
||||
typedef GLuint (GL_APIENTRYP GlesCreateShaderFn)(GLenum type);
|
||||
typedef void (GL_APIENTRYP GlesCullFaceFn)(GLenum mode);
|
||||
typedef void (GL_APIENTRYP GlesDeleteBuffersFn)(GLsizei n, const GLuint *buffers);
|
||||
typedef void (GL_APIENTRYP GlesDeleteFramebuffersFn)(GLsizei n, const GLuint *framebuffers);
|
||||
typedef void (GL_APIENTRYP GlesDeleteProgramFn)(GLuint program);
|
||||
typedef void (GL_APIENTRYP GlesDeleteRenderbuffersFn)(GLsizei n, const GLuint *renderbuffers);
|
||||
typedef void (GL_APIENTRYP GlesDeleteSamplersFn)(GLsizei count, const GLuint *samplers);
|
||||
typedef void (GL_APIENTRYP GlesDeleteShaderFn)(GLuint shader);
|
||||
typedef void (GL_APIENTRYP GlesDeleteTexturesFn)(GLsizei n, const GLuint *textures);
|
||||
typedef void (GL_APIENTRYP GlesDeleteVertexArraysFn)(GLsizei n, const GLuint *arrays);
|
||||
typedef void (GL_APIENTRYP GlesDepthFuncFn)(GLenum func);
|
||||
typedef void (GL_APIENTRYP GlesDepthMaskFn)(GLboolean flag);
|
||||
typedef void (GL_APIENTRYP GlesDisableFn)(GLenum cap);
|
||||
typedef void (GL_APIENTRYP GlesDrawArraysInstancedFn)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
|
||||
typedef void (GL_APIENTRYP GlesDrawBuffersFn)(GLsizei n, const GLenum *bufs);
|
||||
typedef void (GL_APIENTRYP GlesDrawElementsInstancedFn)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
|
||||
typedef void (GL_APIENTRYP GlesEnableFn)(GLenum cap);
|
||||
typedef void (GL_APIENTRYP GlesEnableVertexAttribArrayFn)(GLuint index);
|
||||
typedef void (GL_APIENTRYP GlesFlushFn)(void);
|
||||
typedef void (GL_APIENTRYP GlesFramebufferRenderbufferFn)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
typedef void (GL_APIENTRYP GlesFramebufferTexture2DFn)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
typedef void (GL_APIENTRYP GlesFramebufferTextureLayerFn)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
|
||||
typedef void (GL_APIENTRYP GlesFrontFaceFn)(GLenum mode);
|
||||
typedef void (GL_APIENTRYP GlesGenBuffersFn)(GLsizei n, GLuint *buffers);
|
||||
typedef void (GL_APIENTRYP GlesGenFramebuffersFn)(GLsizei n, GLuint *framebuffers);
|
||||
typedef void (GL_APIENTRYP GlesGenRenderbuffersFn)(GLsizei n, GLuint *renderbuffers);
|
||||
typedef void (GL_APIENTRYP GlesGenSamplersFn)(GLsizei count, GLuint *samplers);
|
||||
typedef void (GL_APIENTRYP GlesGenTexturesFn)(GLsizei n, GLuint *textures);
|
||||
typedef void (GL_APIENTRYP GlesGenVertexArraysFn)(GLsizei n, GLuint *arrays);
|
||||
typedef void (GL_APIENTRYP GlesGenerateMipmapFn)(GLenum target);
|
||||
typedef GLenum (GL_APIENTRYP GlesGetErrorFn)(void);
|
||||
typedef void (GL_APIENTRYP GlesGetIntegervFn)(GLenum pname, GLint *data);
|
||||
typedef void (GL_APIENTRYP GlesGetInternalformativFn)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params);
|
||||
typedef void (GL_APIENTRYP GlesGetProgramInfoLogFn)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (GL_APIENTRYP GlesGetProgramivFn)(GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP GlesGetShaderInfoLogFn)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (GL_APIENTRYP GlesGetShaderivFn)(GLuint shader, GLenum pname, GLint *params);
|
||||
typedef const GLubyte * (GL_APIENTRYP GlesGetStringFn)(GLenum name);
|
||||
typedef GLuint (GL_APIENTRYP GlesGetUniformBlockIndexFn)(GLuint program, const GLchar *uniformBlockName);
|
||||
typedef void (GL_APIENTRYP GlesLinkProgramFn)(GLuint program);
|
||||
typedef void (GL_APIENTRYP GlesPixelStoreiFn)(GLenum pname, GLint param);
|
||||
typedef void (GL_APIENTRYP GlesPolygonOffsetFn)(GLfloat factor, GLfloat units);
|
||||
typedef void (GL_APIENTRYP GlesReadBufferFn)(GLenum src);
|
||||
typedef void (GL_APIENTRYP GlesRenderbufferStorageMultisampleFn)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP GlesGetFloatvFn)(GLenum pname, GLfloat *data);
|
||||
typedef GLint (GL_APIENTRYP GlesGetUniformLocationFn)(GLuint program, const GLchar *name);
|
||||
typedef void (GL_APIENTRYP GlesUniform1iFn)(GLint location, GLint v0);
|
||||
typedef void (GL_APIENTRYP GlesSamplerParameterfFn)(GLuint sampler, GLenum pname, GLfloat param);
|
||||
typedef void (GL_APIENTRYP GlesSamplerParameteriFn)(GLuint sampler, GLenum pname, GLint param);
|
||||
typedef void (GL_APIENTRYP GlesScissorFn)(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP GlesShaderSourceFn)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (GL_APIENTRYP GlesStencilFuncSeparateFn)(GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
typedef void (GL_APIENTRYP GlesStencilMaskFn)(GLuint mask);
|
||||
typedef void (GL_APIENTRYP GlesStencilMaskSeparateFn)(GLenum face, GLuint mask);
|
||||
typedef void (GL_APIENTRYP GlesStencilOpSeparateFn)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
typedef void (GL_APIENTRYP GlesTexParameteriFn)(GLenum target, GLenum pname, GLint param);
|
||||
typedef void (GL_APIENTRYP GlesTexStorage2DFn)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP GlesTexStorage3DFn)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
|
||||
typedef void (GL_APIENTRYP GlesTexSubImage2DFn)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (GL_APIENTRYP GlesTexSubImage3DFn)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (GL_APIENTRYP GlesUniformBlockBindingFn)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
|
||||
typedef void (GL_APIENTRYP GlesUseProgramFn)(GLuint program);
|
||||
typedef void (GL_APIENTRYP GlesValidateProgramFn)(GLuint program);
|
||||
typedef void (GL_APIENTRYP GlesVertexAttribIPointerFn)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
typedef void (GL_APIENTRYP GlesVertexAttribPointerFn)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
typedef void (GL_APIENTRYP GlesViewportFn)(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
|
||||
typedef struct GlesApiS {
|
||||
GlesActiveTextureFn activeTexture;
|
||||
GlesAttachShaderFn attachShader;
|
||||
GlesBindBufferFn bindBuffer;
|
||||
GlesBindBufferBaseFn bindBufferBase;
|
||||
GlesBindBufferRangeFn bindBufferRange;
|
||||
GlesBindFramebufferFn bindFramebuffer;
|
||||
GlesBindRenderbufferFn bindRenderbuffer;
|
||||
GlesBindSamplerFn bindSampler;
|
||||
GlesBindTextureFn bindTexture;
|
||||
GlesBindVertexArrayFn bindVertexArray;
|
||||
GlesBlendEquationSeparateFn blendEquationSeparate;
|
||||
GlesBlendFuncSeparateFn blendFuncSeparate;
|
||||
GlesBlitFramebufferFn blitFramebuffer;
|
||||
GlesBufferDataFn bufferData;
|
||||
GlesBufferSubDataFn bufferSubData;
|
||||
GlesCheckFramebufferStatusFn checkFramebufferStatus;
|
||||
GlesClearFn clear;
|
||||
GlesClearBufferfvFn clearBufferfv;
|
||||
GlesClearDepthfFn clearDepthf;
|
||||
GlesClearStencilFn clearStencil;
|
||||
GlesColorMaskFn colorMask;
|
||||
GlesCompileShaderFn compileShader;
|
||||
GlesCopyTexSubImage2DFn copyTexSubImage2D;
|
||||
GlesCreateProgramFn createProgram;
|
||||
GlesCreateShaderFn createShader;
|
||||
GlesCullFaceFn cullFace;
|
||||
GlesDeleteBuffersFn deleteBuffers;
|
||||
GlesDeleteFramebuffersFn deleteFramebuffers;
|
||||
GlesDeleteProgramFn deleteProgram;
|
||||
GlesDeleteRenderbuffersFn deleteRenderbuffers;
|
||||
GlesDeleteSamplersFn deleteSamplers;
|
||||
GlesDeleteShaderFn deleteShader;
|
||||
GlesDeleteTexturesFn deleteTextures;
|
||||
GlesDeleteVertexArraysFn deleteVertexArrays;
|
||||
GlesDepthFuncFn depthFunc;
|
||||
GlesDepthMaskFn depthMask;
|
||||
GlesDisableFn disable;
|
||||
GlesDrawArraysInstancedFn drawArraysInstanced;
|
||||
GlesDrawBuffersFn drawBuffers;
|
||||
GlesDrawElementsInstancedFn drawElementsInstanced;
|
||||
GlesEnableFn enable;
|
||||
GlesEnableVertexAttribArrayFn enableVertexAttribArray;
|
||||
GlesFlushFn flush;
|
||||
GlesFramebufferRenderbufferFn framebufferRenderbuffer;
|
||||
GlesFramebufferTexture2DFn framebufferTexture2D;
|
||||
GlesFramebufferTextureLayerFn framebufferTextureLayer;
|
||||
GlesFrontFaceFn frontFace;
|
||||
GlesGenBuffersFn genBuffers;
|
||||
GlesGenFramebuffersFn genFramebuffers;
|
||||
GlesGenRenderbuffersFn genRenderbuffers;
|
||||
GlesGenSamplersFn genSamplers;
|
||||
GlesGenTexturesFn genTextures;
|
||||
GlesGenVertexArraysFn genVertexArrays;
|
||||
GlesGenerateMipmapFn generateMipmap;
|
||||
GlesGetErrorFn getError;
|
||||
GlesGetIntegervFn getIntegerv;
|
||||
GlesGetInternalformativFn getInternalformativ;
|
||||
GlesGetProgramInfoLogFn getProgramInfoLog;
|
||||
GlesGetProgramivFn getProgramiv;
|
||||
GlesGetShaderInfoLogFn getShaderInfoLog;
|
||||
GlesGetShaderivFn getShaderiv;
|
||||
GlesGetStringFn getString;
|
||||
GlesGetUniformBlockIndexFn getUniformBlockIndex;
|
||||
GlesLinkProgramFn linkProgram;
|
||||
GlesPixelStoreiFn pixelStorei;
|
||||
GlesPolygonOffsetFn polygonOffset;
|
||||
GlesReadBufferFn readBuffer;
|
||||
GlesRenderbufferStorageMultisampleFn renderbufferStorageMultisample;
|
||||
GlesGetFloatvFn getFloatv;
|
||||
GlesGetUniformLocationFn getUniformLocation;
|
||||
GlesUniform1iFn uniform1i;
|
||||
GlesSamplerParameterfFn samplerParameterf;
|
||||
GlesSamplerParameteriFn samplerParameteri;
|
||||
GlesScissorFn scissor;
|
||||
GlesShaderSourceFn shaderSource;
|
||||
GlesStencilFuncSeparateFn stencilFuncSeparate;
|
||||
GlesStencilMaskFn stencilMask;
|
||||
GlesStencilMaskSeparateFn stencilMaskSeparate;
|
||||
GlesStencilOpSeparateFn stencilOpSeparate;
|
||||
GlesTexParameteriFn texParameteri;
|
||||
GlesTexStorage2DFn texStorage2D;
|
||||
GlesTexStorage3DFn texStorage3D;
|
||||
GlesTexSubImage2DFn texSubImage2D;
|
||||
GlesTexSubImage3DFn texSubImage3D;
|
||||
GlesUniformBlockBindingFn uniformBlockBinding;
|
||||
GlesUseProgramFn useProgram;
|
||||
GlesValidateProgramFn validateProgram;
|
||||
GlesVertexAttribIPointerFn vertexAttribIPointer;
|
||||
GlesVertexAttribPointerFn vertexAttribPointer;
|
||||
GlesViewportFn viewport;
|
||||
} GlesApiT;
|
||||
|
||||
|
||||
extern GlesApiT _glesApi;
|
||||
|
||||
|
||||
bool renderGlesLoad(void);
|
||||
|
||||
|
||||
// Every call in renderGles.c goes through the table.
|
||||
#define glActiveTexture _glesApi.activeTexture
|
||||
#define glAttachShader _glesApi.attachShader
|
||||
#define glBindBuffer _glesApi.bindBuffer
|
||||
#define glBindBufferBase _glesApi.bindBufferBase
|
||||
#define glBindBufferRange _glesApi.bindBufferRange
|
||||
#define glBindFramebuffer _glesApi.bindFramebuffer
|
||||
#define glBindRenderbuffer _glesApi.bindRenderbuffer
|
||||
#define glBindSampler _glesApi.bindSampler
|
||||
#define glBindTexture _glesApi.bindTexture
|
||||
#define glBindVertexArray _glesApi.bindVertexArray
|
||||
#define glBlendEquationSeparate _glesApi.blendEquationSeparate
|
||||
#define glBlendFuncSeparate _glesApi.blendFuncSeparate
|
||||
#define glBlitFramebuffer _glesApi.blitFramebuffer
|
||||
#define glBufferData _glesApi.bufferData
|
||||
#define glBufferSubData _glesApi.bufferSubData
|
||||
#define glCheckFramebufferStatus _glesApi.checkFramebufferStatus
|
||||
#define glClear _glesApi.clear
|
||||
#define glClearBufferfv _glesApi.clearBufferfv
|
||||
#define glClearDepthf _glesApi.clearDepthf
|
||||
#define glClearStencil _glesApi.clearStencil
|
||||
#define glColorMask _glesApi.colorMask
|
||||
#define glCompileShader _glesApi.compileShader
|
||||
#define glCopyTexSubImage2D _glesApi.copyTexSubImage2D
|
||||
#define glCreateProgram _glesApi.createProgram
|
||||
#define glCreateShader _glesApi.createShader
|
||||
#define glCullFace _glesApi.cullFace
|
||||
#define glDeleteBuffers _glesApi.deleteBuffers
|
||||
#define glDeleteFramebuffers _glesApi.deleteFramebuffers
|
||||
#define glDeleteProgram _glesApi.deleteProgram
|
||||
#define glDeleteRenderbuffers _glesApi.deleteRenderbuffers
|
||||
#define glDeleteSamplers _glesApi.deleteSamplers
|
||||
#define glDeleteShader _glesApi.deleteShader
|
||||
#define glDeleteTextures _glesApi.deleteTextures
|
||||
#define glDeleteVertexArrays _glesApi.deleteVertexArrays
|
||||
#define glDepthFunc _glesApi.depthFunc
|
||||
#define glDepthMask _glesApi.depthMask
|
||||
#define glDisable _glesApi.disable
|
||||
#define glDrawArraysInstanced _glesApi.drawArraysInstanced
|
||||
#define glDrawBuffers _glesApi.drawBuffers
|
||||
#define glDrawElementsInstanced _glesApi.drawElementsInstanced
|
||||
#define glEnable _glesApi.enable
|
||||
#define glEnableVertexAttribArray _glesApi.enableVertexAttribArray
|
||||
#define glFlush _glesApi.flush
|
||||
#define glFramebufferRenderbuffer _glesApi.framebufferRenderbuffer
|
||||
#define glFramebufferTexture2D _glesApi.framebufferTexture2D
|
||||
#define glFramebufferTextureLayer _glesApi.framebufferTextureLayer
|
||||
#define glFrontFace _glesApi.frontFace
|
||||
#define glGenBuffers _glesApi.genBuffers
|
||||
#define glGenFramebuffers _glesApi.genFramebuffers
|
||||
#define glGenRenderbuffers _glesApi.genRenderbuffers
|
||||
#define glGenSamplers _glesApi.genSamplers
|
||||
#define glGenTextures _glesApi.genTextures
|
||||
#define glGenVertexArrays _glesApi.genVertexArrays
|
||||
#define glGenerateMipmap _glesApi.generateMipmap
|
||||
#define glGetError _glesApi.getError
|
||||
#define glGetIntegerv _glesApi.getIntegerv
|
||||
#define glGetInternalformativ _glesApi.getInternalformativ
|
||||
#define glGetProgramInfoLog _glesApi.getProgramInfoLog
|
||||
#define glGetProgramiv _glesApi.getProgramiv
|
||||
#define glGetShaderInfoLog _glesApi.getShaderInfoLog
|
||||
#define glGetShaderiv _glesApi.getShaderiv
|
||||
#define glGetString _glesApi.getString
|
||||
#define glGetUniformBlockIndex _glesApi.getUniformBlockIndex
|
||||
#define glLinkProgram _glesApi.linkProgram
|
||||
#define glPixelStorei _glesApi.pixelStorei
|
||||
#define glPolygonOffset _glesApi.polygonOffset
|
||||
#define glReadBuffer _glesApi.readBuffer
|
||||
#define glRenderbufferStorageMultisample _glesApi.renderbufferStorageMultisample
|
||||
#define glGetFloatv _glesApi.getFloatv
|
||||
#define glGetUniformLocation _glesApi.getUniformLocation
|
||||
#define glUniform1i _glesApi.uniform1i
|
||||
#define glSamplerParameterf _glesApi.samplerParameterf
|
||||
#define glSamplerParameteri _glesApi.samplerParameteri
|
||||
#define glScissor _glesApi.scissor
|
||||
#define glShaderSource _glesApi.shaderSource
|
||||
#define glStencilFuncSeparate _glesApi.stencilFuncSeparate
|
||||
#define glStencilMask _glesApi.stencilMask
|
||||
#define glStencilMaskSeparate _glesApi.stencilMaskSeparate
|
||||
#define glStencilOpSeparate _glesApi.stencilOpSeparate
|
||||
#define glTexParameteri _glesApi.texParameteri
|
||||
#define glTexStorage2D _glesApi.texStorage2D
|
||||
#define glTexStorage3D _glesApi.texStorage3D
|
||||
#define glTexSubImage2D _glesApi.texSubImage2D
|
||||
#define glTexSubImage3D _glesApi.texSubImage3D
|
||||
#define glUniformBlockBinding _glesApi.uniformBlockBinding
|
||||
#define glUseProgram _glesApi.useProgram
|
||||
#define glValidateProgram _glesApi.validateProgram
|
||||
#define glVertexAttribIPointer _glesApi.vertexAttribIPointer
|
||||
#define glVertexAttribPointer _glesApi.vertexAttribPointer
|
||||
#define glViewport _glesApi.viewport
|
||||
|
||||
|
||||
#endif // RENDER_GLES_API_H
|
||||
230
src/renderGlesLoad.c
Normal file
230
src/renderGlesLoad.c
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
*
|
||||
* Singe 3
|
||||
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// Loading the GLES entry points. See renderGlesApi.h for why they are fetched rather than linked.
|
||||
|
||||
#include "renderGlesApi.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
GlesApiT _glesApi;
|
||||
|
||||
|
||||
// Fails on the first missing entry point rather than half loading: a null here would be a crash
|
||||
// later, inside a draw call, with nothing to say which function was absent.
|
||||
bool renderGlesLoad(void) {
|
||||
_glesApi.activeTexture = (GlesActiveTextureFn)SDL_GL_GetProcAddress("glActiveTexture");
|
||||
_glesApi.attachShader = (GlesAttachShaderFn)SDL_GL_GetProcAddress("glAttachShader");
|
||||
_glesApi.bindBuffer = (GlesBindBufferFn)SDL_GL_GetProcAddress("glBindBuffer");
|
||||
_glesApi.bindBufferBase = (GlesBindBufferBaseFn)SDL_GL_GetProcAddress("glBindBufferBase");
|
||||
_glesApi.bindBufferRange = (GlesBindBufferRangeFn)SDL_GL_GetProcAddress("glBindBufferRange");
|
||||
_glesApi.bindFramebuffer = (GlesBindFramebufferFn)SDL_GL_GetProcAddress("glBindFramebuffer");
|
||||
_glesApi.bindRenderbuffer = (GlesBindRenderbufferFn)SDL_GL_GetProcAddress("glBindRenderbuffer");
|
||||
_glesApi.bindSampler = (GlesBindSamplerFn)SDL_GL_GetProcAddress("glBindSampler");
|
||||
_glesApi.bindTexture = (GlesBindTextureFn)SDL_GL_GetProcAddress("glBindTexture");
|
||||
_glesApi.bindVertexArray = (GlesBindVertexArrayFn)SDL_GL_GetProcAddress("glBindVertexArray");
|
||||
_glesApi.blendEquationSeparate = (GlesBlendEquationSeparateFn)SDL_GL_GetProcAddress("glBlendEquationSeparate");
|
||||
_glesApi.blendFuncSeparate = (GlesBlendFuncSeparateFn)SDL_GL_GetProcAddress("glBlendFuncSeparate");
|
||||
_glesApi.blitFramebuffer = (GlesBlitFramebufferFn)SDL_GL_GetProcAddress("glBlitFramebuffer");
|
||||
_glesApi.bufferData = (GlesBufferDataFn)SDL_GL_GetProcAddress("glBufferData");
|
||||
_glesApi.bufferSubData = (GlesBufferSubDataFn)SDL_GL_GetProcAddress("glBufferSubData");
|
||||
_glesApi.checkFramebufferStatus = (GlesCheckFramebufferStatusFn)SDL_GL_GetProcAddress("glCheckFramebufferStatus");
|
||||
_glesApi.clear = (GlesClearFn)SDL_GL_GetProcAddress("glClear");
|
||||
_glesApi.clearBufferfv = (GlesClearBufferfvFn)SDL_GL_GetProcAddress("glClearBufferfv");
|
||||
_glesApi.clearDepthf = (GlesClearDepthfFn)SDL_GL_GetProcAddress("glClearDepthf");
|
||||
_glesApi.clearStencil = (GlesClearStencilFn)SDL_GL_GetProcAddress("glClearStencil");
|
||||
_glesApi.colorMask = (GlesColorMaskFn)SDL_GL_GetProcAddress("glColorMask");
|
||||
_glesApi.compileShader = (GlesCompileShaderFn)SDL_GL_GetProcAddress("glCompileShader");
|
||||
_glesApi.copyTexSubImage2D = (GlesCopyTexSubImage2DFn)SDL_GL_GetProcAddress("glCopyTexSubImage2D");
|
||||
_glesApi.createProgram = (GlesCreateProgramFn)SDL_GL_GetProcAddress("glCreateProgram");
|
||||
_glesApi.createShader = (GlesCreateShaderFn)SDL_GL_GetProcAddress("glCreateShader");
|
||||
_glesApi.cullFace = (GlesCullFaceFn)SDL_GL_GetProcAddress("glCullFace");
|
||||
_glesApi.deleteBuffers = (GlesDeleteBuffersFn)SDL_GL_GetProcAddress("glDeleteBuffers");
|
||||
_glesApi.deleteFramebuffers = (GlesDeleteFramebuffersFn)SDL_GL_GetProcAddress("glDeleteFramebuffers");
|
||||
_glesApi.deleteProgram = (GlesDeleteProgramFn)SDL_GL_GetProcAddress("glDeleteProgram");
|
||||
_glesApi.deleteRenderbuffers = (GlesDeleteRenderbuffersFn)SDL_GL_GetProcAddress("glDeleteRenderbuffers");
|
||||
_glesApi.deleteSamplers = (GlesDeleteSamplersFn)SDL_GL_GetProcAddress("glDeleteSamplers");
|
||||
_glesApi.deleteShader = (GlesDeleteShaderFn)SDL_GL_GetProcAddress("glDeleteShader");
|
||||
_glesApi.deleteTextures = (GlesDeleteTexturesFn)SDL_GL_GetProcAddress("glDeleteTextures");
|
||||
_glesApi.deleteVertexArrays = (GlesDeleteVertexArraysFn)SDL_GL_GetProcAddress("glDeleteVertexArrays");
|
||||
_glesApi.depthFunc = (GlesDepthFuncFn)SDL_GL_GetProcAddress("glDepthFunc");
|
||||
_glesApi.depthMask = (GlesDepthMaskFn)SDL_GL_GetProcAddress("glDepthMask");
|
||||
_glesApi.disable = (GlesDisableFn)SDL_GL_GetProcAddress("glDisable");
|
||||
_glesApi.drawArraysInstanced = (GlesDrawArraysInstancedFn)SDL_GL_GetProcAddress("glDrawArraysInstanced");
|
||||
_glesApi.drawBuffers = (GlesDrawBuffersFn)SDL_GL_GetProcAddress("glDrawBuffers");
|
||||
_glesApi.drawElementsInstanced = (GlesDrawElementsInstancedFn)SDL_GL_GetProcAddress("glDrawElementsInstanced");
|
||||
_glesApi.enable = (GlesEnableFn)SDL_GL_GetProcAddress("glEnable");
|
||||
_glesApi.enableVertexAttribArray = (GlesEnableVertexAttribArrayFn)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
||||
_glesApi.flush = (GlesFlushFn)SDL_GL_GetProcAddress("glFlush");
|
||||
_glesApi.framebufferRenderbuffer = (GlesFramebufferRenderbufferFn)SDL_GL_GetProcAddress("glFramebufferRenderbuffer");
|
||||
_glesApi.framebufferTexture2D = (GlesFramebufferTexture2DFn)SDL_GL_GetProcAddress("glFramebufferTexture2D");
|
||||
_glesApi.framebufferTextureLayer = (GlesFramebufferTextureLayerFn)SDL_GL_GetProcAddress("glFramebufferTextureLayer");
|
||||
_glesApi.frontFace = (GlesFrontFaceFn)SDL_GL_GetProcAddress("glFrontFace");
|
||||
_glesApi.genBuffers = (GlesGenBuffersFn)SDL_GL_GetProcAddress("glGenBuffers");
|
||||
_glesApi.genFramebuffers = (GlesGenFramebuffersFn)SDL_GL_GetProcAddress("glGenFramebuffers");
|
||||
_glesApi.genRenderbuffers = (GlesGenRenderbuffersFn)SDL_GL_GetProcAddress("glGenRenderbuffers");
|
||||
_glesApi.genSamplers = (GlesGenSamplersFn)SDL_GL_GetProcAddress("glGenSamplers");
|
||||
_glesApi.genTextures = (GlesGenTexturesFn)SDL_GL_GetProcAddress("glGenTextures");
|
||||
_glesApi.genVertexArrays = (GlesGenVertexArraysFn)SDL_GL_GetProcAddress("glGenVertexArrays");
|
||||
_glesApi.generateMipmap = (GlesGenerateMipmapFn)SDL_GL_GetProcAddress("glGenerateMipmap");
|
||||
_glesApi.getError = (GlesGetErrorFn)SDL_GL_GetProcAddress("glGetError");
|
||||
_glesApi.getIntegerv = (GlesGetIntegervFn)SDL_GL_GetProcAddress("glGetIntegerv");
|
||||
_glesApi.getInternalformativ = (GlesGetInternalformativFn)SDL_GL_GetProcAddress("glGetInternalformativ");
|
||||
_glesApi.getProgramInfoLog = (GlesGetProgramInfoLogFn)SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
||||
_glesApi.getProgramiv = (GlesGetProgramivFn)SDL_GL_GetProcAddress("glGetProgramiv");
|
||||
_glesApi.getShaderInfoLog = (GlesGetShaderInfoLogFn)SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
||||
_glesApi.getShaderiv = (GlesGetShaderivFn)SDL_GL_GetProcAddress("glGetShaderiv");
|
||||
_glesApi.getString = (GlesGetStringFn)SDL_GL_GetProcAddress("glGetString");
|
||||
_glesApi.getUniformBlockIndex = (GlesGetUniformBlockIndexFn)SDL_GL_GetProcAddress("glGetUniformBlockIndex");
|
||||
_glesApi.linkProgram = (GlesLinkProgramFn)SDL_GL_GetProcAddress("glLinkProgram");
|
||||
_glesApi.pixelStorei = (GlesPixelStoreiFn)SDL_GL_GetProcAddress("glPixelStorei");
|
||||
_glesApi.polygonOffset = (GlesPolygonOffsetFn)SDL_GL_GetProcAddress("glPolygonOffset");
|
||||
_glesApi.readBuffer = (GlesReadBufferFn)SDL_GL_GetProcAddress("glReadBuffer");
|
||||
_glesApi.renderbufferStorageMultisample = (GlesRenderbufferStorageMultisampleFn)SDL_GL_GetProcAddress("glRenderbufferStorageMultisample");
|
||||
_glesApi.getFloatv = (GlesGetFloatvFn)SDL_GL_GetProcAddress("glGetFloatv");
|
||||
_glesApi.getUniformLocation = (GlesGetUniformLocationFn)SDL_GL_GetProcAddress("glGetUniformLocation");
|
||||
_glesApi.uniform1i = (GlesUniform1iFn)SDL_GL_GetProcAddress("glUniform1i");
|
||||
_glesApi.samplerParameterf = (GlesSamplerParameterfFn)SDL_GL_GetProcAddress("glSamplerParameterf");
|
||||
_glesApi.samplerParameteri = (GlesSamplerParameteriFn)SDL_GL_GetProcAddress("glSamplerParameteri");
|
||||
_glesApi.scissor = (GlesScissorFn)SDL_GL_GetProcAddress("glScissor");
|
||||
_glesApi.shaderSource = (GlesShaderSourceFn)SDL_GL_GetProcAddress("glShaderSource");
|
||||
_glesApi.stencilFuncSeparate = (GlesStencilFuncSeparateFn)SDL_GL_GetProcAddress("glStencilFuncSeparate");
|
||||
_glesApi.stencilMask = (GlesStencilMaskFn)SDL_GL_GetProcAddress("glStencilMask");
|
||||
_glesApi.stencilMaskSeparate = (GlesStencilMaskSeparateFn)SDL_GL_GetProcAddress("glStencilMaskSeparate");
|
||||
_glesApi.stencilOpSeparate = (GlesStencilOpSeparateFn)SDL_GL_GetProcAddress("glStencilOpSeparate");
|
||||
_glesApi.texParameteri = (GlesTexParameteriFn)SDL_GL_GetProcAddress("glTexParameteri");
|
||||
_glesApi.texStorage2D = (GlesTexStorage2DFn)SDL_GL_GetProcAddress("glTexStorage2D");
|
||||
_glesApi.texStorage3D = (GlesTexStorage3DFn)SDL_GL_GetProcAddress("glTexStorage3D");
|
||||
_glesApi.texSubImage2D = (GlesTexSubImage2DFn)SDL_GL_GetProcAddress("glTexSubImage2D");
|
||||
_glesApi.texSubImage3D = (GlesTexSubImage3DFn)SDL_GL_GetProcAddress("glTexSubImage3D");
|
||||
_glesApi.uniformBlockBinding = (GlesUniformBlockBindingFn)SDL_GL_GetProcAddress("glUniformBlockBinding");
|
||||
_glesApi.useProgram = (GlesUseProgramFn)SDL_GL_GetProcAddress("glUseProgram");
|
||||
_glesApi.validateProgram = (GlesValidateProgramFn)SDL_GL_GetProcAddress("glValidateProgram");
|
||||
_glesApi.vertexAttribIPointer = (GlesVertexAttribIPointerFn)SDL_GL_GetProcAddress("glVertexAttribIPointer");
|
||||
_glesApi.vertexAttribPointer = (GlesVertexAttribPointerFn)SDL_GL_GetProcAddress("glVertexAttribPointer");
|
||||
_glesApi.viewport = (GlesViewportFn)SDL_GL_GetProcAddress("glViewport");
|
||||
|
||||
{
|
||||
const void *const *slot = (const void *const *)&_glesApi;
|
||||
const char *const names[] = {
|
||||
"glActiveTexture",
|
||||
"glAttachShader",
|
||||
"glBindBuffer",
|
||||
"glBindBufferBase",
|
||||
"glBindBufferRange",
|
||||
"glBindFramebuffer",
|
||||
"glBindRenderbuffer",
|
||||
"glBindSampler",
|
||||
"glBindTexture",
|
||||
"glBindVertexArray",
|
||||
"glBlendEquationSeparate",
|
||||
"glBlendFuncSeparate",
|
||||
"glBlitFramebuffer",
|
||||
"glBufferData",
|
||||
"glBufferSubData",
|
||||
"glCheckFramebufferStatus",
|
||||
"glClear",
|
||||
"glClearBufferfv",
|
||||
"glClearDepthf",
|
||||
"glClearStencil",
|
||||
"glColorMask",
|
||||
"glCompileShader",
|
||||
"glCopyTexSubImage2D",
|
||||
"glCreateProgram",
|
||||
"glCreateShader",
|
||||
"glCullFace",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteFramebuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteRenderbuffers",
|
||||
"glDeleteSamplers",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
"glDepthFunc",
|
||||
"glDepthMask",
|
||||
"glDisable",
|
||||
"glDrawArraysInstanced",
|
||||
"glDrawBuffers",
|
||||
"glDrawElementsInstanced",
|
||||
"glEnable",
|
||||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glFramebufferRenderbuffer",
|
||||
"glFramebufferTexture2D",
|
||||
"glFramebufferTextureLayer",
|
||||
"glFrontFace",
|
||||
"glGenBuffers",
|
||||
"glGenFramebuffers",
|
||||
"glGenRenderbuffers",
|
||||
"glGenSamplers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGenerateMipmap",
|
||||
"glGetError",
|
||||
"glGetIntegerv",
|
||||
"glGetInternalformativ",
|
||||
"glGetProgramInfoLog",
|
||||
"glGetProgramiv",
|
||||
"glGetShaderInfoLog",
|
||||
"glGetShaderiv",
|
||||
"glGetString",
|
||||
"glGetUniformBlockIndex",
|
||||
"glLinkProgram",
|
||||
"glPixelStorei",
|
||||
"glPolygonOffset",
|
||||
"glReadBuffer",
|
||||
"glRenderbufferStorageMultisample",
|
||||
"glGetFloatv",
|
||||
"glGetUniformLocation",
|
||||
"glUniform1i",
|
||||
"glSamplerParameterf",
|
||||
"glSamplerParameteri",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glStencilFuncSeparate",
|
||||
"glStencilMask",
|
||||
"glStencilMaskSeparate",
|
||||
"glStencilOpSeparate",
|
||||
"glTexParameteri",
|
||||
"glTexStorage2D",
|
||||
"glTexStorage3D",
|
||||
"glTexSubImage2D",
|
||||
"glTexSubImage3D",
|
||||
"glUniformBlockBinding",
|
||||
"glUseProgram",
|
||||
"glValidateProgram",
|
||||
"glVertexAttribIPointer",
|
||||
"glVertexAttribPointer",
|
||||
"glViewport",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
||||
if (slot[i] == NULL) {
|
||||
utilTrace("Gles: %s is missing from this driver", names[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
78
src/renderGpu.c
Normal file
78
src/renderGpu.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
*
|
||||
* Singe 3
|
||||
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// The SDL_GPU backend: a table, not an implementation.
|
||||
//
|
||||
// Every entry in RenderBackendT carries SDL_GPU's own signature, so this backend is SDL's functions
|
||||
// taken by address. Nothing is forwarded by hand, so there is no wrapper here to fall out of step
|
||||
// with the header and nothing to get wrong. renderGles.c is where the work is.
|
||||
|
||||
#include "render.h"
|
||||
|
||||
|
||||
const RenderBackendT renderGpuBackend = {
|
||||
.acquireCommandBuffer = SDL_AcquireGPUCommandBuffer,
|
||||
.beginCopyPass = SDL_BeginGPUCopyPass,
|
||||
.beginRenderPass = SDL_BeginGPURenderPass,
|
||||
.bindFragmentSamplers = SDL_BindGPUFragmentSamplers,
|
||||
.bindGraphicsPipeline = SDL_BindGPUGraphicsPipeline,
|
||||
.bindIndexBuffer = SDL_BindGPUIndexBuffer,
|
||||
.bindVertexBuffers = SDL_BindGPUVertexBuffers,
|
||||
.bindVertexStorageBuffers = SDL_BindGPUVertexStorageBuffers,
|
||||
.blitTexture = SDL_BlitGPUTexture,
|
||||
.cancelCommandBuffer = SDL_CancelGPUCommandBuffer,
|
||||
.copyTextureToTexture = SDL_CopyGPUTextureToTexture,
|
||||
.createBuffer = SDL_CreateGPUBuffer,
|
||||
.createDevice = SDL_CreateGPUDevice,
|
||||
.createGraphicsPipeline = SDL_CreateGPUGraphicsPipeline,
|
||||
.createSampler = SDL_CreateGPUSampler,
|
||||
.createShader = SDL_CreateGPUShader,
|
||||
.createTexture = SDL_CreateGPUTexture,
|
||||
.createTransferBuffer = SDL_CreateGPUTransferBuffer,
|
||||
.destroyDevice = SDL_DestroyGPUDevice,
|
||||
.drawIndexedPrimitives = SDL_DrawGPUIndexedPrimitives,
|
||||
.drawPrimitives = SDL_DrawGPUPrimitives,
|
||||
.endCopyPass = SDL_EndGPUCopyPass,
|
||||
.endRenderPass = SDL_EndGPURenderPass,
|
||||
.generateMipmapsForTexture = SDL_GenerateMipmapsForGPUTexture,
|
||||
.getDeviceDriver = SDL_GetGPUDeviceDriver,
|
||||
.getShaderFormats = SDL_GetGPUShaderFormats,
|
||||
.getSwapchainTextureFormat = SDL_GetGPUSwapchainTextureFormat,
|
||||
.getTextureFormatFromPixelFormat = SDL_GetGPUTextureFormatFromPixelFormat,
|
||||
.mapTransferBuffer = SDL_MapGPUTransferBuffer,
|
||||
.pushFragmentUniformData = SDL_PushGPUFragmentUniformData,
|
||||
.pushVertexUniformData = SDL_PushGPUVertexUniformData,
|
||||
.releaseBuffer = SDL_ReleaseGPUBuffer,
|
||||
.releaseGraphicsPipeline = SDL_ReleaseGPUGraphicsPipeline,
|
||||
.releaseSampler = SDL_ReleaseGPUSampler,
|
||||
.releaseShader = SDL_ReleaseGPUShader,
|
||||
.releaseTexture = SDL_ReleaseGPUTexture,
|
||||
.releaseTransferBuffer = SDL_ReleaseGPUTransferBuffer,
|
||||
.setScissor = SDL_SetGPUScissor,
|
||||
.setStencilReference = SDL_SetGPUStencilReference,
|
||||
.submitCommandBuffer = SDL_SubmitGPUCommandBuffer,
|
||||
.textureSupportsFormat = SDL_GPUTextureSupportsFormat,
|
||||
.textureSupportsSampleCount = SDL_GPUTextureSupportsSampleCount,
|
||||
.unmapTransferBuffer = SDL_UnmapGPUTransferBuffer,
|
||||
.uploadToBuffer = SDL_UploadToGPUBuffer,
|
||||
.uploadToTexture = SDL_UploadToGPUTexture,
|
||||
};
|
||||
387
src/scene.c
387
src/scene.c
File diff suppressed because it is too large
Load diff
|
|
@ -71,6 +71,7 @@ LSEC_API int luaopen_ssl_config(lua_State *L);
|
|||
#include "vfs.h"
|
||||
#include "persist.h"
|
||||
#include "scene.h"
|
||||
#include "render.h"
|
||||
#include "scheduler.h"
|
||||
#include "stats.h"
|
||||
#include "hdr.h"
|
||||
|
|
@ -12646,7 +12647,7 @@ static int32_t apiSingeGetSystemInfo(lua_State *L) {
|
|||
lua_pushstring(L, (os != NULL) ? os : ""); lua_setfield(L, -2, "os");
|
||||
lua_pushstring(L, (cpu != NULL) ? cpu : ""); lua_setfield(L, -2, "cpu");
|
||||
lua_pushstring(L, SDL_GetRendererName(_global.renderer)); lua_setfield(L, -2, "renderer");
|
||||
lua_pushstring(L, (_global.device != NULL) ? SDL_GetGPUDeviceDriver(_global.device) : "none (3D unavailable)"); lua_setfield(L, -2, "gpu");
|
||||
lua_pushstring(L, (_global.device != NULL) ? rgpuGetDeviceDriver(_global.device) : "none (3D unavailable)"); lua_setfield(L, -2, "gpu");
|
||||
lua_pushstring(L, videoGetDecoderDescription()); lua_setfield(L, -2, "decoder");
|
||||
lua_pushstring(L, (audio != NULL) ? audio : ""); lua_setfield(L, -2, "audio");
|
||||
lua_pushstring(L, midiSoundfont()); lua_setfield(L, -2, "soundFont");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue