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
This commit is contained in:
PyryM 2017-04-06 21:59:30 -04:00 committed by Branimir Karadžić
parent 9b218c9644
commit 83e30ec609
7 changed files with 151 additions and 12 deletions

View File

@ -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 };

View File

@ -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);

View File

@ -5938,14 +5938,34 @@ 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)
{
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
{
m_textureStage.m_srv[stage] = NULL;

View File

@ -5299,6 +5299,10 @@ data.NumQualityLevels = 0;
{
const Binding& bind = draw.m_bind[stage];
if (invalidHandle != bind.m_idx)
{
switch (bind.m_type)
{
case Binding::Texture:
{
TextureD3D12& texture = m_textures[bind.m_idx];
texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
@ -5306,9 +5310,35 @@ data.NumQualityLevels = 0;
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)
) & (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
{
bx::memCopy(&srvHandle[stage], &srvHandle[0], sizeof(D3D12_GPU_DESCRIPTOR_HANDLE) );

View File

@ -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)

View File

@ -6988,14 +6988,38 @@ 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)
{
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;
}
}
}
current = bind;

View File

@ -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)