Metal: added support for binding buffers to vertex/fragment shader stages

I have removed the SamplerInfo workaround, because new shaderc preserves texture stages. Some shaders needed recompile with latest shaderc to get the new behavior.
This commit is contained in:
attilaz
2019-08-16 15:02:38 +02:00
committed by Бранимир Караџић
parent e0b99aa358
commit 75d5662f0b
56 changed files with 60 additions and 32 deletions

View File

@@ -67,7 +67,7 @@ void openUrl(const bx::StringView& _url)
#if BX_PLATFORM_WINDOWS
void* result = ShellExecuteA(NULL, NULL, tmp, NULL, NULL, false);
BX_UNUSED(result);
#else
#elif !defined(BX_PLATFORM_IOS)
int32_t result = system(tmp);
BX_UNUSED(result);
#endif // BX_PLATFORM_*

View File

@@ -847,13 +847,6 @@ namespace bgfx { namespace mtl
uint16_t m_numThreads[3];
};
struct SamplerInfo
{
uint32_t m_index;
UniformHandle m_uniform;
bool m_fragment;
};
struct PipelineStateMtl;
struct ProgramMtl
@@ -887,7 +880,6 @@ namespace bgfx { namespace mtl
, m_vshConstantBufferAlignmentMask(0)
, m_fshConstantBufferSize(0)
, m_fshConstantBufferAlignmentMask(0)
, m_samplerCount(0)
, m_numPredefined(0)
, m_rps(NULL)
, m_cps(NULL)
@@ -895,6 +887,8 @@ namespace bgfx { namespace mtl
m_numThreads[0] = 1;
m_numThreads[1] = 1;
m_numThreads[2] = 1;
for(uint32_t i=0; i<BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++i)
m_bindingTypes[i] = 0;
}
~PipelineStateMtl()
@@ -923,8 +917,12 @@ namespace bgfx { namespace mtl
uint32_t m_fshConstantBufferSize;
uint32_t m_fshConstantBufferAlignmentMask;
SamplerInfo m_samplers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t m_samplerCount;
enum
{
BindToVertexShader = 1 << 0,
BindToFragmentShader = 1 << 1,
};
uint8_t m_bindingTypes[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint16_t m_numThreads[3];

View File

@@ -1853,6 +1853,20 @@ namespace bgfx { namespace mtl
}
}
}
else if ( arg.type == MTLArgumentTypeBuffer && arg.index > 0 && NULL != arg.bufferStructType)
{
const char* name = utf8String(arg.name);
if (arg.index >= BGFX_CONFIG_MAX_TEXTURE_SAMPLERS)
{
BX_WARN(false, "Binding index is too large %d max is %d. User defined uniform '%s' won't be set.", int(arg.index - 1), BGFX_CONFIG_MAX_TEXTURE_SAMPLERS - 1, name);
}
else
{
ps->m_bindingTypes[arg.index-1] = fragmentBit ? PipelineStateMtl::BindToFragmentShader : PipelineStateMtl::BindToVertexShader;
BX_TRACE("buffer %s index:%d", name, uint32_t(arg.index-1) );
}
}
else if (arg.type == MTLArgumentTypeTexture)
{
const char* name = utf8String(arg.name);
@@ -1861,16 +1875,13 @@ namespace bgfx { namespace mtl
if (NULL != info)
{
if (ps->m_samplerCount >= BGFX_CONFIG_MAX_TEXTURE_SAMPLERS)
if (arg.index >= BGFX_CONFIG_MAX_TEXTURE_SAMPLERS)
{
BX_WARN(NULL != info, "Too many samplers in shader(only %d is supported). User defined uniform '%s' won't be set.", BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, name);
BX_WARN(false, "Binding index is too large %d max is %d. User defined uniform '%s' won't be set.", int(arg.index), BGFX_CONFIG_MAX_TEXTURE_SAMPLERS - 1, name);
}
else
{
ps->m_samplers[ps->m_samplerCount].m_index = uint32_t(arg.index);
ps->m_samplers[ps->m_samplerCount].m_uniform = info->m_handle;
ps->m_samplers[ps->m_samplerCount].m_fragment = fragmentBit ? 1 : 0;
++ps->m_samplerCount;
ps->m_bindingTypes[arg.index] = fragmentBit ? PipelineStateMtl::BindToFragmentShader : PipelineStateMtl::BindToVertexShader;
BX_TRACE("texture %s %d index:%d", name, info->m_handle, uint32_t(arg.index) );
}
}
@@ -3696,6 +3707,7 @@ namespace bgfx { namespace mtl
uint8_t primIndex = uint8_t(primType>>BGFX_STATE_PT_SHIFT);
PrimInfo prim = s_primInfo[primIndex];
const uint32_t maxComputeBindings = g_caps.limits.maxComputeBindings;
const uint32_t maxTextureSamplers = g_caps.limits.maxTextureSamplers;
RenderCommandEncoder rce;
PipelineStateMtl* currentPso = NULL;
@@ -4379,28 +4391,46 @@ namespace bgfx { namespace mtl
if (isValid(currentProgram) )
{
for (uint32_t sampler = 0, numSamplers = currentPso->m_samplerCount; sampler < numSamplers; ++sampler)
uint8_t* bindingTypes = currentPso->m_bindingTypes;
for (uint8_t stage = 0; stage < maxTextureSamplers; ++stage)
{
const SamplerInfo& samplerInfo = currentPso->m_samplers[sampler];
UniformHandle handle = samplerInfo.m_uniform;
int stage = *( (int*)m_uniforms[handle.idx]);
const Binding& bind = renderBind.m_bind[stage];
Binding& current = currentBind.m_bind[stage];
if (current.m_idx != bind.m_idx
|| current.m_samplerFlags != bind.m_samplerFlags
|| programChanged)
|| current.m_type != bind.m_type
|| current.m_samplerFlags != bind.m_samplerFlags
|| programChanged)
{
if (kInvalidHandle != bind.m_idx)
{
TextureMtl& texture = m_textures[bind.m_idx];
texture.commit(samplerInfo.m_index
, !samplerInfo.m_fragment
, samplerInfo.m_fragment
, bind.m_samplerFlags
);
switch (bind.m_type)
{
case Binding::Texture:
{
TextureMtl& texture = m_textures[bind.m_idx];
texture.commit(stage
, 0 != (bindingTypes[stage] & PipelineStateMtl::BindToVertexShader)
, 0 != (bindingTypes[stage] & PipelineStateMtl::BindToFragmentShader)
, bind.m_samplerFlags
);
}
break;
case Binding::IndexBuffer:
case Binding::VertexBuffer:
{
const BufferMtl& buffer = Binding::IndexBuffer == bind.m_type
? m_indexBuffers[bind.m_idx]
: m_vertexBuffers[bind.m_idx]
;
if (0 != (bindingTypes[stage] & PipelineStateMtl::BindToVertexShader))
rce.setVertexBuffer(buffer.m_ptr, 0, stage + 1);
if (0 != (bindingTypes[stage] & PipelineStateMtl::BindToFragmentShader))
rce.setFragmentBuffer(buffer.m_ptr, 0, stage + 1);
}
break;
}
}
}