aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sokol_gfx.h129
-rw-r--r--tests/functional/sokol_gfx_test.c89
-rw-r--r--util/sokol_gfx_imgui.h1
3 files changed, 217 insertions, 2 deletions
diff --git a/sokol_gfx.h b/sokol_gfx.h
index f3deebf5..a546c283 100644
--- a/sokol_gfx.h
+++ b/sokol_gfx.h
@@ -3859,6 +3859,7 @@ typedef struct sg_trace_hooks {
typedef struct sg_slot_info {
sg_resource_state state; // the current state of this resource slot
uint32_t res_id; // type-neutral resource if (e.g. sg_buffer.id)
+ uint32_t uninit_count;
} sg_slot_info;
typedef struct sg_buffer_info {
@@ -5584,6 +5585,7 @@ inline int sg_append_buffer(sg_buffer buf_id, const sg_range& data) { return sg_
// resource pool slots
typedef struct {
uint32_t id;
+ uint32_t uninit_count;
sg_resource_state state;
} _sg_slot_t;
@@ -5606,8 +5608,45 @@ _SOKOL_PRIVATE int _sg_slot_index(uint32_t id);
// resource func forward decls
struct _sg_pools_s;
struct _sg_buffer_s;
+struct _sg_image_s;
+struct _sg_shader_s;
+struct _sg_pipeline_s;
+struct _sg_attachments_s;
_SOKOL_PRIVATE struct _sg_buffer_s* _sg_lookup_buffer(const struct _sg_pools_s* p, uint32_t buf_id);
+// safe references to resource objects
+typedef struct _sg_buffer_ref_s {
+ uint32_t id;
+ uint32_t uninit_count;
+} _sg_buffer_ref_t;
+_SOKOL_PRIVATE _sg_buffer_ref_t _sg_buffer_ref(const struct _sg_buffer_s* buf);
+_SOKOL_PRIVATE void _sg_buffer_ref_clear(_sg_buffer_ref_t* ref);
+_SOKOL_PRIVATE struct _sg_buffer_s* _sg_buffer_ref_lookup(const _sg_buffer_ref_t* ref);
+
+typedef struct _sg_image_ref_s {
+ uint32_t id;
+ uint32_t uninit_count;
+} _sg_image_ref_t;
+_SOKOL_PRIVATE _sg_image_ref_t _sg_image_ref(const struct _sg_image_s* img);
+_SOKOL_PRIVATE void _sg_image_ref_clear(_sg_image_ref_t* ref);
+_SOKOL_PRIVATE struct _sg_image_s* _sg_image_ref_lookup(const _sg_image_ref_t* ref);
+
+typedef struct _sg_shader_ref_s {
+ uint32_t id;
+ uint32_t uninit_count;
+} _sg_shader_ref_t;
+_SOKOL_PRIVATE _sg_shader_ref_t _sg_shader_ref(const struct _sg_shader_s* shd);
+_SOKOL_PRIVATE void _sg_shader_ref_clear(_sg_shader_ref_t* ref);
+_SOKOL_PRIVATE struct _sg_shader_s* _sg_shader_ref_lookup(const _sg_shader_ref_t* ref);
+
+typedef struct _sg_pipeline_ref_s {
+ uint32_t id;
+ uint32_t uninit_count;
+} _sg_pipeline_ref_t;
+_SOKOL_PRIVATE _sg_pipeline_ref_t _sg_pipeline_ref(const struct _sg_pipeline_s* pip);
+_SOKOL_PRIVATE void _sg_pipeline_ref_clear(_sg_pipeline_ref_t* ref);
+_SOKOL_PRIVATE struct _sg_pipeline_s* _sg_pipeline_ref_lookup(const _sg_pipeline_ref_t* ref);
+
// resource tracking (for keeping track of gpu-written storage resources
typedef struct {
uint32_t size;
@@ -6655,8 +6694,6 @@ typedef struct {
} _sg_wgpu_backend_t;
#endif
-// POOL STRUCTS
-
// this *MUST* remain 0
#define _SG_INVALID_SLOT_INDEX (0)
@@ -18238,6 +18275,7 @@ _SOKOL_PRIVATE void _sg_reset_buffer_to_alloc_state(_sg_buffer_t* buf) {
_sg_slot_t slot = buf->slot;
_sg_clear(buf, sizeof(*buf));
buf->slot = slot;
+ buf->slot.uninit_count += 1;
buf->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18246,6 +18284,7 @@ _SOKOL_PRIVATE void _sg_reset_image_to_alloc_state(_sg_image_t* img) {
_sg_slot_t slot = img->slot;
_sg_clear(img, sizeof(*img));
img->slot = slot;
+ img->slot.uninit_count += 1;
img->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18254,6 +18293,7 @@ _SOKOL_PRIVATE void _sg_reset_sampler_to_alloc_state(_sg_sampler_t* smp) {
_sg_slot_t slot = smp->slot;
_sg_clear(smp, sizeof(*smp));
smp->slot = slot;
+ smp->slot.uninit_count += 1;
smp->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18262,6 +18302,7 @@ _SOKOL_PRIVATE void _sg_reset_shader_to_alloc_state(_sg_shader_t* shd) {
_sg_slot_t slot = shd->slot;
_sg_clear(shd, sizeof(*shd));
shd->slot = slot;
+ shd->slot.uninit_count += 1;
shd->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18270,6 +18311,7 @@ _SOKOL_PRIVATE void _sg_reset_pipeline_to_alloc_state(_sg_pipeline_t* pip) {
_sg_slot_t slot = pip->slot;
_sg_clear(pip, sizeof(*pip));
pip->slot = slot;
+ pip->slot.uninit_count += 1;
pip->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18278,6 +18320,7 @@ _SOKOL_PRIVATE void _sg_reset_attachments_to_alloc_state(_sg_attachments_t* atts
_sg_slot_t slot = atts->slot;
_sg_clear(atts, sizeof(*atts));
atts->slot = slot;
+ atts->slot.uninit_count += 1;
atts->slot.state = SG_RESOURCESTATE_ALLOC;
}
@@ -18514,6 +18557,82 @@ _SOKOL_PRIVATE void _sg_discard_all_resources(_sg_pools_t* p) {
}
}
+_SOKOL_PRIVATE _sg_buffer_ref_t _sg_buffer_ref(const _sg_buffer_t* buf) {
+ SOKOL_ASSERT(buf && (buf->slot.id != SG_INVALID_ID));
+ _sg_buffer_ref_t ref; _sg_clear(&ref, sizeof(ref));
+ ref.id = buf->slot.id;
+ ref.uninit_count = buf->slot.uninit_count;
+ return ref;
+}
+
+_SOKOL_PRIVATE _sg_image_ref_t _sg_image_ref(const _sg_image_t* img) {
+ SOKOL_ASSERT(img && (img->slot.id != SG_INVALID_ID));
+ _sg_image_ref_t ref; _sg_clear(&ref, sizeof(ref));
+ ref.id = img->slot.id;
+ ref.uninit_count = img->slot.uninit_count;
+ return ref;
+}
+
+_SOKOL_PRIVATE _sg_shader_ref_t _sg_shader_ref(const _sg_shader_t* shd) {
+ SOKOL_ASSERT(shd && (shd->slot.id != SG_INVALID_ID));
+ _sg_shader_ref_t ref; _sg_clear(&ref, sizeof(ref));
+ ref.id = shd->slot.id;
+ ref.uninit_count = shd->slot.uninit_count;
+ return ref;
+}
+
+_SOKOL_PRIVATE _sg_pipeline_ref_t _sg_pipeline_ref(const _sg_pipeline_t* pip) {
+ SOKOL_ASSERT(pip && (pip->slot.id != SG_INVALID_ID));
+ _sg_pipeline_ref_t ref; _sg_clear(&ref, sizeof(ref));
+ ref.id = pip->slot.id;
+ ref.uninit_count = pip->slot.uninit_count;
+ return ref;
+}
+
+_SOKOL_PRIVATE void _sg_buffer_ref_clear(_sg_buffer_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_clear(ref, sizeof(_sg_buffer_ref_t));
+}
+
+_SOKOL_PRIVATE void _sg_image_ref_clear(_sg_image_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_clear(ref, sizeof(_sg_image_ref_t));
+}
+
+_SOKOL_PRIVATE void _sg_shader_ref_clear(_sg_shader_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_clear(ref, sizeof(_sg_shader_ref_t));
+}
+
+_SOKOL_PRIVATE void _sg_pipeline_ref_clear(_sg_pipeline_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_clear(ref, sizeof(_sg_pipeline_ref_t));
+}
+
+_SOKOL_PRIVATE _sg_buffer_t* _sg_buffer_ref_lookup(const _sg_buffer_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_buffer_t* ptr = _sg_lookup_buffer(&_sg.pools, ref->id);
+ return (ptr && ptr->slot.uninit_count == ref->uninit_count) ? ptr : 0;
+}
+
+_SOKOL_PRIVATE _sg_image_t* _sg_image_ref_lookup(const _sg_image_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_image_t* ptr = _sg_lookup_image(&_sg.pools, ref->id);
+ return (ptr && ptr->slot.uninit_count == ref->uninit_count) ? ptr : 0;
+}
+
+_SOKOL_PRIVATE _sg_shader_t* _sg_shader_ref_lookup(const _sg_shader_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_shader_t* ptr = _sg_lookup_shader(&_sg.pools, ref->id);
+ return (ptr && ptr->slot.uninit_count == ref->uninit_count) ? ptr : 0;
+}
+
+_SOKOL_PRIVATE _sg_pipeline_t* _sg_pipeline_ref_lookup(const _sg_pipeline_ref_t* ref) {
+ SOKOL_ASSERT(ref);
+ _sg_pipeline_t* ptr = _sg_lookup_pipeline(&_sg.pools, ref->id);
+ return (ptr && ptr->slot.uninit_count == ref->uninit_count) ? ptr : 0;
+}
+
// ████████ ██████ █████ ██████ ██ ██ ███████ ██████
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
// ██ ██████ ███████ ██ █████ █████ ██████
@@ -21667,6 +21786,7 @@ SOKOL_API_IMPL sg_buffer_info sg_query_buffer_info(sg_buffer buf_id) {
if (buf) {
info.slot.state = buf->slot.state;
info.slot.res_id = buf->slot.id;
+ info.slot.uninit_count = buf->slot.uninit_count;
info.update_frame_index = buf->cmn.update_frame_index;
info.append_frame_index = buf->cmn.append_frame_index;
info.append_pos = buf->cmn.append_pos;
@@ -21690,6 +21810,7 @@ SOKOL_API_IMPL sg_image_info sg_query_image_info(sg_image img_id) {
if (img) {
info.slot.state = img->slot.state;
info.slot.res_id = img->slot.id;
+ info.slot.uninit_count = img->slot.uninit_count;
info.upd_frame_index = img->cmn.upd_frame_index;
#if defined(SOKOL_D3D11)
info.num_slots = 1;
@@ -21710,6 +21831,7 @@ SOKOL_API_IMPL sg_sampler_info sg_query_sampler_info(sg_sampler smp_id) {
if (smp) {
info.slot.state = smp->slot.state;
info.slot.res_id = smp->slot.id;
+ info.slot.uninit_count = smp->slot.uninit_count;
}
return info;
}
@@ -21722,6 +21844,7 @@ SOKOL_API_IMPL sg_shader_info sg_query_shader_info(sg_shader shd_id) {
if (shd) {
info.slot.state = shd->slot.state;
info.slot.res_id = shd->slot.id;
+ info.slot.uninit_count = shd->slot.uninit_count;
}
return info;
}
@@ -21734,6 +21857,7 @@ SOKOL_API_IMPL sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip_id) {
if (pip) {
info.slot.state = pip->slot.state;
info.slot.res_id = pip->slot.id;
+ info.slot.uninit_count = pip->slot.uninit_count;
}
return info;
}
@@ -21746,6 +21870,7 @@ SOKOL_API_IMPL sg_attachments_info sg_query_attachments_info(sg_attachments atts
if (atts) {
info.slot.state = atts->slot.state;
info.slot.res_id = atts->slot.id;
+ info.slot.uninit_count = atts->slot.uninit_count;
}
return info;
}
diff --git a/tests/functional/sokol_gfx_test.c b/tests/functional/sokol_gfx_test.c
index 82742b8d..4b8694d5 100644
--- a/tests/functional/sokol_gfx_test.c
+++ b/tests/functional/sokol_gfx_test.c
@@ -1341,6 +1341,95 @@ UTEST(sokol_gfx, attachments_resource_states) {
sg_shutdown();
}
+UTEST(sokol_gfx, buffer_uninit_count) {
+ setup(&(sg_desc){0});
+ const sg_buffer_desc desc = { .usage.stream_update = true, .size = 128 };
+ sg_buffer buf = sg_make_buffer(&desc);
+ T(sg_query_buffer_info(buf).slot.uninit_count == 0);
+ sg_uninit_buffer(buf);
+ T(sg_query_buffer_info(buf).slot.uninit_count == 1);
+ sg_init_buffer(buf, &desc);
+ T(sg_query_buffer_info(buf).slot.uninit_count == 1);
+ sg_uninit_buffer(buf);
+ T(sg_query_buffer_info(buf).slot.uninit_count == 2);
+ sg_dealloc_buffer(buf);
+ T(sg_query_buffer_info(buf).slot.uninit_count == 0);
+ sg_shutdown();
+}
+
+UTEST(sokol_gfx, image_uninit_count) {
+ setup(&(sg_desc){0});
+ const sg_image_desc desc = { .usage.render_attachment = true, .width = 128, .height = 128 };
+ sg_image img = sg_make_image(&desc);
+ T(sg_query_image_info(img).slot.uninit_count == 0);
+ sg_uninit_image(img);
+ T(sg_query_image_info(img).slot.uninit_count == 1);
+ sg_init_image(img, &desc);
+ T(sg_query_image_info(img).slot.uninit_count == 1);
+ sg_uninit_image(img);
+ T(sg_query_image_info(img).slot.uninit_count == 2);
+ sg_dealloc_image(img);
+ T(sg_query_image_info(img).slot.uninit_count == 0);
+ sg_shutdown();
+}
+
+UTEST(sokol_gfx, shader_uninit_count) {
+ setup(&(sg_desc){0});
+ const sg_shader_desc desc = {0};
+ sg_shader shd = sg_make_shader(&desc);
+ T(sg_query_shader_info(shd).slot.uninit_count == 0);
+ sg_uninit_shader(shd);
+ T(sg_query_shader_info(shd).slot.uninit_count == 1);
+ sg_init_shader(shd, &desc);
+ T(sg_query_shader_info(shd).slot.uninit_count == 1);
+ sg_uninit_shader(shd);
+ T(sg_query_shader_info(shd).slot.uninit_count == 2);
+ sg_dealloc_shader(shd);
+ T(sg_query_shader_info(shd).slot.uninit_count == 0);
+ sg_shutdown();
+}
+
+UTEST(sokol_gfx, pipeline_uninit_count) {
+ setup(&(sg_desc){0});
+ const sg_pipeline_desc desc = { .shader = sg_make_shader(&(sg_shader_desc){0}) };
+ sg_pipeline pip = sg_make_pipeline(&desc);
+ T(sg_query_pipeline_info(pip).slot.uninit_count == 0);
+ sg_uninit_pipeline(pip);
+ T(sg_query_pipeline_info(pip).slot.uninit_count == 1);
+ sg_init_pipeline(pip, &desc);
+ T(sg_query_pipeline_info(pip).slot.uninit_count == 1);
+ sg_uninit_pipeline(pip);
+ T(sg_query_pipeline_info(pip).slot.uninit_count == 2);
+ sg_dealloc_pipeline(pip);
+ T(sg_query_pipeline_info(pip).slot.uninit_count == 0);
+ sg_shutdown();
+}
+
+UTEST(sokol_gfx, atachments_uninit_count) {
+ setup(&(sg_desc){0});
+ const sg_image_desc img_desc = {
+ .usage.render_attachment = true,
+ .width = 128,
+ .height = 128,
+ };
+ const sg_attachments_desc desc = {
+ .colors = {
+ [0].image = sg_make_image(&img_desc),
+ }
+ };
+ sg_attachments atts = sg_make_attachments(&desc);
+ T(sg_query_attachments_info(atts).slot.uninit_count == 0);
+ sg_uninit_attachments(atts);
+ T(sg_query_attachments_info(atts).slot.uninit_count == 1);
+ sg_init_attachments(atts, &desc);
+ T(sg_query_attachments_info(atts).slot.uninit_count == 1);
+ sg_uninit_attachments(atts);
+ T(sg_query_attachments_info(atts).slot.uninit_count == 2);
+ sg_dealloc_attachments(atts);
+ T(sg_query_attachments_info(atts).slot.uninit_count == 0);
+ sg_shutdown();
+}
+
UTEST(sokol_gfx, query_buffer_will_overflow) {
setup(&(sg_desc){0});
sg_buffer buf = sg_make_buffer(&(sg_buffer_desc){
diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h
index 2ba3a2e9..e023d7e5 100644
--- a/util/sokol_gfx_imgui.h
+++ b/util/sokol_gfx_imgui.h
@@ -1144,6 +1144,7 @@ _SOKOL_PRIVATE const char* _sgimgui_resourcestate_string(sg_resource_state s) {
_SOKOL_PRIVATE void _sgimgui_draw_resource_slot(const sg_slot_info* slot) {
igText("ResId: %08X", slot->res_id);
igText("State: %s", _sgimgui_resourcestate_string(slot->state));
+ igText("Uninit Count: %d", slot->uninit_count);
}
_SOKOL_PRIVATE const char* _sgimgui_backend_string(sg_backend b) {