diff options
| author | Andre Weissflog <floooh@gmail.com> | 2025-09-22 17:14:28 +0200 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2025-09-22 17:14:28 +0200 |
| commit | 0202220cf283278099dbe07495c3a488f60a0087 (patch) | |
| tree | e4dfd2333eb898bcc4bee40dc74bf0e1140db07e | |
| parent | ea3ecb9ec18f3921f454393a163dd8c04cfe6a4b (diff) | |
| parent | 4eb7f07783c9a6bb74cc05ced00e5f83d3bd2100 (diff) | |
Merge branch 'master' into issue1302/flexible-bind-limits
| -rw-r--r-- | CHANGELOG.md | 13 | ||||
| -rw-r--r-- | sokol_gfx.h | 85 | ||||
| -rw-r--r-- | tests/test_common.sh | 7 |
3 files changed, 71 insertions, 34 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a3f48c..d5ecc976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ ## Updates +### 22-Sep-2025 + +- sokol_gfx.h d3d11: fix a bug in the d3d11 backend which existed since the 'resource-view-update': + when a compute pass used ping-ponging by alternating two textures as shader-resource-view binding + and unordered-access-view-binding, the D3D11 validation layer would complain that the same resource + is still set as input- or output-resource. This has now been fixed rather crudely by first clearing the + shader resource bindings before setting the unordered-access-bindings when calling sg_apply_bindings() + in a compute pass. IMHO this D3D11 validation layer warning is a false positive though, because at the + time of the next draw call, the chicken-egg-situation has been resolved (since at that point, both the + UAV and SRV bindings have been set correctly). + + PR: https://github.com/floooh/sokol/pull/1333 + ### 15-Sep-2025 - sokol_gfx.h: a minor breaking change which removes a special case for diff --git a/sokol_gfx.h b/sokol_gfx.h index bedbc046..bad3dad3 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -6337,6 +6337,18 @@ typedef struct { HINSTANCE d3dcompiler_dll; bool d3dcompiler_dll_load_failed; pD3DCompile D3DCompile_func; + // static bindings arrays + struct { + ID3D11Buffer* vbs[SG_MAX_VERTEXBUFFER_BINDSLOTS]; + UINT vb_offsets[SG_MAX_VERTEXBUFFER_BINDSLOTS]; + ID3D11ShaderResourceView* vs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS]; + ID3D11ShaderResourceView* fs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS]; + ID3D11ShaderResourceView* cs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS]; + ID3D11UnorderedAccessView* cs_uavs[_SG_D3D11_MAX_STAGE_UAV_BINDINGS]; + ID3D11SamplerState* vs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS]; + ID3D11SamplerState* fs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS]; + ID3D11SamplerState* cs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS]; + } bnd; // global subresourcedata array for texture updates D3D11_SUBRESOURCE_DATA subres_data[_SG_D3D11_MAX_TEXTURE_SUBRESOURCES]; } _sg_d3d11_backend_t; @@ -13560,27 +13572,36 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { const _sg_shader_t* shd = _sg_shader_ref_ptr(&bnd->pip->cmn.shader); const bool is_compute = bnd->pip->cmn.is_compute; + if (is_compute) { + _sg_clear(&_sg.d3d11.bnd.cs_srvs, sizeof(_sg.d3d11.bnd.cs_srvs)); + _sg_clear(&_sg.d3d11.bnd.cs_uavs, sizeof(_sg.d3d11.bnd.cs_uavs)); + _sg_clear(&_sg.d3d11.bnd.cs_smps, sizeof(_sg.d3d11.bnd.cs_smps)); + } else { + _sg_clear(&_sg.d3d11.bnd.vbs, sizeof(_sg.d3d11.bnd.vbs)); + _sg_clear(&_sg.d3d11.bnd.vb_offsets, sizeof(_sg.d3d11.bnd.vb_offsets)); + _sg_clear(&_sg.d3d11.bnd.vs_srvs, sizeof(_sg.d3d11.bnd.vs_srvs)); + _sg_clear(&_sg.d3d11.bnd.fs_srvs, sizeof(_sg.d3d11.bnd.fs_srvs)); + _sg_clear(&_sg.d3d11.bnd.vs_smps, sizeof(_sg.d3d11.bnd.vs_smps)); + _sg_clear(&_sg.d3d11.bnd.fs_smps, sizeof(_sg.d3d11.bnd.fs_smps)); + } + // gather all the D3D11 resources into arrays ID3D11Buffer* d3d11_ib = bnd->ib ? bnd->ib->d3d11.buf : 0; - ID3D11Buffer* d3d11_vbs[SG_MAX_VERTEXBUFFER_BINDSLOTS] = {0}; - UINT d3d11_vb_offsets[SG_MAX_VERTEXBUFFER_BINDSLOTS] = {0}; - ID3D11ShaderResourceView* d3d11_vs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS] = {0}; - ID3D11ShaderResourceView* d3d11_fs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS] = {0}; - ID3D11ShaderResourceView* d3d11_cs_srvs[_SG_D3D11_MAX_STAGE_SRV_BINDINGS] = {0}; - ID3D11UnorderedAccessView* d3d11_cs_uavs[_SG_D3D11_MAX_STAGE_UAV_BINDINGS] = {0}; - ID3D11SamplerState* d3d11_vs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS] = {0}; - ID3D11SamplerState* d3d11_fs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS] = {0}; - ID3D11SamplerState* d3d11_cs_smps[_SG_D3D11_MAX_STAGE_SMP_BINDINGS] = {0}; - - if (!is_compute) { + + if (is_compute) { + // on D3D11 we need to break a chicken-egg-situation where a resource + // may still be set as shader resource view, but is going to be set + // as unordered-access-view, so first clear all shader resource view bindings + _sg_d3d11_CSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, _sg.d3d11.bnd.cs_srvs); + } else { for (size_t i = 0; i < SG_MAX_VERTEXBUFFER_BINDSLOTS; i++) { const _sg_buffer_t* vb = bnd->vbs[i]; if (vb == 0) { continue; } SOKOL_ASSERT(vb->d3d11.buf); - d3d11_vbs[i] = vb->d3d11.buf; - d3d11_vb_offsets[i] = (UINT)bnd->vb_offsets[i]; + _sg.d3d11.bnd.vbs[i] = vb->d3d11.buf; + _sg.d3d11.bnd.vb_offsets[i] = (UINT)bnd->vb_offsets[i]; } } for (size_t i = 0; i < SG_MAX_VIEW_BINDSLOTS; i++) { @@ -13602,9 +13623,9 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { ID3D11ShaderResourceView* d3d11_srv = view->d3d11.srv; SOKOL_ASSERT(d3d11_srv); switch (stage) { - case SG_SHADERSTAGE_VERTEX: d3d11_vs_srvs[d3d11_slot] = d3d11_srv; break; - case SG_SHADERSTAGE_FRAGMENT: d3d11_fs_srvs[d3d11_slot] = d3d11_srv; break; - case SG_SHADERSTAGE_COMPUTE: d3d11_cs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_VERTEX: _sg.d3d11.bnd.vs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_FRAGMENT: _sg.d3d11.bnd.fs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_COMPUTE: _sg.d3d11.bnd.cs_srvs[d3d11_slot] = d3d11_srv; break; default: SOKOL_UNREACHABLE; } } else if (shd_view->view_type == SG_VIEWTYPE_STORAGEBUFFER) { @@ -13614,9 +13635,9 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { ID3D11ShaderResourceView* d3d11_srv = view->d3d11.srv; SOKOL_ASSERT(d3d11_srv); switch (stage) { - case SG_SHADERSTAGE_VERTEX: d3d11_vs_srvs[d3d11_slot] = d3d11_srv; break; - case SG_SHADERSTAGE_FRAGMENT: d3d11_fs_srvs[d3d11_slot] = d3d11_srv; break; - case SG_SHADERSTAGE_COMPUTE: d3d11_cs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_VERTEX: _sg.d3d11.bnd.vs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_FRAGMENT: _sg.d3d11.bnd.fs_srvs[d3d11_slot] = d3d11_srv; break; + case SG_SHADERSTAGE_COMPUTE: _sg.d3d11.bnd.cs_srvs[d3d11_slot] = d3d11_srv; break; default: SOKOL_UNREACHABLE; } } else { @@ -13625,7 +13646,7 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { SOKOL_ASSERT(d3d11_slot < _sg.limits.d3d11_max_unordered_access_views); ID3D11UnorderedAccessView* d3d11_uav = view->d3d11.uav; SOKOL_ASSERT(d3d11_uav); - d3d11_cs_uavs[d3d11_slot] = d3d11_uav; + _sg.d3d11.bnd.cs_uavs[d3d11_slot] = d3d11_uav; } } else if (shd_view->view_type == SG_VIEWTYPE_STORAGEIMAGE) { SOKOL_ASSERT(stage == SG_SHADERSTAGE_COMPUTE); @@ -13633,7 +13654,7 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { SOKOL_ASSERT(d3d11_slot < _sg.limits.d3d11_max_unordered_access_views); ID3D11UnorderedAccessView* d3d11_uav = view->d3d11.uav; SOKOL_ASSERT(d3d11_uav); - d3d11_cs_uavs[d3d11_slot] = d3d11_uav; + _sg.d3d11.bnd.cs_uavs[d3d11_slot] = d3d11_uav; } else SOKOL_UNREACHABLE; } for (size_t i = 0; i < SG_MAX_SAMPLER_BINDSLOTS; i++) { @@ -13648,27 +13669,27 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_ptrs_t* bnd) { SOKOL_ASSERT(smp->d3d11.smp); ID3D11SamplerState* d3d11_smp = smp->d3d11.smp; switch (stage) { - case SG_SHADERSTAGE_VERTEX: d3d11_vs_smps[d3d11_slot] = d3d11_smp; break; - case SG_SHADERSTAGE_FRAGMENT: d3d11_fs_smps[d3d11_slot] = d3d11_smp; break; - case SG_SHADERSTAGE_COMPUTE: d3d11_cs_smps[d3d11_slot] = d3d11_smp; break; + case SG_SHADERSTAGE_VERTEX: _sg.d3d11.bnd.vs_smps[d3d11_slot] = d3d11_smp; break; + case SG_SHADERSTAGE_FRAGMENT: _sg.d3d11.bnd.fs_smps[d3d11_slot] = d3d11_smp; break; + case SG_SHADERSTAGE_COMPUTE: _sg.d3d11.bnd.cs_smps[d3d11_slot] = d3d11_smp; break; default: SOKOL_UNREACHABLE; } } if (is_compute) { SOKOL_ASSERT(_sg.limits.d3d11_max_unordered_access_views <= _SG_D3D11_MAX_STAGE_UAV_BINDINGS); - _sg_d3d11_CSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, d3d11_cs_srvs); - _sg_d3d11_CSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, d3d11_cs_smps); - _sg_d3d11_CSSetUnorderedAccessViews(_sg.d3d11.ctx, 0, _sg.limits.d3d11_max_unordered_access_views, d3d11_cs_uavs, NULL); + _sg_d3d11_CSSetUnorderedAccessViews(_sg.d3d11.ctx, 0, _sg.limits.d3d11_max_unordered_access_views, _sg.d3d11.bnd.cs_uavs, NULL); + _sg_d3d11_CSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, _sg.d3d11.bnd.cs_srvs); + _sg_d3d11_CSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, _sg.d3d11.bnd.cs_smps); _sg_stats_add(d3d11.bindings.num_cs_set_shader_resources, 1); _sg_stats_add(d3d11.bindings.num_cs_set_samplers, 1); _sg_stats_add(d3d11.bindings.num_cs_set_unordered_access_views, 1); } else { - _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEXBUFFER_BINDSLOTS, d3d11_vbs, bnd->pip->d3d11.vb_strides, d3d11_vb_offsets); + _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEXBUFFER_BINDSLOTS, _sg.d3d11.bnd.vbs, bnd->pip->d3d11.vb_strides, _sg.d3d11.bnd.vb_offsets); _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, bnd->pip->d3d11.index_format, (UINT)bnd->ib_offset); - _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, d3d11_vs_srvs); - _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, d3d11_fs_srvs); - _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, d3d11_vs_smps); - _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, d3d11_fs_smps); + _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, _sg.d3d11.bnd.vs_srvs); + _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SRV_BINDINGS, _sg.d3d11.bnd.fs_srvs); + _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, _sg.d3d11.bnd.vs_smps); + _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_STAGE_SMP_BINDINGS, _sg.d3d11.bnd.fs_smps); _sg_stats_add(d3d11.bindings.num_ia_set_vertex_buffers, 1); _sg_stats_add(d3d11.bindings.num_ia_set_index_buffer, 1); _sg_stats_add(d3d11.bindings.num_vs_set_shader_resources, 1); diff --git a/tests/test_common.sh b/tests/test_common.sh index 65b2bafd..def2579e 100644 --- a/tests/test_common.sh +++ b/tests/test_common.sh @@ -3,8 +3,11 @@ setup_emsdk() { mkdir -p build && cd build git clone https://github.com/emscripten-core/emsdk.git cd emsdk - ./emsdk install latest - ./emsdk activate latest + # FIXME: temporarily use emsdk 4.0.14 until spine is fixed + ./emsdk install 4.0.14 + ./emsdk activate 4.0.14 + # ./emsdk install latest + # ./emsdk activate latest cd ../.. fi source build/emsdk/emsdk_env.sh |