diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 2badfc2f3..a4c5db6b9 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -3818,6 +3818,20 @@ error: s_ctx->setBuffer(_stage, _handle, _access); } + void setShaderBuffer(uint8_t _stage, DynamicIndexBufferHandle _handle) + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(_stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, "Invalid stage %d (max %d).", _stage, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS); + s_ctx->setShaderBuffer(_stage, _handle); + } + + void setShaderBuffer(uint8_t _stage, DynamicVertexBufferHandle _handle) + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(_stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, "Invalid stage %d (max %d).", _stage, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS); + s_ctx->setShaderBuffer(_stage, _handle); + } + void setBuffer(uint8_t _stage, IndirectBufferHandle _handle, Access::Enum _access) { BGFX_CHECK_MAIN_THREAD(); @@ -4838,6 +4852,18 @@ BGFX_C_API void bgfx_set_compute_dynamic_vertex_buffer(uint8_t _stage, bgfx_dyna bgfx::setBuffer(_stage, handle.cpp, bgfx::Access::Enum(_access) ); } +BGFX_C_API void bgfx_set_shader_dynamic_index_buffer(uint8_t _stage, bgfx_dynamic_index_buffer_handle_t _handle) +{ + union { bgfx_dynamic_index_buffer_handle_t c; bgfx::DynamicIndexBufferHandle cpp; } handle = { _handle }; + bgfx::setShaderBuffer(_stage, handle.cpp); +} + +BGFX_C_API void bgfx_set_shader_dynamic_vertex_buffer(uint8_t _stage, bgfx_dynamic_vertex_buffer_handle_t _handle) +{ + union { bgfx_dynamic_vertex_buffer_handle_t c; bgfx::DynamicVertexBufferHandle cpp; } handle = { _handle }; + bgfx::setShaderBuffer(_stage, handle.cpp); +} + BGFX_C_API void bgfx_set_compute_indirect_buffer(uint8_t _stage, bgfx_indirect_buffer_handle_t _handle, bgfx_access_t _access) { union { bgfx_indirect_buffer_handle_t c; bgfx::IndirectBufferHandle cpp; } handle = { _handle }; diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 8aa10b21b..f3e645046 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1677,6 +1677,26 @@ namespace bgfx bind.m_un.m_compute.m_mip = 0; } + void setShaderBuffer(uint8_t _stage, IndexBufferHandle _handle) + { + Binding& bind = m_draw.m_bind[_stage]; + bind.m_idx = _handle.idx; + bind.m_type = uint8_t(Binding::IndexBuffer); + bind.m_un.m_compute.m_access = uint8_t(Access::Read); + + // TODO: should this take in a uniform as well for opengl? + } + + void setShaderBuffer(uint8_t _stage, VertexBufferHandle _handle) + { + Binding& bind = m_draw.m_bind[_stage]; + bind.m_idx = _handle.idx; + bind.m_type = uint8_t(Binding::VertexBuffer); + bind.m_un.m_compute.m_access = uint8_t(Access::Read); + + // TODO: should this take in a uniform as well for opengl? + } + void setImage(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format) { Binding& bind = m_compute.m_bind[_stage]; @@ -4039,6 +4059,20 @@ namespace bgfx m_submit->setBuffer(_stage, dvb.m_handle, _access); } + BGFX_API_FUNC(void setShaderBuffer(uint8_t _stage, DynamicIndexBufferHandle _handle)) + { + BGFX_CHECK_HANDLE("setShaderBuffer", m_dynamicIndexBufferHandle, _handle); + const DynamicIndexBuffer& dib = m_dynamicIndexBuffers[_handle.idx]; + m_submit->setShaderBuffer(_stage, dib.m_handle); + } + + BGFX_API_FUNC(void setShaderBuffer(uint8_t _stage, DynamicVertexBufferHandle _handle) ) + { + BGFX_CHECK_HANDLE("setShaderBuffer", m_dynamicVertexBufferHandle, _handle); + const DynamicVertexBuffer& dvb = m_dynamicVertexBuffers[_handle.idx]; + m_submit->setShaderBuffer(_stage, dvb.m_handle); + } + BGFX_API_FUNC(void setBuffer(uint8_t _stage, IndirectBufferHandle _handle, Access::Enum _access) ) { BGFX_CHECK_HANDLE("setBuffer", m_vertexBufferHandle, _handle); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index cfbfa50ca..b973182f7 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -5938,13 +5938,33 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; if (current.m_idx != bind.m_idx + || current.m_type != bind.m_type || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) { if (invalidHandle != bind.m_idx) { - TextureD3D11& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); + switch (bind.m_type) + { + case Binding::Texture: + { + TextureD3D11& texture = m_textures[bind.m_idx]; + texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); + } + break; + + case Binding::IndexBuffer: + case Binding::VertexBuffer: + { + const BufferD3D11& buffer = Binding::IndexBuffer == bind.m_type + ? m_indexBuffers[bind.m_idx] + : m_vertexBuffers[bind.m_idx] + ; + m_textureStage.m_srv[stage] = buffer.m_srv; + m_textureStage.m_sampler[stage] = NULL; + } + break; + } } else { diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index e469d9880..75c942753 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -5300,14 +5300,44 @@ data.NumQualityLevels = 0; const Binding& bind = draw.m_bind[stage]; if (invalidHandle != bind.m_idx) { - TextureD3D12& texture = m_textures[bind.m_idx]; - texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture); - samplerFlags[stage] = (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & bind.m_un.m_draw.m_textureFlags) - ? bind.m_un.m_draw.m_textureFlags - : texture.m_flags - ) & (BGFX_TEXTURE_SAMPLER_BITS_MASK|BGFX_TEXTURE_BORDER_COLOR_MASK) - ; + switch (bind.m_type) + { + case Binding::Texture: + { + TextureD3D12& texture = m_textures[bind.m_idx]; + texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); + scratchBuffer.allocSrv(srvHandle[stage], texture); + samplerFlags[stage] = (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & bind.m_un.m_draw.m_textureFlags) + ? bind.m_un.m_draw.m_textureFlags + : texture.m_flags + ) & (BGFX_TEXTURE_SAMPLER_BITS_MASK | BGFX_TEXTURE_BORDER_COLOR_MASK) + ; + } + break; + + case Binding::IndexBuffer: + case Binding::VertexBuffer: + { + BufferD3D12& buffer = Binding::IndexBuffer == bind.m_type + ? m_indexBuffers[bind.m_idx] + : m_vertexBuffers[bind.m_idx] + ; + + if (Access::Read != bind.m_un.m_compute.m_access) + { + // The api functions prevent binding with Access::Write, + // but might as well allow it in here for future-proofing + buffer.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + scratchBuffer.allocUav(srvHandle[stage], buffer); + } + else + { + buffer.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); + scratchBuffer.allocSrv(srvHandle[stage], buffer); + } + } + break; + } } else { diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 9f055f250..ba54e375d 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -4094,6 +4094,9 @@ namespace bgfx { namespace d3d9 { const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; + BX_CHECK(Binding::Texture == current.m_type + , "Buffer binding is not supported on DirectX 9."); + if (current.m_idx != bind.m_idx || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 0419c966f..a8884e928 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -6988,13 +6988,37 @@ namespace bgfx { namespace gl const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; if (current.m_idx != bind.m_idx + || current.m_type != bind.m_type || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) { if (invalidHandle != bind.m_idx) { - TextureGL& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); + switch (bind.m_type) + { + case Binding::Texture: + { + TextureGL& texture = m_textures[bind.m_idx]; + texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); + } + break; + + case Binding::IndexBuffer: + { + const IndexBufferGL& buffer = m_indexBuffers[bind.m_idx]; + GL_CHECK(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, stage, buffer.m_id) ); + // TODO: barriers? + } + break; + + case Binding::VertexBuffer: + { + const VertexBufferGL& buffer = m_vertexBuffers[bind.m_idx]; + GL_CHECK(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, stage, buffer.m_id) ); + // TODO: barriers? + } + break; + } } } diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 3f658e0b7..cdd114661 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -3623,6 +3623,8 @@ namespace bgfx { namespace mtl { const Binding& sampler = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; + BX_CHECK(Binding::Texture == current.m_type + , "Buffer binding is not supported on Metal."); if (current.m_idx != sampler.m_idx || current.m_un.m_draw.m_textureFlags != sampler.m_un.m_draw.m_textureFlags || programChanged)