#1547·sokol

Brain dump new resource update api

Author: flooohCreated Jul 8, 2026Updated Sep 15, 2026
Labelssokol-gfx

Write-Transient vs Copy-Src vs Copy-Dst resource usage

Replace the current .dynamic_update and .stream_update usages:

c
sg_buffer/image_usage {
    // ...
    .write_transient = true/false,
    .copy_src = true/false,
    .copy_dst = true/false,
};

Write-Transient behaviour:

  • can only be written once per resource and frame
  • no random placement, data must be written from start, but less data can be written than resource size
  • written data must be 'consumed' in the same frame (it won't survive into the next frame)
  • depending on backend a sokol-gfx transient resource may not even have a unique backing resource, the data may be written into a unified staging buffer
  • write_transient usage can be combined with copy_src, but not copy_dst.

'Consuming' the transient-write data means:

  • for buffers (but not images): can be bound directly as rendering/compute resource
  • can the be source of a copy-operation (for images that's the only operation that makes sense)

Associated sokol-gfx functions:

c
sg_write_buffer(sg_buffer buf, const sg_range* data);
c
sg_write_image(sg_image img, const sg_image_data* data);

Copy behaviour:

Copy data on the GPU between resources with random source and destination locations. The only way to upload CPU-side data persistently and piece-wise into a GPU resource to first write the CPU-side data into a transient resource, and then do a copy-operation on the GPU (this pretty much mimicks the upload via staging buffer in modern 3D APIs).

Associated sokol-gfx functions:

c
sg_copy_buffer_to_buffer(&(sg_copy_buffer_to_buffer_desc){
    .src = {
        .buffer = ...,  // must have .copy_src usage
        .offset = ...,
    },
    .dst = {
        .buffer = ..., // must have copy_dst usage
        .offset = ...,
    },
    .size = ....,
});
c
sg_copy_buffer_to_image(&(sg_copy_buffer_to_image_desc){
    .src = {
        .buffer = ...,  // must have .copy_src usage
        .offset = ...,
        .range = { .ptr = ..., .size = ... }, // source data chunk
    },
    .dst = {
        .image = ..., // must have .copy_dst usage
        ???
    },
});
c
sg_copy_image_to_image(&(sg_copy_image_to_image_desc){
    .src = {
        .image = ..., // must have .copy_src usage
       ???
    },
    .dst = {
        .image = ..., // must have .copy_dst usage
        ???
    },
});
c
sg_copy_image_to_buffer(&(sg_copy_image_to_buffer_desc){
    .src = {
        .image = ..., // must have .copy_src usage
        ???
    },
    .dst = {
        .buffer = ..., // must have copy_dst usage
        .offset = ...,
    },
});

To be defined

  • GPU vs CPU timelines...
    • is are write operations allowed within passes? (ideally yes but they may be moved in front of all render commands in the frame)
    • are copy operations allowed in passes? copy operations must be able to consume a former write operation, the output of a former pass, and in compute passes ideally the result of a former dispatch within the same pass... possible on all backend APIs or needs more restrictions?
  • read operations? (GPU => CPU)
  • should the be an sg_clear_buffer() and sg_clear_image()?