Commit 3a7b29ce by Alexis Hetu Committed by Alexis Hétu

Uniform block register allocation

Uniform blocks members, when unnamed blocks are used, are used in glsl only with the member's name, without any reference to the block itself. When this happens, we still need the whole block to be allocated as one contiguous structure in the registers. To do that, whenever a member of an unnamed block is first used, the whole block is allocated. Also, whenever any member of an unnamed block attempts to allocate a register, it first verifies if the parent block has already been allocated. So this means that both allocation and lookup must be done through the parent block when dealing with unnamed block members. Change-Id: Ib11eaa1ee052d32252f32997eb5f650a9765533d Reviewed-on: https://swiftshader-review.googlesource.com/5059Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent ffb35eb4
......@@ -2792,14 +2792,28 @@ namespace glsl
if(symbol || block)
{
int index = lookup(uniforms, uniform);
TInterfaceBlock* parentBlock = type.getInterfaceBlock();
bool isBlockMember = (!block && parentBlock);
int index = isBlockMember ? lookup(uniforms, parentBlock) : lookup(uniforms, uniform);
if(index == -1)
if(index == -1 || isBlockMember)
{
index = allocate(uniforms, uniform);
const TString &name = symbol ? symbol->getSymbol() : block->name();
if(index == -1)
{
index = allocate(uniforms, uniform);
}
declareUniform(type, name, index);
// Verify if the current uniform is a member of an already declared block
const TString &name = symbol ? symbol->getSymbol() : block->name();
int blockMemberIndex = blockMemberLookup(type, name, index);
if(blockMemberIndex == -1)
{
declareUniform(type, name, index);
}
else
{
index = blockMemberIndex;
}
}
return index;
......@@ -2953,13 +2967,25 @@ namespace glsl
return -1;
}
int OutputASM::lookup(VariableArray &list, TInterfaceBlock *block)
{
for(unsigned int i = 0; i < list.size(); i++)
{
if(list[i] && (list[i]->getType().getInterfaceBlock() == block))
{
return i; // Pointer match
}
}
return -1;
}
int OutputASM::allocate(VariableArray &list, TIntermTyped *variable)
{
int index = lookup(list, variable);
if(index == -1)
{
unsigned int registerCount = variable->totalRegisterCount();
unsigned int registerCount = variable->blockRegisterCount();
for(unsigned int i = 0; i < list.size(); i++)
{
......@@ -3007,40 +3033,18 @@ namespace glsl
}
}
int OutputASM::declareUniform(const TType &type, const TString &name, int registerIndex, int blockId, BlockLayoutEncoder* encoder)
int OutputASM::blockMemberLookup(const TType &type, const TString &name, int registerIndex)
{
const TStructure *structure = type.getStruct();
const TInterfaceBlock *block = (type.isInterfaceBlock() || (blockId == -1)) ? type.getInterfaceBlock() : nullptr;
ActiveUniforms &activeUniforms = shaderObject->activeUniforms;
const TInterfaceBlock *block = type.getInterfaceBlock();
if(!structure && !block)
{
const BlockMemberInfo blockInfo = encoder ? encoder->encodeType(type) : BlockMemberInfo::getDefaultBlockInfo();
if(blockId >= 0)
{
blockDefinitions[blockId][registerIndex] = TypedMemberInfo(blockInfo, type);
shaderObject->activeUniformBlocks[blockId].fields.push_back(activeUniforms.size());
}
int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex;
activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(),
fieldRegisterIndex, blockId, blockInfo));
if(isSamplerRegister(type))
{
for(int i = 0; i < type.totalRegisterCount(); i++)
{
shader->declareSampler(fieldRegisterIndex + i);
}
}
}
else if(block)
if(block)
{
ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks;
const TFieldList& fields = block->fields();
const TString &blockName = block->name();
int fieldRegisterIndex = registerIndex;
bool isUniformBlockMember = !type.isInterfaceBlock() && (blockId == -1);
if(isUniformBlockMember)
if(!type.isInterfaceBlock())
{
// This is a uniform that's part of a block, let's see if the block is already defined
for(size_t i = 0; i < activeUniformBlocks.size(); ++i)
......@@ -3064,6 +3068,43 @@ namespace glsl
}
}
}
}
return -1;
}
void OutputASM::declareUniform(const TType &type, const TString &name, int registerIndex, int blockId, BlockLayoutEncoder* encoder)
{
const TStructure *structure = type.getStruct();
const TInterfaceBlock *block = (type.isInterfaceBlock() || (blockId == -1)) ? type.getInterfaceBlock() : nullptr;
if(!structure && !block)
{
ActiveUniforms &activeUniforms = shaderObject->activeUniforms;
const BlockMemberInfo blockInfo = encoder ? encoder->encodeType(type) : BlockMemberInfo::getDefaultBlockInfo();
if(blockId >= 0)
{
blockDefinitions[blockId][registerIndex] = TypedMemberInfo(blockInfo, type);
shaderObject->activeUniformBlocks[blockId].fields.push_back(activeUniforms.size());
}
int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex;
activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(),
fieldRegisterIndex, blockId, blockInfo));
if(isSamplerRegister(type))
{
for(int i = 0; i < type.totalRegisterCount(); i++)
{
shader->declareSampler(fieldRegisterIndex + i);
}
}
}
else if(block)
{
ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks;
const TFieldList& fields = block->fields();
const TString &blockName = block->name();
int fieldRegisterIndex = registerIndex;
bool isUniformBlockMember = !type.isInterfaceBlock() && (blockId == -1);
blockId = activeUniformBlocks.size();
bool isRowMajor = block->matrixPacking() == EmpRowMajor;
......@@ -3139,8 +3180,6 @@ namespace glsl
}
}
}
return registerIndex;
}
GLenum OutputASM::glVariableType(const TType &type)
......
......@@ -290,10 +290,12 @@ namespace glsl
typedef std::vector<TIntermTyped*> VariableArray;
int lookup(VariableArray &list, TIntermTyped *variable);
int lookup(VariableArray &list, TInterfaceBlock *block);
int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
int allocate(VariableArray &list, TIntermTyped *variable);
void free(VariableArray &list, TIntermTyped *variable);
int declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
GLenum glVariableType(const TType &type);
GLenum glVariablePrecision(const TType &type);
......
......@@ -333,6 +333,24 @@ public:
}
}
int blockRegisterCount() const
{
// If this TType object is a block member, return the register count of the parent block
// Otherwise, return the register count of the current TType object
if(interfaceBlock && !isInterfaceBlock())
{
int registerCount = 0;
const TFieldList& fieldList = interfaceBlock->fields();
for(size_t i = 0; i < fieldList.size(); i++)
{
const TType &fieldType = *(fieldList[i]->type());
registerCount += fieldType.totalRegisterCount();
}
return registerCount;
}
return totalRegisterCount();
}
int totalRegisterCount() const
{
if(array)
......
......@@ -320,6 +320,7 @@ public:
TString getCompleteString() const { return type.getCompleteString(); }
int totalRegisterCount() const { return type.totalRegisterCount(); }
int blockRegisterCount() const { return type.blockRegisterCount(); }
int elementRegisterCount() const { return type.elementRegisterCount(); }
int registerSize() const { return type.registerSize(); }
int getArraySize() const { return type.getArraySize(); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment