From 83e30ec609194824a4724af1f882ab2a28c50a0c Mon Sep 17 00:00:00 2001 From: PyryM Date: Thu, 6 Apr 2017 21:59:30 -0400 Subject: [PATCH] api changes (#1107) d3d11 + opengl implementations everything else will have very strange behavior if you try to bind a buffer to a shader avoid compiler error/warning about unused parameter copy paste mistake add in function for index buffers as well Might as well cover all the bases; index buffers are also a convenient way to create int-typed buffers, since there aren't int32 vertex attributes. get rid of precision loss warnings d3d12 bindShaderBuffer implementation throw an assert on d3d9 at least BX_CHECK on metal as well (no compute support atm) simplify api since access is restricted to read hide from public api at the moment move comment into correct branch of if Feature: bind vertex/index buffers for vertex/fragment shaders --- src/bgfx.cpp | 26 ++++++++++++++++++++++++ src/bgfx_p.h | 34 +++++++++++++++++++++++++++++++ src/renderer_d3d11.cpp | 24 ++++++++++++++++++++-- src/renderer_d3d12.cpp | 46 ++++++++++++++++++++++++++++++++++-------- src/renderer_d3d9.cpp | 3 +++ src/renderer_gl.cpp | 28 +++++++++++++++++++++++-- src/renderer_mtl.mm | 2 ++ 7 files changed, 151 insertions(+), 12 deletions(-) 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)