summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2023-02-19 16:33:25 +0100
committerAndre Weissflog <floooh@gmail.com>2023-02-19 16:33:25 +0100
commit494fb11e9af560d9df0d65c754b24f3ce3e5b7b9 (patch)
treec1d089fd0293a81d0aff1fe7313dfd1db7bc3393
parenta0a7c38f5bfb1ed14d5d6b824ab919df023acb1d (diff)
sokol_gfx.h: implement sg_query_shader_desc()
-rw-r--r--sokol_gfx.h43
-rw-r--r--tests/functional/sokol_gfx_test.c57
2 files changed, 94 insertions, 6 deletions
diff --git a/sokol_gfx.h b/sokol_gfx.h
index c7dc9ddb..9d1dc071 100644
--- a/sokol_gfx.h
+++ b/sokol_gfx.h
@@ -311,9 +311,15 @@
sg_pass_desc sg_query_pass_desc(sg_pass pass)
...but NOTE that the returned desc structs may be incomplete,
- for instance any references to external data, or generally
- information that is no longer available after creation will
- be zeroed.
+ only attributes that is kept around internally after resource creation
+ will be filled in, and in some cases (like shaders) that's very little.
+ The returned desc structs might still be useful as partial blueprint
+ for creating similar resources if filled up with the missing
+ properties. Missing properties will be set to zero.
+
+ Also calling the functions on an invalid resource will return
+ completely zeroed structs (it makes sense to check with sg_query_*_state()
+ first)
--- you can inspect various internal resource attributes via:
@@ -3808,7 +3814,7 @@ _SOKOL_PRIVATE void _sg_image_common_init(_sg_image_common_t* cmn, const sg_imag
typedef struct {
size_t size;
-} _sg_uniform_block_t;
+} _sg_shader_uniform_block_t;
typedef struct {
sg_image_type image_type;
@@ -3818,7 +3824,7 @@ typedef struct {
typedef struct {
int num_uniform_blocks;
int num_images;
- _sg_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
+ _sg_shader_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
_sg_shader_image_t images[SG_MAX_SHADERSTAGE_IMAGES];
} _sg_shader_stage_t;
@@ -9554,7 +9560,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons
_sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];
_sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index];
for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) {
- const _sg_uniform_block_t* ub = &cmn_stage->uniform_blocks[ub_index];
+ const _sg_shader_uniform_block_t* ub = &cmn_stage->uniform_blocks[ub_index];
/* create a D3D constant buffer for each uniform block */
SOKOL_ASSERT(0 == d3d11_stage->cbufs[ub_index]);
@@ -16911,6 +16917,31 @@ SOKOL_API_IMPL sg_image_desc sg_query_image_desc(sg_image img_id) {
return desc;
}
+SOKOL_API_IMPL sg_shader_desc sg_query_shader_desc(sg_shader shd_id) {
+ SOKOL_ASSERT(_sg.valid);
+ sg_shader_desc desc;
+ _sg_clear(&desc, sizeof(desc));
+ const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
+ if (shd) {
+ for (int stage_idx = 0; stage_idx < SG_NUM_SHADER_STAGES; stage_idx++) {
+ sg_shader_stage_desc* stage_desc = (stage_idx == 0) ? &desc.vs : &desc.fs;
+ const _sg_shader_stage_t* stage = &shd->cmn.stage[stage_idx];
+ for (int ub_idx = 0; ub_idx < stage->num_uniform_blocks; ub_idx++) {
+ sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_idx];
+ const _sg_shader_uniform_block_t* ub = &stage->uniform_blocks[ub_idx];
+ ub_desc->size = ub->size;
+ }
+ for (int img_idx = 0; img_idx < stage->num_images; img_idx++) {
+ sg_shader_image_desc* img_desc = &stage_desc->images[img_idx];
+ const _sg_shader_image_t* img = &stage->images[img_idx];
+ img_desc->image_type = img->image_type;
+ img_desc->sampler_type = img->sampler_type;
+ }
+ }
+ }
+ return desc;
+}
+
SOKOL_API_IMPL sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc) {
SOKOL_ASSERT(_sg.valid && desc);
return _sg_buffer_desc_defaults(desc);
diff --git a/tests/functional/sokol_gfx_test.c b/tests/functional/sokol_gfx_test.c
index a9e0d0e5..8a8612c6 100644
--- a/tests/functional/sokol_gfx_test.c
+++ b/tests/functional/sokol_gfx_test.c
@@ -929,6 +929,63 @@ UTEST(sokol_gfx, query_image_desc) {
sg_shutdown();
}
+UTEST(sokol_gfx, query_shader_desc) {
+ setup(&(sg_desc){0});
+
+ sg_shader s0 = sg_make_shader(&(sg_shader_desc){
+ .attrs = {
+ [0] = { .name = "pos", .sem_name = "POS", .sem_index = 1 },
+ },
+ .vs = {
+ .source = "vs_source",
+ .uniform_blocks = {
+ [0] = {
+ .size = 128,
+ .layout = SG_UNIFORMLAYOUT_STD140,
+ .uniforms = {
+ [0] = { .name = "blub", .type = SG_UNIFORMTYPE_FLOAT4, .array_count = 1 },
+ [1] = { .name = "blob", .type = SG_UNIFORMTYPE_FLOAT2, .array_count = 1 },
+ }
+ }
+ },
+ .images = {
+ [0] = { .name = "img0", .image_type = SG_IMAGETYPE_2D, .sampler_type = SG_SAMPLERTYPE_FLOAT },
+ }
+ },
+ .fs = {
+ .source = "fs_source",
+ .images = {
+ [0] = { .name = "img1", .image_type = SG_IMAGETYPE_ARRAY, .sampler_type = SG_SAMPLERTYPE_UINT },
+ }
+ },
+ .label = "label",
+ });
+ const sg_shader_desc s0_desc = sg_query_shader_desc(s0);
+ T(s0_desc.attrs[0].name == 0);
+ T(s0_desc.attrs[0].sem_name == 0);
+ T(s0_desc.attrs[0].sem_index == 0);
+ T(s0_desc.vs.source == 0);
+ T(s0_desc.vs.uniform_blocks[0].size == 128);
+ T(s0_desc.vs.uniform_blocks[0].layout == 0);
+ T(s0_desc.vs.uniform_blocks[0].uniforms[0].name == 0);
+ T(s0_desc.vs.uniform_blocks[0].uniforms[0].type == 0);
+ T(s0_desc.vs.uniform_blocks[0].uniforms[0].array_count == 0);
+ T(s0_desc.vs.images[0].name == 0);
+ T(s0_desc.vs.images[0].image_type == SG_IMAGETYPE_2D);
+ T(s0_desc.vs.images[0].sampler_type == SG_SAMPLERTYPE_FLOAT);
+ T(s0_desc.fs.source == 0);
+ T(s0_desc.fs.uniform_blocks[0].size == 0);
+ T(s0_desc.fs.uniform_blocks[0].layout == 0);
+ T(s0_desc.fs.uniform_blocks[0].uniforms[0].name == 0);
+ T(s0_desc.fs.uniform_blocks[0].uniforms[0].type == 0);
+ T(s0_desc.fs.uniform_blocks[0].uniforms[0].array_count == 0);
+ T(s0_desc.fs.images[0].name == 0);
+ T(s0_desc.fs.images[0].image_type == SG_IMAGETYPE_ARRAY);
+ T(s0_desc.fs.images[0].sampler_type == SG_SAMPLERTYPE_UINT);
+
+ sg_shutdown();
+}
+
UTEST(sokol_gfx, buffer_resource_states) {
setup(&(sg_desc){0});
sg_buffer buf = sg_alloc_buffer();