Fix sampler/texture indices for metal (#1242)

Fix for https://github.com/bkaradzic/bgfx/issues/1227 .

It gets texture slot from compiled shaders and maps it to Sampler uniform. So sampler uniform MUST be defined before using shader (shadowmap_simple has a bug with invalid uniform name).
This commit is contained in:
attilaz 2017-09-22 17:44:51 +02:00 committed by Branimir Karadžić
parent bc065cc4d0
commit acf3db7a06
3 changed files with 47 additions and 41 deletions

View File

@ -82,7 +82,7 @@ public:
bgfx::setDebug(m_debug);
// Uniforms.
u_shadowMap = bgfx::createUniform("u_shadowMap", bgfx::UniformType::Int1);
s_shadowMap = bgfx::createUniform("s_shadowMap", bgfx::UniformType::Int1);
u_lightPos = bgfx::createUniform("u_lightPos", bgfx::UniformType::Vec4);
u_lightMtx = bgfx::createUniform("u_lightMtx", bgfx::UniformType::Mat4);
@ -204,7 +204,7 @@ public:
m_state[1]->m_numTextures = 1;
m_state[1]->m_textures[0].m_flags = UINT32_MAX;
m_state[1]->m_textures[0].m_stage = 0;
m_state[1]->m_textures[0].m_sampler = u_shadowMap;
m_state[1]->m_textures[0].m_sampler = s_shadowMap;
m_state[1]->m_textures[0].m_texture = shadowMapTexture;
// Set view and projection matrices.
@ -240,7 +240,7 @@ public:
bgfx::destroy(m_shadowMapFB);
bgfx::destroy(u_shadowMap);
bgfx::destroy(s_shadowMap);
bgfx::destroy(u_lightPos);
bgfx::destroy(u_lightMtx);
bgfx::destroy(u_depthScaleOffset);
@ -421,7 +421,7 @@ public:
uint32_t m_debug;
uint32_t m_reset;
bgfx::UniformHandle u_shadowMap;
bgfx::UniformHandle s_shadowMap;
bgfx::UniformHandle u_lightPos;
bgfx::UniformHandle u_lightMtx;

View File

@ -726,8 +726,7 @@ namespace bgfx { namespace mtl
, m_vshConstantBufferAlignmentMask(0)
, m_fshConstantBufferSize(0)
, m_fshConstantBufferAlignmentMask(0)
, m_usedVertexSamplerStages(0)
, m_usedFragmentSamplerStages(0)
, m_samplerCount(0)
, m_numPredefined(0)
, m_processedUniforms(false)
{
@ -753,8 +752,16 @@ namespace bgfx { namespace mtl
uint32_t m_vshConstantBufferAlignmentMask;
uint32_t m_fshConstantBufferSize;
uint32_t m_fshConstantBufferAlignmentMask;
uint32_t m_usedVertexSamplerStages;
uint32_t m_usedFragmentSamplerStages;
struct SamplerInfo
{
uint32_t m_index;
bgfx::UniformHandle m_uniform;
bool m_fragment;
};
SamplerInfo m_samplers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t m_samplerCount;
PredefinedUniform m_predefined[PredefinedUniform::Count*2];
uint8_t m_numPredefined;
bool m_processedUniforms;

View File

@ -21,17 +21,7 @@
/*
// known metal shader generation issues:
03-raymarch: OSX10.11.3 nothing is visible ( depth/color swap in fragment output struct fixed this )
14-shadowvolumes: in texture as stencil mode - columns/bunny are dark. in fs_shadowvolume_color_lighting SAMPLER2D(s_texStencil, 1) is
converted to "texture2d<float> s_texStencil [[texture(0)]], sampler _mtlsmp_s_texStencil [[sampler(0)]]". Slot is 1 -> 0.
15-shadowmaps-simple: shader compilation error
16-shadowmaps: //problem with essl -> metal: SAMPLER2D(u_shadowMap0, 4); sampler index is lost. Shadowmap is set to slot 4, but
metal shader uses sampler/texture slot 0. this could require changes outside of renderer_mtl?
packFloatToRGBA needs highp. currently it uses half.
24-nbody: no generated compute shaders for metal
27-terrain: shaderc generates invalid metal shader for vs_terrain_height_texture. vertex output: half4 gl_Position [[position]], should be float4
31-rsm:
<program source>:6:23: error: type 'half4' (aka 'vector_half4') is not valid for attribute 'position'
half4 gl_Position [[position]];
Known issues(driver problems??):
@ -2022,6 +2012,8 @@ namespace bgfx { namespace mtl
m_fshConstantBufferSize = 0;
m_fshConstantBufferAlignmentMask = 0;
m_samplerCount = 0;
m_processedUniforms = false;
m_numPredefined = 0;
@ -2340,16 +2332,25 @@ namespace bgfx { namespace mtl
}
else if (arg.type == MTLArgumentTypeTexture)
{
if (0 == shaderType)
{
m_usedVertexSamplerStages |= 1<<arg.index;
}
else
{
m_usedFragmentSamplerStages |= 1<<arg.index;
}
const char* name = utf8String(arg.name);
const UniformRegInfo* info = s_renderMtl->m_uniformReg.find(name);
BX_WARN(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
BX_TRACE("texture: %s index:%d", utf8String(arg.name), arg.index);
if (NULL != info)
{
if ( m_samplerCount >= 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);
}
else
{
m_samplers[m_samplerCount].m_index = uint32_t(arg.index);
m_samplers[m_samplerCount].m_uniform = info->m_handle;
m_samplers[m_samplerCount].m_fragment = fragmentBit ? 1 : 0;
++m_samplerCount;
BX_TRACE("texture %s %d index:%d", name, info->m_handle, uint32_t(arg.index) );
}
}
}
else if (arg.type == MTLArgumentTypeSampler)
{
@ -3727,19 +3728,17 @@ namespace bgfx { namespace mtl
m_uniformBufferVertexOffset = m_uniformBufferFragmentOffset;
}
if (kInvalidHandle != programIdx)
{
uint32_t usedVertexSamplerStages = 0;
uint32_t usedFragmentSamplerStages = 0;
ProgramMtl& program = m_program[programIdx];
if (kInvalidHandle != programIdx)
for (uint32_t sampler = 0; sampler < program.m_samplerCount; ++sampler)
{
ProgramMtl& program = m_program[programIdx];
usedVertexSamplerStages = program.m_usedVertexSamplerStages;
usedFragmentSamplerStages = program.m_usedFragmentSamplerStages;
}
ProgramMtl::SamplerInfo& samplerInfo = program.m_samplers[sampler];
UniformHandle handle = samplerInfo.m_uniform;
int stage = *((int*)m_uniforms[handle.idx]);
for (uint8_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage)
{
const Binding& bind = renderBind.m_bind[stage];
Binding& current = currentBind.m_bind[stage];
@ -3750,11 +3749,11 @@ namespace bgfx { namespace mtl
if (kInvalidHandle != bind.m_idx)
{
TextureMtl& texture = m_textures[bind.m_idx];
texture.commit(stage
, 0 != (usedVertexSamplerStages & (1<<stage) )
, 0 != (usedFragmentSamplerStages & (1<<stage) )
, bind.m_un.m_draw.m_textureFlags
);
texture.commit(samplerInfo.m_index
, !samplerInfo.m_fragment
, samplerInfo.m_fragment
, bind.m_un.m_draw.m_textureFlags
);
}
}