diff options
| -rw-r--r-- | README.md | 113 | ||||
| -rw-r--r-- | sokol_gfx.h | 137 | ||||
| -rw-r--r-- | util/sokol_gfx_imgui.h | 42 | ||||
| -rw-r--r-- | util/sokol_gl.h | 12 | ||||
| -rw-r--r-- | util/sokol_imgui.h | 24 |
5 files changed, 252 insertions, 76 deletions
@@ -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; |