aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2025-11-08 11:23:01 +0100
committerAndre Weissflog <floooh@gmail.com>2025-11-08 11:23:01 +0100
commita37bfc56b519112ff246322bb0425836d062f7b2 (patch)
tree62e8523a1017720a16a27e9c9170dc7591567616
parent1b7928613d8c0d96498a683a4ac10c0965f0bcb5 (diff)
sokol_gfx.h vk: buffer memory barriers wip
-rw-r--r--sokol_gfx.h141
1 files changed, 105 insertions, 36 deletions
diff --git a/sokol_gfx.h b/sokol_gfx.h
index 1937fb92..ab07b354 100644
--- a/sokol_gfx.h
+++ b/sokol_gfx.h
@@ -18606,6 +18606,26 @@ _SOKOL_PRIVATE VkImageLayout _sg_vk_image_layout(_sg_vk_access_t access) {
}
}
+_SOKOL_PRIVATE void _sg_vk_memory_barrier(VkCommandBuffer cmd_buf, _sg_vk_access_t old_access, _sg_vk_access_t new_access) {
+ SOKOL_ASSERT(cmd_buf);
+ if (_sg_vk_is_read_access(old_access) && _sg_vk_is_read_access(new_access)) {
+ return;
+ }
+ VkMemoryBarrier2 barrier;
+ _sg_clear(&barrier, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
+ barrier.srcStageMask = _sg_vk_src_stage_mask(old_access);
+ barrier.srcAccessMask = _sg_vk_src_access_mask(old_access);
+ barrier.dstStageMask = _sg_vk_dst_stage_mask(new_access);
+ barrier.dstAccessMask = _sg_vk_dst_access_mask(new_access);
+ VkDependencyInfo dep_info;
+ _sg_clear(&dep_info, sizeof(dep_info));
+ dep_info.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dep_info.memoryBarrierCount = 1;
+ dep_info.pMemoryBarriers = &barrier;
+ vkCmdPipelineBarrier2(cmd_buf, &dep_info);
+}
+
_SOKOL_PRIVATE void _sg_vk_swapchain_barrier(VkCommandBuffer cmd_buf, VkImage vkimg, _sg_vk_access_t old_access, _sg_vk_access_t new_access) {
SOKOL_ASSERT(cmd_buf);
VkImageMemoryBarrier2 barrier;
@@ -18674,29 +18694,75 @@ _SOKOL_PRIVATE void _sg_vk_image_barrier(VkCommandBuffer cmd_buf, _sg_image_t* i
img->vk.cur_access = new_access;
}
-_SOKOL_PRIVATE void _sg_vk_buffer_barrier(VkCommandBuffer cmd_buf, _sg_buffer_t* buf, _sg_vk_access_t new_access) {
- SOKOL_ASSERT(cmd_buf && buf && buf->vk.buf);
- if (_sg_vk_is_read_access(buf->vk.cur_access) && _sg_vk_is_read_access(new_access)) {
- return;
+
+_SOKOL_PRIVATE void _sg_vk_buffer_bindings_barriers(VkCommandBuffer cmd_buf, const _sg_bindings_ptrs_t* bnd) {
+ SOKOL_ASSERT(bnd && bnd->pip);
+
+ // NOTE: all buffer access transitions are handled through a single memory barrier
+ // (see: https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/)
+ const _sg_shader_t* shd = _sg_shader_ref_ptr(&bnd->pip->cmn.shader);
+ // gather current access types for all buffers and clear their cur_access field
+ _sg_vk_access_t cur_access_bits = 0;
+ for (size_t i = 0; i < SG_MAX_VERTEXBUFFER_BINDSLOTS; i++) {
+ if (bnd->vbs[i]) {
+ cur_access_bits |= bnd->vbs[i]->vk.cur_access;
+ bnd->vbs[i]->vk.cur_access = 0;
+ }
+ }
+ if (bnd->ib) {
+ cur_access_bits |= bnd->ib->vk.cur_access;
+ bnd->ib->vk.cur_access = 0;
+ }
+ for (size_t i = 0; i < SG_MAX_VIEW_BINDSLOTS; i++) {
+ if (bnd->views[i] && (bnd->views[i]->cmn.type == SG_VIEWTYPE_STORAGEBUFFER)) {
+ _sg_buffer_t* buf = _sg_buffer_ref_ptr(&bnd->views[i]->cmn.buf.ref);
+ cur_access_bits |= buf->vk.cur_access;
+ buf->vk.cur_access = 0;
+ }
+ }
+
+ // gather next access type for all buffers and update their cur_access field
+ _sg_vk_access_t next_access_bits = 0;
+ for (size_t i = 0; i < SG_MAX_VERTEXBUFFER_BINDSLOTS; i++) {
+ if (bnd->vbs[i]) {
+ bnd->vbs[i]->vk.cur_access |= _SG_VK_ACCESS_VERTEXBUFFER;
+ next_access_bits |= _SG_VK_ACCESS_VERTEXBUFFER;
+ }
+ }
+ if (bnd->ib) {
+ bnd->ib->vk.cur_access |= _SG_VK_ACCESS_INDEXBUFFER;
+ next_access_bits |= _SG_VK_ACCESS_INDEXBUFFER;
+ }
+ for (size_t i = 0; i < SG_MAX_VIEW_BINDSLOTS; i++) {
+ if (bnd->views[i] && (bnd->views[i]->cmn.type == SG_VIEWTYPE_STORAGEBUFFER)) {
+ _sg_buffer_t* buf = _sg_buffer_ref_ptr(&bnd->views[i]->cmn.buf.ref);
+ if (shd->cmn.views[i].sbuf_readonly) {
+ buf->vk.cur_access |= _SG_VK_ACCESS_STORAGEBUFFER_RO;
+ next_access_bits |= _SG_VK_ACCESS_STORAGEBUFFER_RO;
+ } else {
+ buf->vk.cur_access |= _SG_VK_ACCESS_STORAGEBUFFER_RW;
+ next_access_bits |= _SG_VK_ACCESS_STORAGEBUFFER_RW;
+ }
+ }
+ }
+ _sg_vk_memory_barrier(cmd_buf, cur_access_bits, next_access_bits);
+}
+
+_SOKOL_PRIVATE void _sg_vk_image_bindings_barriers(const _sg_bindings_ptrs_t* bnd, bool is_compute_pass) {
+ if (is_compute_pass) {
+ SOKOL_ASSERT(false && "FIXME");
+ } else {
+ // all images used as textures must already be in texture access state
+ for (size_t i = 0; i < SG_MAX_VIEW_BINDSLOTS; i++) {
+ const _sg_view_t* view = bnd->views[i];
+ if (view) {
+ if (view->cmn.type == SG_VIEWTYPE_TEXTURE) {
+ const _sg_image_t* img = _sg_image_ref_ptr(&view->cmn.img.ref);
+ SOKOL_ASSERT(img->vk.cur_access == _SG_VK_ACCESS_TEXTURE);
+ }
+ }
+ }
}
- VkBufferMemoryBarrier2 barrier;
- barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2;
- barrier.srcStageMask = _sg_vk_src_stage_mask(buf->vk.cur_access);
- barrier.srcAccessMask = _sg_vk_src_access_mask(buf->vk.cur_access);
- barrier.dstStageMask = _sg_vk_dst_stage_mask(new_access);
- barrier.dstAccessMask = _sg_vk_dst_access_mask(new_access);
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.buffer = buf->vk.buf;
- barrier.offset = 0;
- barrier.size = (VkDeviceSize)buf->cmn.size;
- VkDependencyInfo dep_info;
- _sg_clear(&dep_info, sizeof(dep_info));
- dep_info.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dep_info.bufferMemoryBarrierCount = 1;
- dep_info.pBufferMemoryBarriers = &barrier;
- vkCmdPipelineBarrier2(cmd_buf, &dep_info);
- buf->vk.cur_access = new_access;
}
_SOKOL_PRIVATE int _sg_vk_mem_find_memory_type_index(uint32_t type_filter, VkMemoryPropertyFlags props) {
@@ -19318,9 +19384,9 @@ _SOKOL_PRIVATE void _sg_vk_bind_before_submit(void) {
_sg_vk_shared_buffer_before_submit(&_sg.vk.bind);
}
-_SOKOL_PRIVATE bool _sg_vk_bind_view_smp_descriptor_set(const _sg_bindings_ptrs_t* bnd, VkPipelineBindPoint vk_bind_point) {
+_SOKOL_PRIVATE bool _sg_vk_bind_view_smp_descriptor_set(VkCommandBuffer cmd_buf, const _sg_bindings_ptrs_t* bnd, VkPipelineBindPoint vk_bind_point) {
SOKOL_ASSERT(_sg.vk.dev);
- SOKOL_ASSERT(_sg.vk.frame.cmd_buf);
+ SOKOL_ASSERT(cmd_buf);
SOKOL_ASSERT(bnd && bnd->pip);
const _sg_shader_t* shd = _sg_shader_ref_ptr(&bnd->pip->cmn.shader);
@@ -19365,7 +19431,7 @@ _SOKOL_PRIVATE bool _sg_vk_bind_view_smp_descriptor_set(const _sg_bindings_ptrs_
const uint32_t dbuf_index = 0;
SOKOL_ASSERT(shd->vk.pip_layout);
_sg.vk.ext.cmd_set_descriptor_buffer_offsets(
- _sg.vk.frame.cmd_buf,
+ cmd_buf,
vk_bind_point,
shd->vk.pip_layout,
_SG_VK_VIEW_SMP_DESCRIPTORSET_INDEX, // firstSet
@@ -19376,8 +19442,8 @@ _SOKOL_PRIVATE bool _sg_vk_bind_view_smp_descriptor_set(const _sg_bindings_ptrs_
return true;
}
-_SOKOL_PRIVATE bool _sg_vk_bind_uniform_descriptor_set(void) {
- SOKOL_ASSERT(_sg.vk.frame.cmd_buf);
+_SOKOL_PRIVATE bool _sg_vk_bind_uniform_descriptor_set(VkCommandBuffer cmd_buf) {
+ SOKOL_ASSERT(cmd_buf);
SOKOL_ASSERT(_sg.vk.uniforms_dirty);
_sg.vk.uniforms_dirty = false;
const _sg_pipeline_t* pip = _sg_pipeline_ref_ptr(&_sg.cur_pip);
@@ -19409,7 +19475,7 @@ _SOKOL_PRIVATE bool _sg_vk_bind_uniform_descriptor_set(void) {
const uint32_t dbuf_index = 0;
SOKOL_ASSERT(shd->vk.pip_layout);
_sg.vk.ext.cmd_set_descriptor_buffer_offsets(
- _sg.vk.frame.cmd_buf,
+ cmd_buf,
vk_bind_point,
shd->vk.pip_layout,
_SG_VK_UB_DESCRIPTORSET_INDEX, // firstIndex
@@ -21168,9 +21234,11 @@ _SOKOL_PRIVATE bool _sg_vk_apply_bindings(_sg_bindings_ptrs_t* bnd) {
SOKOL_ASSERT(bnd && bnd->pip);
SOKOL_ASSERT(_sg.vk.dev);
SOKOL_ASSERT(_sg.vk.frame.cmd_buf);
+ VkCommandBuffer cmd_buf = _sg.vk.frame.cmd_buf;
- // FIXME FIXME FIXME:
- // update barriers (in compute passes) or verify access type (in render pass)
+ // insert barriers as needed
+ _sg_vk_buffer_bindings_barriers(cmd_buf, bnd);
+ _sg_vk_image_bindings_barriers(bnd, _sg.cur_pass.is_compute);
if (!_sg.cur_pass.is_compute) {
// bind vertex buffers
@@ -21181,14 +21249,14 @@ _SOKOL_PRIVATE bool _sg_vk_apply_bindings(_sg_bindings_ptrs_t* bnd) {
if (bnd->vbs[i]) {
VkBuffer vk_buf = bnd->vbs[i]->vk.buf;
VkDeviceSize vk_offset = (VkDeviceSize)bnd->vb_offsets[i];
- vkCmdBindVertexBuffers(_sg.vk.frame.cmd_buf, i, 1, &vk_buf, &vk_offset);
+ vkCmdBindVertexBuffers(cmd_buf, i, 1, &vk_buf, &vk_offset);
}
}
if (bnd->ib) {
VkBuffer vk_buf = bnd->ib->vk.buf;
VkDeviceSize vk_offset = (VkDeviceSize)bnd->ib_offset;
VkIndexType vk_index_type = _sg_vk_index_type(bnd->pip->cmn.index_type);
- vkCmdBindIndexBuffer(_sg.vk.frame.cmd_buf, vk_buf, vk_offset, vk_index_type);
+ vkCmdBindIndexBuffer(cmd_buf, vk_buf, vk_offset, vk_index_type);
}
}
@@ -21196,7 +21264,7 @@ _SOKOL_PRIVATE bool _sg_vk_apply_bindings(_sg_bindings_ptrs_t* bnd) {
const VkPipelineBindPoint pip_bind_point = _sg.cur_pass.is_compute
? VK_PIPELINE_BIND_POINT_COMPUTE
: VK_PIPELINE_BIND_POINT_GRAPHICS;
- return _sg_vk_bind_view_smp_descriptor_set(bnd, pip_bind_point);
+ return _sg_vk_bind_view_smp_descriptor_set(cmd_buf, bnd, pip_bind_point);
}
_SOKOL_PRIVATE void _sg_vk_apply_uniforms(int ub_slot, const sg_range* data) {
@@ -21218,20 +21286,21 @@ _SOKOL_PRIVATE void _sg_vk_apply_uniforms(int ub_slot, const sg_range* data) {
_SOKOL_PRIVATE void _sg_vk_draw(int base_element, int num_elements, int num_instances, int base_vertex, int base_instance) {
SOKOL_ASSERT(_sg.vk.frame.cmd_buf);
+ VkCommandBuffer cmd_buf = _sg.vk.frame.cmd_buf;
if (_sg.vk.uniforms_dirty) {
- if (!_sg_vk_bind_uniform_descriptor_set()) {
+ if (!_sg_vk_bind_uniform_descriptor_set(cmd_buf)) {
return;
}
}
if (_sg.use_indexed_draw) {
- vkCmdDrawIndexed(_sg.vk.frame.cmd_buf,
+ vkCmdDrawIndexed(cmd_buf,
(uint32_t)num_elements,
(uint32_t)num_instances,
(uint32_t)base_element,
base_vertex,
(uint32_t)base_instance);
} else {
- vkCmdDraw(_sg.vk.frame.cmd_buf,
+ vkCmdDraw(cmd_buf,
(uint32_t)num_elements,
(uint32_t)num_instances,
(uint32_t)base_element,