|
@@ -89,10 +89,10 @@
|
|
|
sg_setup(const sg_desc*)
|
|
|
|
|
|
Depending on the selected 3D backend, sokol-gfx requires some
|
|
|
- information, like a device pointer, default swapchain pixel formats
|
|
|
- and so on. If you are using sokol_app.h for the window system
|
|
|
- glue, you can use a helper function provided in the sokol_glue.h
|
|
|
- header:
|
|
|
+ information about its runtime environment, like a GPU device pointer,
|
|
|
+ default swapchain pixel formats and so on. If you are using sokol_app.h
|
|
|
+ for the window system glue, you can use a helper function provided in
|
|
|
+ the sokol_glue.h header:
|
|
|
|
|
|
#include "sokol_gfx.h"
|
|
|
#include "sokol_app.h"
|
|
@@ -134,8 +134,8 @@
|
|
|
|
|
|
...where .action is an sg_pass_action struct containing actions to be performed
|
|
|
at the start and end of a render pass (such as clearing the render surfaces to
|
|
|
- a specific color), and .swapchain is an sg_swapchain
|
|
|
- struct all the required information to render into the swapchain's surfaces.
|
|
|
+ a specific color), and .swapchain is an sg_swapchain struct with all the required
|
|
|
+ information to render into the swapchain's surfaces.
|
|
|
|
|
|
To start an 'offscreen render pass' into sokol-gfx image objects, an sg_attachment
|
|
|
object handle is required instead of an sg_swapchain struct. An offscreen
|
|
@@ -238,11 +238,11 @@
|
|
|
sg_update_image(sg_image img, const sg_image_data* data)
|
|
|
|
|
|
Buffers and images to be updated must have been created with
|
|
|
- SG_USAGE_DYNAMIC or SG_USAGE_STREAM
|
|
|
+ SG_USAGE_DYNAMIC or SG_USAGE_STREAM.
|
|
|
|
|
|
Only one update per frame is allowed for buffer and image resources when
|
|
|
using the sg_update_*() functions. The rationale is to have a simple
|
|
|
- countermeasure to avoid the CPU scribbling over data the GPU is currently
|
|
|
+ protection from the CPU scribbling over data the GPU is currently
|
|
|
using, or the CPU having to wait for the GPU
|
|
|
|
|
|
Buffer and image updates can be partial, as long as a rendering
|
|
@@ -416,6 +416,7 @@
|
|
|
per uniform update (this worst-case alignment is 256 bytes)
|
|
|
- the max size of all dynamic resource updates (sg_update_buffer,
|
|
|
sg_append_buffer and sg_update_image) per frame
|
|
|
+ - the max number of compute-dispatch calls in a compute pass
|
|
|
Not all of those limit values are used by all backends, but it is
|
|
|
good practice to provide them none-the-less.
|
|
|
|
|
@@ -827,11 +828,15 @@
|
|
|
- an entry function name (only on D3D11 or Metal, but not OpenGL)
|
|
|
- on D3D11 only, a compilation target (default is "vs_4_0" and "ps_4_0")
|
|
|
|
|
|
- - Depending on backend, information about the input vertex attributes used by the
|
|
|
- vertex shader:
|
|
|
- - Metal: no information needed since vertex attributes are always bound
|
|
|
+ - Information about the input vertex attributes used by the vertex shader,
|
|
|
+ most of that backend-specific:
|
|
|
+ - An optional 'base type' (float, signed-/unsigned-int) for each vertex
|
|
|
+ attribute. When provided, this used by the validation layer to check
|
|
|
+ that the CPU-side input vertex format is compatible with the input
|
|
|
+ vertex declaration of the vertex shader.
|
|
|
+ - Metal: no location information needed since vertex attributes are always bound
|
|
|
by their attribute location defined in the shader via '[[attribute(N)]]'
|
|
|
- - WebGPU: no information needed since vertex attributes are always
|
|
|
+ - WebGPU: no location information needed since vertex attributes are always
|
|
|
bound by their attribute location defined in the shader via `@location(N)`
|
|
|
- GLSL: vertex attribute names can be optionally provided, in that case their
|
|
|
location will be looked up by name, otherwise, the vertex attribute location
|
|
@@ -1016,6 +1021,46 @@
|
|
|
sg_shader_desc struct.
|
|
|
|
|
|
|
|
|
+ ON VERTEX FORMATS
|
|
|
+ =================
|
|
|
+ Sokol-gfx implements the same strict mapping rules from CPU-side
|
|
|
+ vertex component formats to GPU-side vertex input data types:
|
|
|
+
|
|
|
+ - float and packed normalized CPU-side formats must be used as
|
|
|
+ floating point base type in the vertex shader
|
|
|
+ - packed signed-integer CPU-side formats must be used as signed
|
|
|
+ integer base type in the vertex shader
|
|
|
+ - packed unsigned-integer CPU-side formats must be used as unsigned
|
|
|
+ integer base type in the vertex shader
|
|
|
+
|
|
|
+ These mapping rules are enforced by the sokol-gfx validation layer,
|
|
|
+ but only when sufficient reflection information is provided in
|
|
|
+ `sg_shader_desc.attrs[].base_type`. This is the case when sokol-shdc
|
|
|
+ is used, otherwise the default base_type will be SG_SHADERATTRBASETYPE_UNDEFINED
|
|
|
+ which causes the sokol-gfx validation check to be skipped (of course you
|
|
|
+ can also provide the per-attribute base type information manually when
|
|
|
+ not using sokol-shdc).
|
|
|
+
|
|
|
+ The detailed mapping rules from SG_VERTEXFORMAT_* to GLSL data types
|
|
|
+ are as follows:
|
|
|
+
|
|
|
+ - FLOAT[*] => float, vec*
|
|
|
+ - BYTE4N => vec* (scaled to -1.0 .. +1.0)
|
|
|
+ - UBYTE4N => vec* (scaled to 0.0 .. +1.0)
|
|
|
+ - SHORT[*]N => vec* (scaled to -1.0 .. +1.0)
|
|
|
+ - USHORT[*]N => vec* (scaled to 0.0 .. +1.0)
|
|
|
+ - INT[*] => int, ivec*
|
|
|
+ - UINT[*] => uint, uvec*
|
|
|
+ - BYTE4 => int*
|
|
|
+ - UBYTE4 => uint*
|
|
|
+ - SHORT[*] => int*
|
|
|
+ - USHORT[*] => uint*
|
|
|
+
|
|
|
+ NOTE that sokol-gfx only provides vertex formats with sizes of a multiple
|
|
|
+ of 4 (e.g. BYTE4N but not BYTE2N). This is because vertex components must
|
|
|
+ be 4-byte aligned anyway.
|
|
|
+
|
|
|
+
|
|
|
UNIFORM DATA LAYOUT:
|
|
|
====================
|
|
|
NOTE: if you use the sokol-shdc shader compiler tool, you don't need to worry
|
|
@@ -1124,6 +1169,7 @@
|
|
|
The by far easiest way to tackle the common uniform block layout problem is
|
|
|
to use the sokol-shdc shader cross-compiler tool!
|
|
|
|
|
|
+
|
|
|
ON STORAGE BUFFERS
|
|
|
==================
|
|
|
The two main purpose of storage buffers are:
|
|
@@ -1287,6 +1333,7 @@
|
|
|
|
|
|
`@group(1) @binding(0..127)
|
|
|
|
|
|
+
|
|
|
TRACE HOOKS:
|
|
|
============
|
|
|
sokol_gfx.h optionally allows to install "trace hook" callbacks for
|
|
@@ -1317,54 +1364,6 @@
|
|
|
debugging UI for sokol_gfx.h on top of Dear ImGui.
|
|
|
|
|
|
|
|
|
- A NOTE ON PORTABLE PACKED VERTEX FORMATS:
|
|
|
- =========================================
|
|
|
- There are two things to consider when using packed
|
|
|
- vertex formats like UBYTE4, SHORT2, etc which need to work
|
|
|
- across all backends:
|
|
|
-
|
|
|
- - D3D11 can only convert *normalized* vertex formats to
|
|
|
- floating point during vertex fetch, normalized formats
|
|
|
- have a trailing 'N', and are "normalized" to a range
|
|
|
- -1.0..+1.0 (for the signed formats) or 0.0..1.0 (for the
|
|
|
- unsigned formats):
|
|
|
-
|
|
|
- - SG_VERTEXFORMAT_BYTE4N
|
|
|
- - SG_VERTEXFORMAT_UBYTE4N
|
|
|
- - SG_VERTEXFORMAT_SHORT2N
|
|
|
- - SG_VERTEXFORMAT_USHORT2N
|
|
|
- - SG_VERTEXFORMAT_SHORT4N
|
|
|
- - SG_VERTEXFORMAT_USHORT4N
|
|
|
-
|
|
|
- D3D11 will not convert *non-normalized* vertex formats to floating point
|
|
|
- vertex shader inputs, those can only be uses with the *ivecn* vertex shader
|
|
|
- input types when D3D11 is used as backend (GL and Metal can use both formats)
|
|
|
-
|
|
|
- - SG_VERTEXFORMAT_BYTE4,
|
|
|
- - SG_VERTEXFORMAT_UBYTE4
|
|
|
- - SG_VERTEXFORMAT_SHORT2
|
|
|
- - SG_VERTEXFORMAT_SHORT4
|
|
|
-
|
|
|
- For a vertex input layout which works on all platforms, only use the following
|
|
|
- vertex formats, and if needed "expand" the normalized vertex shader
|
|
|
- inputs in the vertex shader by multiplying with 127.0, 255.0, 32767.0 or
|
|
|
- 65535.0:
|
|
|
-
|
|
|
- - SG_VERTEXFORMAT_FLOAT,
|
|
|
- - SG_VERTEXFORMAT_FLOAT2,
|
|
|
- - SG_VERTEXFORMAT_FLOAT3,
|
|
|
- - SG_VERTEXFORMAT_FLOAT4,
|
|
|
- - SG_VERTEXFORMAT_BYTE4N,
|
|
|
- - SG_VERTEXFORMAT_UBYTE4N,
|
|
|
- - SG_VERTEXFORMAT_SHORT2N,
|
|
|
- - SG_VERTEXFORMAT_USHORT2N
|
|
|
- - SG_VERTEXFORMAT_SHORT4N,
|
|
|
- - SG_VERTEXFORMAT_USHORT4N
|
|
|
- - SG_VERTEXFORMAT_UINT10_N2
|
|
|
- - SG_VERTEXFORMAT_HALF2
|
|
|
- - SG_VERTEXFORMAT_HALF4
|
|
|
-
|
|
|
-
|
|
|
MEMORY ALLOCATION OVERRIDE
|
|
|
==========================
|
|
|
You can override the memory allocation functions at initialization time
|
|
@@ -1659,9 +1658,9 @@
|
|
|
must be used:
|
|
|
|
|
|
All uniform block structs must use `@group(0)` and bindings in the
|
|
|
- range 0..127:
|
|
|
+ range 0..15
|
|
|
|
|
|
- @group(0) @binding(0..7)
|
|
|
+ @group(0) @binding(0..15)
|
|
|
|
|
|
All textures, samplers and storage buffers must use `@group(1)` and
|
|
|
bindings must be in the range 0..127:
|
|
@@ -1712,17 +1711,14 @@
|
|
|
workaround sokol_gfx.h will clip incoming viewport rectangles against
|
|
|
the framebuffer, but this will distort the clipspace-to-screenspace mapping.
|
|
|
There's no proper way to handle this inside sokol_gfx.h, this must be fixed
|
|
|
- in a future WebGPU update.
|
|
|
+ in a future WebGPU update (see: https://github.com/gpuweb/gpuweb/issues/373
|
|
|
+ and https://github.com/gpuweb/gpuweb/pull/5025)
|
|
|
|
|
|
- The sokol shader compiler generally adds `diagnostic(off, derivative_uniformity);`
|
|
|
into the WGSL output. Currently only the Chrome WebGPU implementation seems
|
|
|
to recognize this.
|
|
|
|
|
|
- - The vertex format SG_VERTEXFORMAT_UINT10_N2 is currently not supported because
|
|
|
- WebGPU lacks a matching vertex format (this is currently being worked on though,
|
|
|
- as soon as the vertex format shows up in webgpu.h, sokol_gfx.h will add support.
|
|
|
-
|
|
|
- - Likewise, the following sokol-gfx vertex formats are not supported in WebGPU:
|
|
|
+ - Likewise, the following sokol-gfx pixel formats are not supported in WebGPU:
|
|
|
R16, R16SN, RG16, RG16SN, RGBA16, RGBA16SN.
|
|
|
Unlike unsupported vertex formats, unsupported pixel formats can be queried
|
|
|
in cross-backend code via sg_query_pixel_format() though.
|
|
@@ -2082,7 +2078,7 @@ typedef enum sg_resource_state {
|
|
|
and images:
|
|
|
|
|
|
SG_USAGE_IMMUTABLE: the resource will never be updated with
|
|
|
- new data, instead the content of the
|
|
|
+ new (CPU-side) data, instead the content of the
|
|
|
resource must be provided on creation
|
|
|
SG_USAGE_DYNAMIC: the resource will be updated infrequently
|
|
|
with new data (this could range from "once
|
|
@@ -2336,7 +2332,11 @@ typedef enum sg_border_color {
|
|
|
sg_vertex_format
|
|
|
|
|
|
The data type of a vertex component. This is used to describe
|
|
|
- the layout of vertex data when creating a pipeline object.
|
|
|
+ the layout of input vertex data when creating a pipeline object.
|
|
|
+
|
|
|
+ NOTE that specific mapping rules exist from the CPU-side vertex
|
|
|
+ formats to the vertex attribute base type in the vertex shader code
|
|
|
+ (see doc header section 'ON VERTEX FORMATS').
|
|
|
*/
|
|
|
typedef enum sg_vertex_format {
|
|
|
SG_VERTEXFORMAT_INVALID,
|
|
@@ -2344,15 +2344,25 @@ typedef enum sg_vertex_format {
|
|
|
SG_VERTEXFORMAT_FLOAT2,
|
|
|
SG_VERTEXFORMAT_FLOAT3,
|
|
|
SG_VERTEXFORMAT_FLOAT4,
|
|
|
+ SG_VERTEXFORMAT_INT,
|
|
|
+ SG_VERTEXFORMAT_INT2,
|
|
|
+ SG_VERTEXFORMAT_INT3,
|
|
|
+ SG_VERTEXFORMAT_INT4,
|
|
|
+ SG_VERTEXFORMAT_UINT,
|
|
|
+ SG_VERTEXFORMAT_UINT2,
|
|
|
+ SG_VERTEXFORMAT_UINT3,
|
|
|
+ SG_VERTEXFORMAT_UINT4,
|
|
|
SG_VERTEXFORMAT_BYTE4,
|
|
|
SG_VERTEXFORMAT_BYTE4N,
|
|
|
SG_VERTEXFORMAT_UBYTE4,
|
|
|
SG_VERTEXFORMAT_UBYTE4N,
|
|
|
SG_VERTEXFORMAT_SHORT2,
|
|
|
SG_VERTEXFORMAT_SHORT2N,
|
|
|
+ SG_VERTEXFORMAT_USHORT2,
|
|
|
SG_VERTEXFORMAT_USHORT2N,
|
|
|
SG_VERTEXFORMAT_SHORT4,
|
|
|
SG_VERTEXFORMAT_SHORT4N,
|
|
|
+ SG_VERTEXFORMAT_USHORT4,
|
|
|
SG_VERTEXFORMAT_USHORT4N,
|
|
|
SG_VERTEXFORMAT_UINT10_N2,
|
|
|
SG_VERTEXFORMAT_HALF2,
|
|
@@ -3193,8 +3203,12 @@ typedef struct sg_sampler_desc {
|
|
|
(the default is "cs_5_0")
|
|
|
|
|
|
- vertex attributes required by some backends (not for compute shaders):
|
|
|
- - for the GL backend: optional vertex attribute names
|
|
|
- used for name lookup
|
|
|
+ - the vertex attribute base type (undefined, float, signed int, unsigned int),
|
|
|
+ this information is only used in the validation layer to check that the
|
|
|
+ pipeline object vertex formats are compatible with the input vertex attribute
|
|
|
+ type used in the vertex shader. NOTE that the default base type
|
|
|
+ 'undefined' skips the validation layer check.
|
|
|
+ - for the GL backend: optional vertex attribute names used for name lookup
|
|
|
- for the D3D11 backend: semantic names and indices
|
|
|
|
|
|
- only for compute shaders on the Metal backend:
|
|
@@ -3294,6 +3308,7 @@ typedef enum sg_shader_stage {
|
|
|
SG_SHADERSTAGE_VERTEX,
|
|
|
SG_SHADERSTAGE_FRAGMENT,
|
|
|
SG_SHADERSTAGE_COMPUTE,
|
|
|
+ _SG_SHADERSTAGE_FORCE_U32 = 0x7FFFFFFF,
|
|
|
} sg_shader_stage;
|
|
|
|
|
|
typedef struct sg_shader_function {
|
|
@@ -3303,7 +3318,16 @@ typedef struct sg_shader_function {
|
|
|
const char* d3d11_target; // default: "vs_4_0" or "ps_4_0"
|
|
|
} sg_shader_function;
|
|
|
|
|
|
+typedef enum sg_shader_attr_base_type {
|
|
|
+ SG_SHADERATTRBASETYPE_UNDEFINED,
|
|
|
+ SG_SHADERATTRBASETYPE_FLOAT,
|
|
|
+ SG_SHADERATTRBASETYPE_SINT,
|
|
|
+ SG_SHADERATTRBASETYPE_UINT,
|
|
|
+ _SG_SHADERATTRBASETYPE_FORCE_U32 = 0x7FFFFFFF,
|
|
|
+} sg_shader_attr_base_type;
|
|
|
+
|
|
|
typedef struct sg_shader_vertex_attr {
|
|
|
+ sg_shader_attr_base_type base_type; // default: UNDEFINED (disables validation)
|
|
|
const char* glsl_name; // [optional] GLSL attribute name
|
|
|
const char* hlsl_sem_name; // HLSL semantic name
|
|
|
uint8_t hlsl_sem_index; // HLSL semantic index
|
|
@@ -4101,6 +4125,7 @@ typedef struct sg_frame_stats {
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_COMPUTE_SHADER_EXPECTED, "sg_pipeline_desc.shader must be a compute shader") \
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_NO_COMPUTE_SHADER_EXPECTED, "sg_pipeline_desc.compute is false, but shader is a compute shader") \
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_NO_CONT_ATTRS, "sg_pipeline_desc.layout.attrs is not continuous") \
|
|
|
+ _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH, "sg_pipeline_desc.layout.attrs[].format is incompatble with sg_shader_desc.attrs[].base_type") \
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4, "sg_pipeline_desc.layout.buffers[].stride must be multiple of 4") \
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_ATTR_SEMANTICS, "D3D11 missing vertex attribute semantics in shader") \
|
|
|
_SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_SHADER_READONLY_STORAGEBUFFERS, "sg_pipeline_desc.shader: only readonly storage buffer bindings allowed in render pipelines") \
|
|
@@ -4469,7 +4494,7 @@ SOKOL_GFX_API_DECL int sg_append_buffer(sg_buffer buf, const sg_range* data);
|
|
|
SOKOL_GFX_API_DECL bool sg_query_buffer_overflow(sg_buffer buf);
|
|
|
SOKOL_GFX_API_DECL bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size);
|
|
|
|
|
|
-// rendering functions
|
|
|
+// render and compute functions
|
|
|
SOKOL_GFX_API_DECL void sg_begin_pass(const sg_pass* pass);
|
|
|
SOKOL_GFX_API_DECL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);
|
|
|
SOKOL_GFX_API_DECL void sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left);
|
|
@@ -5507,6 +5532,10 @@ _SOKOL_PRIVATE void _sg_sampler_common_init(_sg_sampler_common_t* cmn, const sg_
|
|
|
cmn->max_anisotropy = desc->max_anisotropy;
|
|
|
}
|
|
|
|
|
|
+typedef struct {
|
|
|
+ sg_shader_attr_base_type base_type;
|
|
|
+} _sg_shader_attr_t;
|
|
|
+
|
|
|
typedef struct {
|
|
|
sg_shader_stage stage;
|
|
|
uint32_t size;
|
|
@@ -5539,6 +5568,7 @@ typedef struct {
|
|
|
typedef struct {
|
|
|
uint32_t required_bindings_and_uniforms;
|
|
|
bool is_compute;
|
|
|
+ _sg_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
|
|
|
_sg_shader_uniform_block_t uniform_blocks[SG_MAX_UNIFORMBLOCK_BINDSLOTS];
|
|
|
_sg_shader_storage_buffer_t storage_buffers[SG_MAX_STORAGEBUFFER_BINDSLOTS];
|
|
|
_sg_shader_image_t images[SG_MAX_IMAGE_BINDSLOTS];
|
|
@@ -5548,6 +5578,9 @@ typedef struct {
|
|
|
|
|
|
_SOKOL_PRIVATE void _sg_shader_common_init(_sg_shader_common_t* cmn, const sg_shader_desc* desc) {
|
|
|
cmn->is_compute = desc->compute_func.source || desc->compute_func.bytecode.ptr;
|
|
|
+ for (size_t i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
|
|
|
+ cmn->attrs[i].base_type = desc->attrs[i].base_type;
|
|
|
+ }
|
|
|
for (size_t i = 0; i < SG_MAX_UNIFORMBLOCK_BINDSLOTS; i++) {
|
|
|
const sg_shader_uniform_block* src = &desc->uniform_blocks[i];
|
|
|
_sg_shader_uniform_block_t* dst = &cmn->uniform_blocks[i];
|
|
@@ -5814,6 +5847,7 @@ typedef struct {
|
|
|
uint8_t normalized;
|
|
|
int offset;
|
|
|
GLenum type;
|
|
|
+ sg_shader_attr_base_type base_type;
|
|
|
} _sg_gl_attr_t;
|
|
|
|
|
|
typedef struct _sg_pipeline_s {
|
|
@@ -6608,15 +6642,25 @@ _SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_FLOAT2: return 8;
|
|
|
case SG_VERTEXFORMAT_FLOAT3: return 12;
|
|
|
case SG_VERTEXFORMAT_FLOAT4: return 16;
|
|
|
+ case SG_VERTEXFORMAT_INT: return 4;
|
|
|
+ case SG_VERTEXFORMAT_INT2: return 8;
|
|
|
+ case SG_VERTEXFORMAT_INT3: return 12;
|
|
|
+ case SG_VERTEXFORMAT_INT4: return 16;
|
|
|
+ case SG_VERTEXFORMAT_UINT: return 4;
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return 8;
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return 12;
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return 16;
|
|
|
case SG_VERTEXFORMAT_BYTE4: return 4;
|
|
|
case SG_VERTEXFORMAT_BYTE4N: return 4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4: return 4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4N: return 4;
|
|
|
case SG_VERTEXFORMAT_SHORT2: return 4;
|
|
|
case SG_VERTEXFORMAT_SHORT2N: return 4;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return 4;
|
|
|
case SG_VERTEXFORMAT_USHORT2N: return 4;
|
|
|
case SG_VERTEXFORMAT_SHORT4: return 8;
|
|
|
case SG_VERTEXFORMAT_SHORT4N: return 8;
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return 8;
|
|
|
case SG_VERTEXFORMAT_USHORT4N: return 8;
|
|
|
case SG_VERTEXFORMAT_UINT10_N2: return 4;
|
|
|
case SG_VERTEXFORMAT_HALF2: return 4;
|
|
@@ -6628,6 +6672,91 @@ _SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+_SOKOL_PRIVATE const char* _sg_vertexformat_to_string(sg_vertex_format fmt) {
|
|
|
+ switch (fmt) {
|
|
|
+ case SG_VERTEXFORMAT_FLOAT: return "FLOAT";
|
|
|
+ case SG_VERTEXFORMAT_FLOAT2: return "FLOAT2";
|
|
|
+ case SG_VERTEXFORMAT_FLOAT3: return "FLOAT3";
|
|
|
+ case SG_VERTEXFORMAT_FLOAT4: return "FLOAT4";
|
|
|
+ case SG_VERTEXFORMAT_INT: return "INT";
|
|
|
+ case SG_VERTEXFORMAT_INT2: return "INT2";
|
|
|
+ case SG_VERTEXFORMAT_INT3: return "INT3";
|
|
|
+ case SG_VERTEXFORMAT_INT4: return "INT4";
|
|
|
+ case SG_VERTEXFORMAT_UINT: return "UINT";
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return "UINT2";
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return "UINT3";
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return "UINT4";
|
|
|
+ case SG_VERTEXFORMAT_BYTE4: return "BYTE4";
|
|
|
+ case SG_VERTEXFORMAT_BYTE4N: return "BYTE4N";
|
|
|
+ case SG_VERTEXFORMAT_UBYTE4: return "UBYTE4";
|
|
|
+ case SG_VERTEXFORMAT_UBYTE4N: return "UBYTE4N";
|
|
|
+ case SG_VERTEXFORMAT_SHORT2: return "SHORT4";
|
|
|
+ case SG_VERTEXFORMAT_SHORT2N: return "SHORT2N";
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return "USHORT2";
|
|
|
+ case SG_VERTEXFORMAT_USHORT2N: return "USHORT2N";
|
|
|
+ case SG_VERTEXFORMAT_SHORT4: return "SHORT4";
|
|
|
+ case SG_VERTEXFORMAT_SHORT4N: return "SHORT4N";
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return "USHORT4";
|
|
|
+ case SG_VERTEXFORMAT_USHORT4N: return "USHORT4N";
|
|
|
+ case SG_VERTEXFORMAT_UINT10_N2: return "UINT10_N2";
|
|
|
+ case SG_VERTEXFORMAT_HALF2: return "HALF2";
|
|
|
+ case SG_VERTEXFORMAT_HALF4: return "HALF4";
|
|
|
+ default:
|
|
|
+ SOKOL_UNREACHABLE;
|
|
|
+ return "INVALID";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+_SOKOL_PRIVATE const char* _sg_shaderattrbasetype_to_string(sg_shader_attr_base_type b) {
|
|
|
+ switch (b) {
|
|
|
+ case SG_SHADERATTRBASETYPE_UNDEFINED: return "UNDEFINED";
|
|
|
+ case SG_SHADERATTRBASETYPE_FLOAT: return "FLOAT";
|
|
|
+ case SG_SHADERATTRBASETYPE_SINT: return "SINT";
|
|
|
+ case SG_SHADERATTRBASETYPE_UINT: return "UINT";
|
|
|
+ default:
|
|
|
+ SOKOL_UNREACHABLE;
|
|
|
+ return "INVALID";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+_SOKOL_PRIVATE sg_shader_attr_base_type _sg_vertexformat_basetype(sg_vertex_format fmt) {
|
|
|
+ switch (fmt) {
|
|
|
+ case SG_VERTEXFORMAT_FLOAT:
|
|
|
+ case SG_VERTEXFORMAT_FLOAT2:
|
|
|
+ case SG_VERTEXFORMAT_FLOAT3:
|
|
|
+ case SG_VERTEXFORMAT_FLOAT4:
|
|
|
+ case SG_VERTEXFORMAT_HALF2:
|
|
|
+ case SG_VERTEXFORMAT_HALF4:
|
|
|
+ case SG_VERTEXFORMAT_BYTE4N:
|
|
|
+ case SG_VERTEXFORMAT_UBYTE4N:
|
|
|
+ case SG_VERTEXFORMAT_SHORT2N:
|
|
|
+ case SG_VERTEXFORMAT_USHORT2N:
|
|
|
+ case SG_VERTEXFORMAT_SHORT4N:
|
|
|
+ case SG_VERTEXFORMAT_USHORT4N:
|
|
|
+ case SG_VERTEXFORMAT_UINT10_N2:
|
|
|
+ return SG_SHADERATTRBASETYPE_FLOAT;
|
|
|
+ case SG_VERTEXFORMAT_INT:
|
|
|
+ case SG_VERTEXFORMAT_INT2:
|
|
|
+ case SG_VERTEXFORMAT_INT3:
|
|
|
+ case SG_VERTEXFORMAT_INT4:
|
|
|
+ case SG_VERTEXFORMAT_BYTE4:
|
|
|
+ case SG_VERTEXFORMAT_SHORT2:
|
|
|
+ case SG_VERTEXFORMAT_SHORT4:
|
|
|
+ return SG_SHADERATTRBASETYPE_SINT;
|
|
|
+ case SG_VERTEXFORMAT_UINT:
|
|
|
+ case SG_VERTEXFORMAT_UINT2:
|
|
|
+ case SG_VERTEXFORMAT_UINT3:
|
|
|
+ case SG_VERTEXFORMAT_UINT4:
|
|
|
+ case SG_VERTEXFORMAT_UBYTE4:
|
|
|
+ case SG_VERTEXFORMAT_USHORT2:
|
|
|
+ case SG_VERTEXFORMAT_USHORT4:
|
|
|
+ return SG_SHADERATTRBASETYPE_UINT;
|
|
|
+ default:
|
|
|
+ SOKOL_UNREACHABLE;
|
|
|
+ return SG_SHADERATTRBASETYPE_UNDEFINED;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
_SOKOL_PRIVATE uint32_t _sg_uniform_alignment(sg_uniform_type type, int array_count, sg_uniform_layout ub_layout) {
|
|
|
if (ub_layout == SG_UNIFORMLAYOUT_NATIVE) {
|
|
|
return 1;
|
|
@@ -7353,6 +7482,7 @@ _SOKOL_PRIVATE void _sg_dummy_update_image(_sg_image_t* img, const sg_image_data
|
|
|
_SG_XMACRO(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) \
|
|
|
_SG_XMACRO(glDrawElementsInstanced, void, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)) \
|
|
|
_SG_XMACRO(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)) \
|
|
|
+ _SG_XMACRO(glVertexAttribIPointer, void, (GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer)) \
|
|
|
_SG_XMACRO(glUniform1i, void, (GLint location, GLint v0)) \
|
|
|
_SG_XMACRO(glDisable, void, (GLenum cap)) \
|
|
|
_SG_XMACRO(glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) \
|
|
@@ -7503,15 +7633,25 @@ _SOKOL_PRIVATE GLint _sg_gl_vertexformat_size(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_FLOAT2: return 2;
|
|
|
case SG_VERTEXFORMAT_FLOAT3: return 3;
|
|
|
case SG_VERTEXFORMAT_FLOAT4: return 4;
|
|
|
+ case SG_VERTEXFORMAT_INT: return 1;
|
|
|
+ case SG_VERTEXFORMAT_INT2: return 2;
|
|
|
+ case SG_VERTEXFORMAT_INT3: return 3;
|
|
|
+ case SG_VERTEXFORMAT_INT4: return 4;
|
|
|
+ case SG_VERTEXFORMAT_UINT: return 1;
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return 2;
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return 3;
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return 4;
|
|
|
case SG_VERTEXFORMAT_BYTE4: return 4;
|
|
|
case SG_VERTEXFORMAT_BYTE4N: return 4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4: return 4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4N: return 4;
|
|
|
case SG_VERTEXFORMAT_SHORT2: return 2;
|
|
|
case SG_VERTEXFORMAT_SHORT2N: return 2;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return 2;
|
|
|
case SG_VERTEXFORMAT_USHORT2N: return 2;
|
|
|
case SG_VERTEXFORMAT_SHORT4: return 4;
|
|
|
case SG_VERTEXFORMAT_SHORT4N: return 4;
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return 4;
|
|
|
case SG_VERTEXFORMAT_USHORT4N: return 4;
|
|
|
case SG_VERTEXFORMAT_UINT10_N2: return 4;
|
|
|
case SG_VERTEXFORMAT_HALF2: return 2;
|
|
@@ -7527,6 +7667,16 @@ _SOKOL_PRIVATE GLenum _sg_gl_vertexformat_type(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_FLOAT3:
|
|
|
case SG_VERTEXFORMAT_FLOAT4:
|
|
|
return GL_FLOAT;
|
|
|
+ case SG_VERTEXFORMAT_INT:
|
|
|
+ case SG_VERTEXFORMAT_INT2:
|
|
|
+ case SG_VERTEXFORMAT_INT3:
|
|
|
+ case SG_VERTEXFORMAT_INT4:
|
|
|
+ return GL_INT;
|
|
|
+ case SG_VERTEXFORMAT_UINT:
|
|
|
+ case SG_VERTEXFORMAT_UINT2:
|
|
|
+ case SG_VERTEXFORMAT_UINT3:
|
|
|
+ case SG_VERTEXFORMAT_UINT4:
|
|
|
+ return GL_UNSIGNED_INT;
|
|
|
case SG_VERTEXFORMAT_BYTE4:
|
|
|
case SG_VERTEXFORMAT_BYTE4N:
|
|
|
return GL_BYTE;
|
|
@@ -7538,7 +7688,9 @@ _SOKOL_PRIVATE GLenum _sg_gl_vertexformat_type(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_SHORT4:
|
|
|
case SG_VERTEXFORMAT_SHORT4N:
|
|
|
return GL_SHORT;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2:
|
|
|
case SG_VERTEXFORMAT_USHORT2N:
|
|
|
+ case SG_VERTEXFORMAT_USHORT4:
|
|
|
case SG_VERTEXFORMAT_USHORT4N:
|
|
|
return GL_UNSIGNED_SHORT;
|
|
|
case SG_VERTEXFORMAT_UINT10_N2:
|
|
@@ -9201,6 +9353,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_pipeline(_sg_pipeline_t* pip, _sg
|
|
|
gl_attr->size = (uint8_t) _sg_gl_vertexformat_size(a_state->format);
|
|
|
gl_attr->type = _sg_gl_vertexformat_type(a_state->format);
|
|
|
gl_attr->normalized = _sg_gl_vertexformat_normalized(a_state->format);
|
|
|
+ gl_attr->base_type = _sg_vertexformat_basetype(a_state->format);
|
|
|
pip->cmn.vertex_buffer_layout_active[a_state->buffer_index] = true;
|
|
|
} else {
|
|
|
_SG_WARN(GL_VERTEX_ATTRIBUTE_NOT_FOUND_IN_SHADER);
|
|
@@ -9730,7 +9883,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) {
|
|
|
|
|
|
if (pip->cmn.color_count > 0) {
|
|
|
// update blend state
|
|
|
- // FIXME: separate blend state per color attachment not support, needs GL4
|
|
|
+ // FIXME: separate blend state per color attachment
|
|
|
const sg_blend_state* state_bs = &pip->gl.blend;
|
|
|
sg_blend_state* cache_bs = &_sg.gl.cache.blend;
|
|
|
if (state_bs->enabled != cache_bs->enabled) {
|
|
@@ -9944,12 +10097,17 @@ _SOKOL_PRIVATE bool _sg_gl_apply_bindings(_sg_bindings_t* bnd) {
|
|
|
(attr->size != cache_attr->gl_attr.size) ||
|
|
|
(attr->type != cache_attr->gl_attr.type) ||
|
|
|
(attr->normalized != cache_attr->gl_attr.normalized) ||
|
|
|
+ (attr->base_type != cache_attr->gl_attr.base_type) ||
|
|
|
(attr->stride != cache_attr->gl_attr.stride) ||
|
|
|
(vb_offset != cache_attr->gl_attr.offset) ||
|
|
|
(cache_attr->gl_attr.divisor != attr->divisor))
|
|
|
{
|
|
|
_sg_gl_cache_bind_buffer(GL_ARRAY_BUFFER, gl_vb);
|
|
|
- glVertexAttribPointer(attr_index, attr->size, attr->type, attr->normalized, attr->stride, (const GLvoid*)(GLintptr)vb_offset);
|
|
|
+ if (attr->base_type == SG_SHADERATTRBASETYPE_FLOAT) {
|
|
|
+ glVertexAttribPointer(attr_index, attr->size, attr->type, attr->normalized, attr->stride, (const GLvoid*)(GLintptr)vb_offset);
|
|
|
+ } else {
|
|
|
+ glVertexAttribIPointer(attr_index, attr->size, attr->type, attr->stride, (const GLvoid*)(GLintptr)vb_offset);
|
|
|
+ }
|
|
|
_sg_stats_add(gl.num_vertex_attrib_pointer, 1);
|
|
|
glVertexAttribDivisor(attr_index, (GLuint)attr->divisor);
|
|
|
_sg_stats_add(gl.num_vertex_attrib_divisor, 1);
|
|
@@ -10875,15 +11033,25 @@ _SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_vertex_format(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_FLOAT2: return DXGI_FORMAT_R32G32_FLOAT;
|
|
|
case SG_VERTEXFORMAT_FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT;
|
|
|
case SG_VERTEXFORMAT_FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
|
+ case SG_VERTEXFORMAT_INT: return DXGI_FORMAT_R32_SINT;
|
|
|
+ case SG_VERTEXFORMAT_INT2: return DXGI_FORMAT_R32G32_SINT;
|
|
|
+ case SG_VERTEXFORMAT_INT3: return DXGI_FORMAT_R32G32B32_SINT;
|
|
|
+ case SG_VERTEXFORMAT_INT4: return DXGI_FORMAT_R32G32B32A32_SINT;
|
|
|
+ case SG_VERTEXFORMAT_UINT: return DXGI_FORMAT_R32_UINT;
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return DXGI_FORMAT_R32G32_UINT;
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return DXGI_FORMAT_R32G32B32_UINT;
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return DXGI_FORMAT_R32G32B32A32_UINT;
|
|
|
case SG_VERTEXFORMAT_BYTE4: return DXGI_FORMAT_R8G8B8A8_SINT;
|
|
|
case SG_VERTEXFORMAT_BYTE4N: return DXGI_FORMAT_R8G8B8A8_SNORM;
|
|
|
case SG_VERTEXFORMAT_UBYTE4: return DXGI_FORMAT_R8G8B8A8_UINT;
|
|
|
case SG_VERTEXFORMAT_UBYTE4N: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
case SG_VERTEXFORMAT_SHORT2: return DXGI_FORMAT_R16G16_SINT;
|
|
|
case SG_VERTEXFORMAT_SHORT2N: return DXGI_FORMAT_R16G16_SNORM;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return DXGI_FORMAT_R16G16_UINT;
|
|
|
case SG_VERTEXFORMAT_USHORT2N: return DXGI_FORMAT_R16G16_UNORM;
|
|
|
case SG_VERTEXFORMAT_SHORT4: return DXGI_FORMAT_R16G16B16A16_SINT;
|
|
|
case SG_VERTEXFORMAT_SHORT4N: return DXGI_FORMAT_R16G16B16A16_SNORM;
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return DXGI_FORMAT_R16G16B16A16_UINT;
|
|
|
case SG_VERTEXFORMAT_USHORT4N: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
|
|
case SG_VERTEXFORMAT_UINT10_N2: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
|
|
case SG_VERTEXFORMAT_HALF2: return DXGI_FORMAT_R16G16_FLOAT;
|
|
@@ -12534,15 +12702,25 @@ _SOKOL_PRIVATE MTLVertexFormat _sg_mtl_vertex_format(sg_vertex_format fmt) {
|
|
|
case SG_VERTEXFORMAT_FLOAT2: return MTLVertexFormatFloat2;
|
|
|
case SG_VERTEXFORMAT_FLOAT3: return MTLVertexFormatFloat3;
|
|
|
case SG_VERTEXFORMAT_FLOAT4: return MTLVertexFormatFloat4;
|
|
|
+ case SG_VERTEXFORMAT_INT: return MTLVertexFormatInt;
|
|
|
+ case SG_VERTEXFORMAT_INT2: return MTLVertexFormatInt2;
|
|
|
+ case SG_VERTEXFORMAT_INT3: return MTLVertexFormatInt3;
|
|
|
+ case SG_VERTEXFORMAT_INT4: return MTLVertexFormatInt4;
|
|
|
+ case SG_VERTEXFORMAT_UINT: return MTLVertexFormatUInt;
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return MTLVertexFormatUInt2;
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return MTLVertexFormatUInt3;
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return MTLVertexFormatUInt4;
|
|
|
case SG_VERTEXFORMAT_BYTE4: return MTLVertexFormatChar4;
|
|
|
case SG_VERTEXFORMAT_BYTE4N: return MTLVertexFormatChar4Normalized;
|
|
|
case SG_VERTEXFORMAT_UBYTE4: return MTLVertexFormatUChar4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4N: return MTLVertexFormatUChar4Normalized;
|
|
|
case SG_VERTEXFORMAT_SHORT2: return MTLVertexFormatShort2;
|
|
|
case SG_VERTEXFORMAT_SHORT2N: return MTLVertexFormatShort2Normalized;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return MTLVertexFormatUShort2;
|
|
|
case SG_VERTEXFORMAT_USHORT2N: return MTLVertexFormatUShort2Normalized;
|
|
|
case SG_VERTEXFORMAT_SHORT4: return MTLVertexFormatShort4;
|
|
|
case SG_VERTEXFORMAT_SHORT4N: return MTLVertexFormatShort4Normalized;
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return MTLVertexFormatUShort4;
|
|
|
case SG_VERTEXFORMAT_USHORT4N: return MTLVertexFormatUShort4Normalized;
|
|
|
case SG_VERTEXFORMAT_UINT10_N2: return MTLVertexFormatUInt1010102Normalized;
|
|
|
case SG_VERTEXFORMAT_HALF2: return MTLVertexFormatHalf2;
|
|
@@ -14652,19 +14830,29 @@ _SOKOL_PRIVATE WGPUVertexFormat _sg_wgpu_vertexformat(sg_vertex_format f) {
|
|
|
case SG_VERTEXFORMAT_FLOAT2: return WGPUVertexFormat_Float32x2;
|
|
|
case SG_VERTEXFORMAT_FLOAT3: return WGPUVertexFormat_Float32x3;
|
|
|
case SG_VERTEXFORMAT_FLOAT4: return WGPUVertexFormat_Float32x4;
|
|
|
+ case SG_VERTEXFORMAT_INT: return WGPUVertexFormat_Sint32;
|
|
|
+ case SG_VERTEXFORMAT_INT2: return WGPUVertexFormat_Sint32x2;
|
|
|
+ case SG_VERTEXFORMAT_INT3: return WGPUVertexFormat_Sint32x3;
|
|
|
+ case SG_VERTEXFORMAT_INT4: return WGPUVertexFormat_Sint32x4;
|
|
|
+ case SG_VERTEXFORMAT_UINT: return WGPUVertexFormat_Uint32;
|
|
|
+ case SG_VERTEXFORMAT_UINT2: return WGPUVertexFormat_Uint32x2;
|
|
|
+ case SG_VERTEXFORMAT_UINT3: return WGPUVertexFormat_Uint32x3;
|
|
|
+ case SG_VERTEXFORMAT_UINT4: return WGPUVertexFormat_Uint32x4;
|
|
|
case SG_VERTEXFORMAT_BYTE4: return WGPUVertexFormat_Sint8x4;
|
|
|
case SG_VERTEXFORMAT_BYTE4N: return WGPUVertexFormat_Snorm8x4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4: return WGPUVertexFormat_Uint8x4;
|
|
|
case SG_VERTEXFORMAT_UBYTE4N: return WGPUVertexFormat_Unorm8x4;
|
|
|
case SG_VERTEXFORMAT_SHORT2: return WGPUVertexFormat_Sint16x2;
|
|
|
case SG_VERTEXFORMAT_SHORT2N: return WGPUVertexFormat_Snorm16x2;
|
|
|
+ case SG_VERTEXFORMAT_USHORT2: return WGPUVertexFormat_Uint16x2;
|
|
|
case SG_VERTEXFORMAT_USHORT2N: return WGPUVertexFormat_Unorm16x2;
|
|
|
case SG_VERTEXFORMAT_SHORT4: return WGPUVertexFormat_Sint16x4;
|
|
|
case SG_VERTEXFORMAT_SHORT4N: return WGPUVertexFormat_Snorm16x4;
|
|
|
+ case SG_VERTEXFORMAT_USHORT4: return WGPUVertexFormat_Uint16x4;
|
|
|
case SG_VERTEXFORMAT_USHORT4N: return WGPUVertexFormat_Unorm16x4;
|
|
|
+ case SG_VERTEXFORMAT_UINT10_N2: return WGPUVertexFormat_Unorm10_10_10_2;
|
|
|
case SG_VERTEXFORMAT_HALF2: return WGPUVertexFormat_Float16x2;
|
|
|
case SG_VERTEXFORMAT_HALF4: return WGPUVertexFormat_Float16x4;
|
|
|
- case SG_VERTEXFORMAT_UINT10_N2: return WGPUVertexFormat_Unorm10_10_10_2;
|
|
|
default:
|
|
|
SOKOL_UNREACHABLE;
|
|
|
return WGPUVertexFormat_Force32;
|
|
@@ -17749,6 +17937,9 @@ _SOKOL_PRIVATE _sg_u128_t _sg_validate_set_slot_bit(_sg_u128_t bits, sg_shader_s
|
|
|
SOKOL_ASSERT(slot < 64);
|
|
|
bits.lo |= 1ULL << slot;
|
|
|
break;
|
|
|
+ default:
|
|
|
+ SOKOL_UNREACHABLE;
|
|
|
+ break;
|
|
|
}
|
|
|
return bits;
|
|
|
}
|
|
@@ -18052,7 +18243,7 @@ _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) {
|
|
|
} else {
|
|
|
_SG_VALIDATE(!shd->cmn.is_compute, VALIDATE_PIPELINEDESC_NO_COMPUTE_SHADER_EXPECTED);
|
|
|
bool attrs_cont = true;
|
|
|
- for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
|
|
|
+ for (size_t attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
|
|
|
const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];
|
|
|
if (a_state->format == SG_VERTEXFORMAT_INVALID) {
|
|
|
attrs_cont = false;
|
|
@@ -18060,6 +18251,16 @@ _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) {
|
|
|
}
|
|
|
_SG_VALIDATE(attrs_cont, VALIDATE_PIPELINEDESC_NO_CONT_ATTRS);
|
|
|
SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEXBUFFER_BINDSLOTS);
|
|
|
+ // vertex format must match expected shader attribute base type (if provided)
|
|
|
+ if (shd->cmn.attrs[attr_index].base_type != SG_SHADERATTRBASETYPE_UNDEFINED) {
|
|
|
+ if (_sg_vertexformat_basetype(a_state->format) != shd->cmn.attrs[attr_index].base_type) {
|
|
|
+ _SG_VALIDATE(false, VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH);
|
|
|
+ _SG_LOGMSG(VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH, "attr format:");
|
|
|
+ _SG_LOGMSG(VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH, _sg_vertexformat_to_string(a_state->format));
|
|
|
+ _SG_LOGMSG(VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH, "shader attr base type:");
|
|
|
+ _SG_LOGMSG(VALIDATE_PIPELINEDESC_ATTR_BASETYPE_MISMATCH, _sg_shaderattrbasetype_to_string(shd->cmn.attrs[attr_index].base_type));
|
|
|
+ }
|
|
|
+ }
|
|
|
#if defined(SOKOL_D3D11)
|
|
|
// on D3D11, semantic names (and semantic indices) must be provided
|
|
|
_SG_VALIDATE(!_sg_strempty(&shd->d3d11.attrs[attr_index].sem_name), VALIDATE_PIPELINEDESC_ATTR_SEMANTICS);
|