aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2019-04-26 18:05:17 +0200
committerGitHub <noreply@github.com>2019-04-26 18:05:17 +0200
commiteaae3947d8171ba6b842d46629df48c027f97822 (patch)
tree41302371aba9ed7b4c39f2fe03cb5957017cb45f
parent339bf9b4833361d7b47549b98c37c0a6a2b7cb6c (diff)
Move vertex-attr names/semantics from sg_pipeline_desc to sg_shader_desc (#146)
* sokol_gfx.h: start working moving vertex attr names into sg_shader_desc * sokol_gfx.h: move vertex attribute names into shader desc * sokol_gfx.h: D3D11 backend fixes * fix typo in GLES2 shader-attr validation * add shader-attribute change to README update section * remove unused _sg_make_str function
-rw-r--r--README.md113
-rw-r--r--sokol_gfx.h137
-rw-r--r--util/sokol_gfx_imgui.h42
-rw-r--r--util/sokol_gl.h12
-rw-r--r--util/sokol_imgui.h24
5 files changed, 252 insertions, 76 deletions
diff --git a/README.md b/README.md
index 3f2c15d5..7efff08d 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
**Sokol (Сокол)**: Russian for Falcon, a smaller and more nimble
bird of prey than the Eagle (Орёл, Oryol)
-[See what's new](#updates)
+[See what's new](#updates) (**26-Apr-2019**: breaking change in sokol_gfx.h)
Minimalistic header-only cross-platform libs in C:
@@ -94,8 +94,8 @@ int main() {
sg_shader shd = sg_make_shader(&(sg_shader_desc){
.vs.source =
"#version 330\n"
- "in vec4 position;\n"
- "in vec4 color0;\n"
+ "layout(location=0) in vec4 position;\n"
+ "layout(location=1) in vec4 color0;\n"
"out vec4 color;\n"
"void main() {\n"
" gl_Position = position;\n"
@@ -115,8 +115,8 @@ int main() {
.shader = shd,
.layout = {
.attrs = {
- [0] = { .name="position", .format=SG_VERTEXFORMAT_FLOAT3 },
- [1] = { .name="color0", .format=SG_VERTEXFORMAT_FLOAT4 }
+ [0].format=SG_VERTEXFORMAT_FLOAT3,
+ [1].format=SG_VERTEXFORMAT_FLOAT4
}
}
});
@@ -399,15 +399,104 @@ Mainly some "missing features" for desktop apps:
- implement an alternative WebAudio backend using Audio Worklets and WASM threads
-## Potential new sokol headers:
+# Updates
-- system clipboard support
-- query filesystem standard locations
-- simple file access API (at least async file/URL loading)
-- gamepad support
-- simple cross-platform touch gesture recognition
+- **26-Apr-2019** Small but breaking change in **sokol_gfx.h** how the vertex
+layout definition in sg_pipeline_desc works:
+
+ Vertex component names and semantics (needed by the GLES2 and D3D11 backends) have moved from ```sg_pipeline_desc``` into ```sg_shader_desc```.
+
+ This may seem like a rather pointless small detail to change, expecially
+ for breaking existing code, but the whole thing will make a bit more
+ sense when the new shader-cross-compiler will be integrated which I'm
+ currently working on (here: https://github.com/floooh/sokol-tools).
+
+ While working on getting reflection data out of the shaders (e.g. what
+ uniform blocks and textures the shader uses), it occured to me that
+ vertex-attribute-names and -semantics are actually part of the reflection
+ info and belong to the shader, not to the vertex layout in the pipeline
+ object (which only describes how the incoming vertex data maps to
+ vertex-component **slots**. Instead of (optionally) mapping this
+ association through a name, the pipeline's vertex layout is now always
+ strictly defined in terms of numeric 'bind slots' for **all** sokol_gfx.h
+ backends. For 3D APIs where the vertex component slot isn't explicitely
+ defined in the shader language (GLES2/WebGL, D3D11, and optionally
+ GLES3/GL), the shader merely offers a lookup table how vertex-layout
+ slot-indices map to names/semantics (and the underlying 3D API than maps
+ those names back to slot indices, which shows that Metal and GL made the
+ right choice defining the slots right in the shader).
+
+ Here's how the code changes (taken from the triangle-sapp.c sample):
+
+ **OLD**:
+ ```c
+ /* create a shader */
+ sg_shader shd = sg_make_shader(&(sg_shader_desc){
+ .vs.source = vs_src,
+ .fs.source = fs_src,
+ });
-# Updates
+ /* create a pipeline object (default render states are fine for triangle) */
+ pip = sg_make_pipeline(&(sg_pipeline_desc){
+ /* if the vertex layout doesn't have gaps, don't need to provide strides and offsets */
+ .shader = shd,
+ .layout = {
+ .attrs = {
+ [0] = { .name="position", .sem_name="POS", .format=SG_VERTEXFORMAT_FLOAT3 },
+ [1] = { .name="color0", .sem_name="COLOR", .format=SG_VERTEXFORMAT_FLOAT4 }
+ }
+ },
+ });
+ ```
+
+ **NEW**:
+ ```c
+ /* create a shader */
+ sg_shader shd = sg_make_shader(&(sg_shader_desc){
+ .attrs = {
+ [0] = { .name="position", .sem_name="POS" },
+ [1] = { .name="color0", .sem_name="COLOR" }
+ },
+ .vs.source = vs_src,
+ .fs.source = fs_src,
+ });
+
+ /* create a pipeline object (default render states are fine for triangle) */
+ pip = sg_make_pipeline(&(sg_pipeline_desc){
+ /* if the vertex layout doesn't have gaps, don't need to provide strides and offsets */
+ .shader = shd,
+ .layout = {
+ .attrs = {
+ [0].format=SG_VERTEXFORMAT_FLOAT3,
+ [1].format=SG_VERTEXFORMAT_FLOAT4
+ }
+ },
+ });
+ ```
+
+ ```sg_shader_desc``` has a new embedded struct ```attrs``` which
+ contains a vertex attribute _name_ (for GLES2/WebGL) and
+ _sem_name/sem_index_ (for D3D11). For the Metal backend this struct is
+ ignored completely, and for GLES3/GL it is optional, and not required
+ when the vertex shader inputs are annotated with ```layout(location=N)```.
+
+ The remaining attribute description members in ```sg_pipeline_desc``` are:
+ - **.format**: the format of input vertex data (this can be different
+ from the vertex shader's inputs when data is extended during
+ vertex fetch (e.g. input can be vec3 while the vertex shader
+ expects vec4)
+ - **.offset**: optional offset of the vertex component data (not needed
+ when the input vertex has no gaps between the components)
+ - **.buffer**: the vertex buffer bind slot if the vertex data is coming
+ from different buffers
+
+ Also check out the various samples:
+
+ - for GLSL (explicit slots via ```layout(location=N)```): https://github.com/floooh/sokol-samples/tree/master/glfw
+ - for D3D11 (semantic names/indices): https://github.com/floooh/sokol-samples/tree/master/d3d11
+ - for GLES2: (vertex attribute names): https://github.com/floooh/sokol-samples/tree/master/html5
+ - for Metal: (explicit slots): https://github.com/floooh/sokol-samples/tree/master/metal
+ - ...and all of the above combined: https://github.com/floooh/sokol-samples/tree/master/sapp
- **19-Apr-2019** I have replaced the rather inflexible render-state handling
in **sokol_gl.h** with a *pipeline stack* (like the GL matrix stack, but with
diff --git a/sokol_gfx.h b/sokol_gfx.h
index 53cb3ef6..82bea326 100644
--- a/sokol_gfx.h
+++ b/sokol_gfx.h
@@ -284,32 +284,34 @@
...
};
- --- when creating a pipeline object, GLES2/WebGL need to know the vertex
- attribute names as used in the vertex shader when describing vertex
- layouts:
+ --- when creating a shader object, GLES2/WebGL need to know the vertex
+ attribute names as used in the vertex shader:
- sg_pipeline_desc desc = {
- .layout = {
- .attrs = {
- [0] = { .name="position", .format=SG_VERTEXFORMAT_FLOAT3 },
- [1] = { .name="color1", .format=SG_VERTEXFORMAT_FLOAT4 }
- }
+ sg_shader_desc desc = {
+ .attrs = {
+ [0] = { .name="position" },
+ [1] = { .name="color1" }
}
};
+ The vertex attribute names provided when creating a shader will be
+ used later in sg_create_pipeline() for matching the vertex layout
+ to vertex shader inputs.
+
--- on D3D11 you need to provide a semantic name and semantic index in the
- vertex attribute definition instead (see the D3D11 documentation on
+ shader description struct instead (see the D3D11 documentation on
D3D11_INPUT_ELEMENT_DESC for details):
- sg_pipeline_desc desc = {
- .layout = {
- .attrs = {
- [0] = { .sem_name="POSITION", .sem_index=0, .format=SG_VERTEXFORMAT_FLOAT3 },
- [1] = { .sem_name="COLOR", .sem_index=1, .format=SG_VERTEXFORMAT_FLOAT4 }
- }
+ sg_shader_desc desc = {
+ .attrs = {
+ [0] = { .sem_name="POSITION", .sem_index=0 }
+ [1] = { .sem_name="COLOR", .sem_index=1 }
}
};
+ The provided semantic information will be used later in sg_create_pipeline()
+ to match the vertex layout to vertex shader inputs.
+
--- on Metal, GL 3.3 or GLES3/WebGL2, you don't need to provide an attribute
name or semantic name, since vertex attributes can be bound by their slot index
(this is mandatory in Metal, and optional in GL):
@@ -1283,10 +1285,17 @@ typedef struct sg_image_desc {
sg_shader_desc
The structure sg_shader_desc describes the shaders, uniform blocks
- and texture images on the vertex- and fragment-shader stage.
+ texture images and vertex-attribute-names/semantics (required
+ for GLES2 and D3D11) of a shader stage.
TODO: source code vs byte code, 3D backend API specifics.
*/
+typedef struct sg_shader_attr_desc {
+ const char* name; /* GLSL vertex attribute name (only required for GLES2) */
+ const char* sem_name; /* HLSL semantic name */
+ int sem_index; /* HLSL semantic index */
+} sg_shader_attr_desc;
+
typedef struct sg_shader_uniform_desc {
const char* name;
sg_uniform_type type;
@@ -1314,6 +1323,7 @@ typedef struct sg_shader_stage_desc {
typedef struct sg_shader_desc {
uint32_t _start_canary;
+ sg_shader_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];
sg_shader_stage_desc vs;
sg_shader_stage_desc fs;
const char* label;
@@ -1401,9 +1411,6 @@ typedef struct sg_buffer_layout_desc {
} sg_buffer_layout_desc;
typedef struct sg_vertex_attr_desc {
- const char* name;
- const char* sem_name;
- int sem_index;
int buffer_index;
int offset;
sg_vertex_format format;
@@ -2039,6 +2046,7 @@ typedef struct {
/* constants */
enum {
+ _SG_STRING_SIZE = 16,
_SG_SLOT_SHIFT = 16,
_SG_SLOT_MASK = (1<<_SG_SLOT_SHIFT)-1,
_SG_MAX_POOL_SIZE = (1<<_SG_SLOT_SHIFT),
@@ -2052,6 +2060,11 @@ enum {
_SG_MTL_DEFAULT_SAMPLER_CACHE_CAPACITY = 64,
};
+/* fixed-size string */
+typedef struct {
+ char buf[_SG_STRING_SIZE];
+} _sg_str_t;
+
/* helper macros */
#define _sg_def(val, def) (((val) == 0) ? (def) : (val))
#define _sg_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))
@@ -2215,6 +2228,10 @@ typedef struct {
} _sg_shader_image_t;
typedef struct {
+ _sg_str_t name;
+} _sg_shader_attr_t;
+
+typedef struct {
int num_uniform_blocks;
int num_images;
_sg_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
@@ -2224,6 +2241,7 @@ typedef struct {
typedef struct {
_sg_slot_t slot;
GLuint gl_prog;
+ _sg_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
_sg_shader_stage_t stage[SG_NUM_SHADER_STAGES];
} _sg_shader_t;
@@ -2364,8 +2382,14 @@ typedef struct {
} _sg_shader_image_t;
typedef struct {
+ _sg_str_t sem_name;
+ int sem_index;
+} _sg_shader_attr_t;
+
+typedef struct {
int num_uniform_blocks;
int num_images;
+ _sg_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
_sg_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
_sg_shader_image_t images[SG_MAX_SHADERSTAGE_IMAGES];
ID3D11Buffer* d3d11_cbs[SG_MAX_SHADERSTAGE_UBS];
@@ -2373,6 +2397,7 @@ typedef struct {
typedef struct {
_sg_slot_t slot;
+ _sg_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
_sg_shader_stage_t stage[SG_NUM_SHADER_STAGES];
ID3D11VertexShader* d3d11_vs;
ID3D11PixelShader* d3d11_fs;
@@ -2711,6 +2736,9 @@ typedef enum {
_SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME,
_SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH,
_SG_VALIDATE_SHADERDESC_IMG_NAME,
+ _SG_VALIDATE_SHADERDESC_ATTR_NAMES,
+ _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS,
+ _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG,
/* pipeline creation */
_SG_VALIDATE_PIPELINEDESC_CANARY,
@@ -2826,6 +2854,29 @@ static _sg_state_t _sg;
/*-- helper functions --------------------------------------------------------*/
+_SOKOL_PRIVATE bool _sg_strempty(const _sg_str_t* str) {
+ return 0 == str->buf[0];
+}
+
+_SOKOL_PRIVATE const char* _sg_strptr(const _sg_str_t* str) {
+ return &str->buf[0];
+}
+
+_SOKOL_PRIVATE void _sg_strcpy(_sg_str_t* dst, const char* src) {
+ SOKOL_ASSERT(dst);
+ if (src) {
+ #if defined(_MSC_VER)
+ strncpy_s(dst->buf, _SG_STRING_SIZE, src, (_SG_STRING_SIZE-1));
+ #else
+ strncpy(dst->buf, src, _SG_STRING_SIZE);
+ #endif
+ dst->buf[_SG_STRING_SIZE-1] = 0;
+ }
+ else {
+ memset(dst->buf, 0, _SG_STRING_SIZE);
+ }
+}
+
/* return byte size of a vertex format */
_SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) {
switch (fmt) {
@@ -4246,6 +4297,12 @@ _SOKOL_PRIVATE sg_resource_state _sg_create_shader(_sg_shader_t* shd, const sg_s
SOKOL_ASSERT(shd && desc);
SOKOL_ASSERT(!shd->gl_prog);
_SG_GL_CHECK_ERROR();
+
+ /* copy vertex attribute names over, these are required for GLES2, and optional for GLES3 and GL3.x */
+ for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
+ _sg_strcpy(&shd->attrs[i].name, desc->attrs[i].name);
+ }
+
GLuint gl_vs = _sg_gl_compile_shader(SG_SHADERSTAGE_VS, desc->vs.source);
GLuint gl_fs = _sg_gl_compile_shader(SG_SHADERSTAGE_FS, desc->fs.source);
if (!(gl_vs && gl_fs)) {
@@ -4384,8 +4441,8 @@ _SOKOL_PRIVATE sg_resource_state _sg_create_pipeline(_sg_pipeline_t* pip, _sg_sh
const sg_vertex_step step_func = l_desc->step_func;
const int step_rate = l_desc->step_rate;
GLint attr_loc = attr_index;
- if (a_desc->name) {
- attr_loc = glGetAttribLocation(pip->shader->gl_prog, a_desc->name);
+ if (!_sg_strempty(&shd->attrs[attr_index].name)) {
+ attr_loc = glGetAttribLocation(pip->shader->gl_prog, _sg_strptr(&shd->attrs[attr_index].name));
}
SOKOL_ASSERT(attr_loc < SG_MAX_VERTEX_ATTRIBUTES);
if (attr_loc != -1) {
@@ -4408,7 +4465,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_create_pipeline(_sg_pipeline_t* pip, _sg_sh
}
else {
SOKOL_LOG("Vertex attribute not found in shader: ");
- SOKOL_LOG(a_desc->name);
+ SOKOL_LOG(_sg_strptr(&shd->attrs[attr_index].name));
}
}
return SG_RESOURCESTATE_VALID;
@@ -5874,6 +5931,12 @@ _SOKOL_PRIVATE sg_resource_state _sg_create_shader(_sg_shader_t* shd, const sg_s
HRESULT hr;
sg_resource_state result = SG_RESOURCESTATE_FAILED;
+ /* copy vertex attribute semantic names and indices */
+ for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
+ _sg_strcpy(&shd->attrs[i].sem_name, desc->attrs[i].sem_name);
+ shd->attrs[i].sem_index = desc->attrs[i].sem_index;
+ }
+
/* shader stage uniform blocks and image slots */
for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;
@@ -6018,8 +6081,8 @@ _SOKOL_PRIVATE sg_resource_state _sg_create_pipeline(_sg_pipeline_t* pip, _sg_sh
const sg_vertex_step step_func = l_desc->step_func;
const int step_rate = l_desc->step_rate;
D3D11_INPUT_ELEMENT_DESC* d3d11_comp = &d3d11_comps[attr_index];
- d3d11_comp->SemanticName = a_desc->sem_name;
- d3d11_comp->SemanticIndex = a_desc->sem_index;
+ d3d11_comp->SemanticName = _sg_strptr(&shd->attrs[attr_index].sem_name);
+ d3d11_comp->SemanticIndex = shd->attrs[attr_index].sem_index;
d3d11_comp->Format = _sg_d3d11_vertex_format(a_desc->format);
d3d11_comp->InputSlot = a_desc->buffer_index;
d3d11_comp->AlignedByteOffset = a_desc->offset;
@@ -8506,14 +8569,17 @@ _SOKOL_PRIVATE const char* _sg_validate_string(_sg_validate_error_t err) {
case _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH: return "size of uniform block members doesn't match uniform block size";
case _SG_VALIDATE_SHADERDESC_NO_CONT_IMGS: return "shader images must occupy continuous slots";
case _SG_VALIDATE_SHADERDESC_IMG_NAME: return "GL backend requires uniform block member names";
+ case _SG_VALIDATE_SHADERDESC_ATTR_NAMES: return "GLES2 backend requires vertex attribute names";
+ case _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS: return "D3D11 backend requires vertex attribute semantics";
+ case _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG: return "vertex attribute name/semantic string too long (max len 16)";
/* pipeline creation */
case _SG_VALIDATE_PIPELINEDESC_CANARY: return "sg_pipeline_desc not initialized";
case _SG_VALIDATE_PIPELINEDESC_SHADER: return "sg_pipeline_desc.shader missing or invalid";
case _SG_VALIDATE_PIPELINEDESC_NO_ATTRS: return "sg_pipeline_desc.layout.attrs is empty or not continuous";
case _SG_VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4: return "sg_pipeline_desc.layout.buffers[].stride must be multiple of 4";
- case _SG_VALIDATE_PIPELINEDESC_ATTR_NAME: return "GLES2/WebGL vertex layouts must have attribute names";
- case _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS: return "D3D11 vertex layouts must have attribute semantics (sem_name and sem_index)";
+ case _SG_VALIDATE_PIPELINEDESC_ATTR_NAME: return "GLES2/WebGL missing vertex attribute name in shader";
+ case _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS: return "D3D11 missing vertex attribute semantics in shader";
/* pass creation */
case _SG_VALIDATE_PASSDESC_CANARY: return "sg_pass_desc not initialized";
@@ -8705,6 +8771,11 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) {
SOKOL_VALIDATE_BEGIN();
SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_SHADERDESC_CANARY);
SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_SHADERDESC_CANARY);
+ #if defined(SOKOL_GLES2)
+ SOKOL_VALIDATE(0 != desc->attrs[0].name, _SG_VALIDATE_SHADERDESC_ATTR_NAMES);
+ #elif defined(SOKOL_D3D11)
+ SOKOL_VALIDATE(0 != desc->attrs[0].sem_name, _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS);
+ #endif
#if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
/* on GL, must provide shader source code */
SOKOL_VALIDATE(0 != desc->vs.source, _SG_VALIDATE_SHADERDESC_SOURCE);
@@ -8720,6 +8791,14 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) {
#else
/* Dummy Backend, don't require source or bytecode */
#endif
+ for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
+ if (desc->attrs[i].name) {
+ SOKOL_VALIDATE(strlen(desc->attrs[i].name) < _SG_STRING_SIZE, _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);
+ }
+ if (desc->attrs[i].sem_name) {
+ SOKOL_VALIDATE(strlen(desc->attrs[i].sem_name) < _SG_STRING_SIZE, _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);
+ }
+ }
/* if shader byte code, the size must also be provided */
if (0 != desc->vs.byte_code) {
SOKOL_VALIDATE(desc->vs.byte_code_size > 0, _SG_VALIDATE_SHADERDESC_NO_BYTECODE_SIZE);
@@ -8810,10 +8889,10 @@ _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) {
SOKOL_ASSERT(a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS);
#if defined(SOKOL_GLES2)
/* on GLES2, vertex attribute names must be provided */
- SOKOL_VALIDATE((0 != a_desc->name), _SG_VALIDATE_PIPELINEDESC_ATTR_NAME);
+ SOKOL_VALIDATE(!_sg_strempty(&shd->attrs[attr_index].name), _SG_VALIDATE_PIPELINEDESC_ATTR_NAME);
#elif defined(SOKOL_D3D11)
/* on D3D11, semantic names (and semantic indices) must be provided */
- SOKOL_VALIDATE((0 != a_desc->sem_name), _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS);
+ SOKOL_VALIDATE(!_sg_strempty(&shd->attrs[attr_index].sem_name), _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS);
#endif
}
return SOKOL_VALIDATE_END();
diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h
index e702c88c..808fd122 100644
--- a/util/sokol_gfx_imgui.h
+++ b/util/sokol_gfx_imgui.h
@@ -185,14 +185,14 @@ typedef struct {
sg_imgui_str_t fs_entry;
sg_imgui_str_t fs_image_name[SG_MAX_SHADERSTAGE_IMAGES];
sg_imgui_str_t fs_uniform_name[SG_MAX_SHADERSTAGE_UBS][SG_MAX_UB_MEMBERS];
+ sg_imgui_str_t attr_name[SG_MAX_VERTEX_ATTRIBUTES];
+ sg_imgui_str_t attr_sem_name[SG_MAX_VERTEX_ATTRIBUTES];
sg_shader_desc desc;
} sg_imgui_shader_t;
typedef struct {
sg_pipeline res_id;
sg_imgui_str_t label;
- sg_imgui_str_t attr_name[SG_MAX_VERTEX_ATTRIBUTES];
- sg_imgui_str_t attr_sem_name[SG_MAX_VERTEX_ATTRIBUTES];
sg_pipeline_desc desc;
} sg_imgui_pipeline_t;
@@ -1109,6 +1109,17 @@ _SOKOL_PRIVATE void _sg_imgui_shader_created(sg_imgui_t* ctx, sg_shader res_id,
if (shd->desc.fs.byte_code) {
shd->desc.fs.byte_code = _sg_imgui_bin_dup(shd->desc.fs.byte_code, shd->desc.fs.byte_code_size);
}
+ for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
+ sg_shader_attr_desc* ad = &shd->desc.attrs[i];
+ if (ad->name) {
+ shd->attr_name[i] = _sg_imgui_make_str(ad->name);
+ ad->name = shd->attr_name[i].buf;
+ }
+ if (ad->sem_name) {
+ shd->attr_sem_name[i] = _sg_imgui_make_str(ad->sem_name);
+ ad->sem_name = shd->attr_sem_name[i].buf;
+ }
+ }
}
_SOKOL_PRIVATE void _sg_imgui_shader_destroyed(sg_imgui_t* ctx, int slot_index) {
@@ -1140,18 +1151,6 @@ _SOKOL_PRIVATE void _sg_imgui_pipeline_created(sg_imgui_t* ctx, sg_pipeline res_
pip->label = _sg_imgui_make_str(desc->label);
pip->desc = *desc;
- /* copy strings in vertex layout to persistent location */
- for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
- sg_vertex_attr_desc* ad = &pip->desc.layout.attrs[i];
- if (ad->name) {
- pip->attr_name[i] = _sg_imgui_make_str(ad->name);
- ad->name = pip->attr_name[i].buf;
- }
- if (ad->sem_name) {
- pip->attr_sem_name[i] = _sg_imgui_make_str(ad->sem_name);
- ad->sem_name = pip->attr_sem_name[i].buf;
- }
- }
}
_SOKOL_PRIVATE void _sg_imgui_pipeline_destroyed(sg_imgui_t* ctx, int slot_index) {
@@ -2683,6 +2682,18 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_panel(sg_imgui_t* ctx, sg_shader shd)
ImGui::Text("Label: %s", shd_ui->label.buf[0] ? shd_ui->label.buf : "---");
_sg_imgui_draw_resource_slot(&info.slot);
ImGui::Separator();
+ if (ImGui::TreeNode("Attrs")) {
+ for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
+ const sg_shader_attr_desc* a_desc = &shd_ui->desc.attrs[i];
+ if (a_desc->name || a_desc->sem_index) {
+ ImGui::Text("#%d:", i);
+ ImGui::Text(" Name: %s", a_desc->name ? a_desc->name : "---");
+ ImGui::Text(" Sem Name: %s", a_desc->sem_name ? a_desc->sem_name : "---");
+ ImGui::Text(" Sem Index: %d", a_desc->sem_index);
+ }
+ }
+ ImGui::TreePop();
+ }
if (ImGui::TreeNode("Vertex Shader Stage")) {
_sg_imgui_draw_shader_stage(ctx, &shd_ui->desc.vs);
ImGui::TreePop();
@@ -2718,9 +2729,6 @@ _SOKOL_PRIVATE void _sg_imgui_draw_vertex_layout(const sg_layout_desc* layout) {
if (a_desc->format != SG_VERTEXFORMAT_INVALID) {
ImGui::Text("#%d:", i);
ImGui::Text(" Format: %s", _sg_imgui_vertexformat_string(a_desc->format));
- ImGui::Text(" Name: %s", a_desc->name ? a_desc->name : "---");
- ImGui::Text(" Sem Name: %s", a_desc->sem_name ? a_desc->sem_name : "---");
- ImGui::Text(" Sem Index: %d", a_desc->sem_index);
ImGui::Text(" Offset: %d", a_desc->offset);
ImGui::Text(" Buffer Index: %d", a_desc->buffer_index);
}
diff --git a/util/sokol_gl.h b/util/sokol_gl.h
index 4f1b1738..38931020 100644
--- a/util/sokol_gl.h
+++ b/util/sokol_gl.h
@@ -1314,22 +1314,16 @@ static void _sgl_init_pipeline(sgl_pipeline pip_id, const sg_pipeline_desc* in_d
desc.layout.buffers[0].stride = sizeof(_sgl_vertex_t);
{
sg_vertex_attr_desc* pos = &desc.layout.attrs[0];
- pos->name = "position";
- pos->sem_name = "POSITION";
pos->offset = offsetof(_sgl_vertex_t, pos);
pos->format = SG_VERTEXFORMAT_FLOAT3;
}
{
sg_vertex_attr_desc* uv = &desc.layout.attrs[1];
- uv->name = "texcoord0";
- uv->sem_name = "TEXCOORD";
uv->offset = offsetof(_sgl_vertex_t, uv);
uv->format = SG_VERTEXFORMAT_FLOAT2;
}
{
sg_vertex_attr_desc* rgba = &desc.layout.attrs[2];
- rgba->name = "color0";
- rgba->sem_name = "COLOR";
rgba->offset = offsetof(_sgl_vertex_t, rgba);
rgba->format = SG_VERTEXFORMAT_UBYTE4N;
}
@@ -1771,6 +1765,12 @@ SOKOL_API_IMPL void sgl_setup(const sgl_desc_t* desc) {
sg_shader_desc shd_desc;
memset(&shd_desc, 0, sizeof(shd_desc));
+ shd_desc.attrs[0].name = "position";
+ shd_desc.attrs[1].name = "texcoord0";
+ shd_desc.attrs[2].name = "color0";
+ shd_desc.attrs[0].sem_name = "POSITION";
+ shd_desc.attrs[1].sem_name = "TEXCOORD";
+ shd_desc.attrs[2].sem_name = "COLOR";
sg_shader_uniform_block_desc* ub = &shd_desc.vs.uniform_blocks[0];
ub->size = sizeof(_sgl_uniform_t);
ub->uniforms[0].name = "mvp";
diff --git a/util/sokol_imgui.h b/util/sokol_imgui.h
index f272d16f..02c90bb9 100644
--- a/util/sokol_imgui.h
+++ b/util/sokol_imgui.h
@@ -755,6 +755,12 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
ub.size = sizeof(_simgui_vs_params_t);
ub.uniforms[0].name = "disp_size";
ub.uniforms[0].type = SG_UNIFORMTYPE_FLOAT2;
+ shd_desc.attrs[0].name = "position";
+ shd_desc.attrs[0].sem_name = "POSITION";
+ shd_desc.attrs[1].name = "texcoord0";
+ shd_desc.attrs[1].sem_name = "TEXCOORD";
+ shd_desc.attrs[2].name = "color0";
+ shd_desc.attrs[2].sem_name = "COLOR";
shd_desc.fs.images[0].name = "tex";
shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
#if defined(SOKOL_D3D11)
@@ -774,24 +780,18 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
{
auto& attr = pip_desc.layout.attrs[0];
- attr.name = "position";
- attr.sem_name = "POSITION";
- attr.offset = offsetof(ImDrawVert, pos);
- attr.format = SG_VERTEXFORMAT_FLOAT2;
+ attr.offset = offsetof(ImDrawVert, pos);
+ attr.format = SG_VERTEXFORMAT_FLOAT2;
}
{
auto& attr = pip_desc.layout.attrs[1];
- attr.name = "texcoord0";
- attr.sem_name = "TEXCOORD";
- attr.offset = offsetof(ImDrawVert, uv);
- attr.format = SG_VERTEXFORMAT_FLOAT2;
+ attr.offset = offsetof(ImDrawVert, uv);
+ attr.format = SG_VERTEXFORMAT_FLOAT2;
}
{
auto& attr = pip_desc.layout.attrs[2];
- attr.name = "color0";
- attr.sem_name = "COLOR";
- attr.offset = offsetof(ImDrawVert, col);
- attr.format = SG_VERTEXFORMAT_UBYTE4N;
+ attr.offset = offsetof(ImDrawVert, col);
+ attr.format = SG_VERTEXFORMAT_UBYTE4N;
}
pip_desc.shader = _simgui.shd;
pip_desc.index_type = SG_INDEXTYPE_UINT16;