From 66c72b149fdc9e8ab1ad4d2554fd1050ca36ea03 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 00:23:39 +0300 Subject: [PATCH] sokol: fix issue with sokol and stbi opening images (fixes #22064) --- vlib/sokol/gfx/gfx.c.v | 24 ++++++++++++++++++++++++ vlib/sokol/gfx/gfx_test.v | 26 ++++++++++++++++++++++++++ vlib/stbi/README.md | 1 + 3 files changed, 51 insertions(+) create mode 100644 vlib/sokol/gfx/gfx_test.v diff --git a/vlib/sokol/gfx/gfx.c.v b/vlib/sokol/gfx/gfx.c.v index a627c7bf5..37fdfcf52 100644 --- a/vlib/sokol/gfx/gfx.c.v +++ b/vlib/sokol/gfx/gfx.c.v @@ -32,34 +32,57 @@ pub fn is_valid() bool { return C.sg_isvalid() } +@[inline] +fn ensure_initialized(op string) { + if is_valid() { + return + } + panic('sokol.gfx is not initialized; call gfx.setup(...) before ${op}') +} + @[inline] pub fn reset_state_cache() { C.sg_reset_state_cache() } // resource creation, destruction and updating +// make_buffer creates a GPU buffer. +// make_buffer requires `gfx.setup(...)` to have completed first. @[inline] pub fn make_buffer(desc &BufferDesc) Buffer { + ensure_initialized('gfx.make_buffer(...)') return C.sg_make_buffer(desc) } +// make_image creates a GPU image. +// make_image requires `gfx.setup(...)` to have completed first. @[inline] pub fn make_image(desc &ImageDesc) Image { + ensure_initialized('gfx.make_image(...)') return C.sg_make_image(desc) } +// make_sampler creates a GPU sampler. +// make_sampler requires `gfx.setup(...)` to have completed first. @[inline] pub fn make_sampler(desc &SamplerDesc) Sampler { + ensure_initialized('gfx.make_sampler(...)') return C.sg_make_sampler(desc) } +// make_shader creates a GPU shader. +// make_shader requires `gfx.setup(...)` to have completed first. @[inline] pub fn make_shader(desc &ShaderDesc) Shader { + ensure_initialized('gfx.make_shader(...)') return C.sg_make_shader(desc) } +// make_pipeline creates a GPU pipeline. +// make_pipeline requires `gfx.setup(...)` to have completed first. @[inline] pub fn make_pipeline(desc &PipelineDesc) Pipeline { + ensure_initialized('gfx.make_pipeline(...)') return C.sg_make_pipeline(desc) } @@ -67,6 +90,7 @@ pub fn make_pipeline(desc &PipelineDesc) Pipeline { // See also: documentation at the top of thirdparty/sokol/sokol_gfx.h @[inline] pub fn make_attachments(const_desc &AttachmentsDesc) Attachments { + ensure_initialized('gfx.make_attachments(...)') return C.sg_make_attachments(const_desc) } diff --git a/vlib/sokol/gfx/gfx_test.v b/vlib/sokol/gfx/gfx_test.v new file mode 100644 index 000000000..6aa89d971 --- /dev/null +++ b/vlib/sokol/gfx/gfx_test.v @@ -0,0 +1,26 @@ +module gfx + +import os + +fn assert_program_panics(source string, expected string) { + source_path := os.join_path(os.temp_dir(), + 'sokol_gfx_make_image_requires_setup_${os.getpid()}.v') + os.write_file(source_path, source) or { panic(err) } + defer { + os.rm(source_path) or {} + } + res := os.execute('${os.quoted_path(@VEXE)} run ${os.quoted_path(source_path)}') + assert res.exit_code != 0, 'expected the test program to fail' + assert res.output.contains(expected), 'expected `${expected}` in `${res.output}`' +} + +fn test_make_image_requires_setup() { + assert_program_panics('import sokol.gfx + +fn main() { + mut desc := gfx.ImageDesc{} + _ = gfx.make_image(&desc) +} +', + 'sokol.gfx is not initialized; call gfx.setup(...) before gfx.make_image(...)') +} diff --git a/vlib/stbi/README.md b/vlib/stbi/README.md index 3bb5bc946..985487369 100644 --- a/vlib/stbi/README.md +++ b/vlib/stbi/README.md @@ -10,3 +10,4 @@ channel count from the source file as metadata. When uploading to `sokol.gfx`, size the upload from `width * height * nr_channels`. If you load with `desired_channels: 0`, convert the data yourself or use a matching pixel format before creating a texture. +Also call `gfx.setup(...)` before `gfx.make_image(...)` and `gfx.make_sampler(...)`. -- 2.39.5