Commit bf9cce2e by Jamie Madill

Use the block encoder class to store uniform offsets.

This will allow us to use the same code path for assigning register information in all places. Because of this it fixes some long-broken dEQP struct uniform tests. BUG=angle:466 BUG=angle:505 Change-Id: I4161a388503aa09bbe2d21ff47bfb3352ec93881 Reviewed-on: https://chromium-review.googlesource.com/207255Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarNicolas Capens <capn@chromium.org>
parent 9fe25e9e
......@@ -161,6 +161,12 @@ HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut, H
{
}
HLSLBlockEncoder::HLSLBlockEncoder(ShShaderOutput outputType)
: BlockLayoutEncoder(NULL),
mEncoderStrategy(GetStrategyFor(outputType))
{
}
void HLSLBlockEncoder::enterAggregateType()
{
nextRegister();
......@@ -245,6 +251,16 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
mCurrentOffset += (numRegisters * ComponentsPerRegister);
}
HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
{
switch (outputType)
{
case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
default: UNREACHABLE(); return ENCODE_PACKED;
}
}
size_t HLSLInterfaceBlockDataSize(const sh::InterfaceBlock &interfaceBlock)
{
switch (interfaceBlock.layout)
......@@ -353,10 +369,7 @@ unsigned int HLSLVariableRegisterCount(const Varying &variable)
unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
{
HLSLBlockEncoder encoder(NULL,
outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE
: HLSLBlockEncoder::ENCODE_PACKED);
HLSLBlockEncoder encoder(outputType);
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
......
......@@ -33,6 +33,8 @@ class BlockLayoutEncoder
void encodeInterfaceBlockField(const InterfaceBlockField &field);
void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; }
static const size_t BytesPerComponent = 4u;
static const unsigned int ComponentsPerRegister = 4u;
......@@ -82,6 +84,7 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut,
HLSLBlockEncoderStrategy strategy);
HLSLBlockEncoder(ShShaderOutput outputType);
virtual void enterAggregateType();
virtual void exitAggregateType();
......@@ -89,6 +92,8 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType);
protected:
virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
......
......@@ -1648,7 +1648,7 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
success = false;
}
if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
if (!linkUniforms(infoLog, *vertexShader, *fragmentShader))
{
success = false;
}
......@@ -1900,8 +1900,11 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &u
return true;
}
bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms)
bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader)
{
const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
// Check that uniforms defined in the vertex and fragment shaders are identical
typedef std::map<std::string, const sh::Uniform*> UniformMap;
UniformMap linkedUniforms;
......@@ -1929,12 +1932,14 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform
for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
{
defineUniformBase(GL_VERTEX_SHADER, vertexUniforms[uniformIndex]);
const sh::Uniform &uniform = vertexUniforms[uniformIndex];
defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShader.getUniformRegister(uniform.name));
}
for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
{
defineUniformBase(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex]);
const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShader.getUniformRegister(uniform.name));
}
if (!indexUniforms(infoLog))
......@@ -1947,46 +1952,45 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform
return true;
}
void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform)
void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
{
defineUniform(shader, uniform, uniform.name, uniform.registerIndex);
ShShaderOutput outputType = Shader::getCompilerOutputType(shader);
sh::HLSLBlockEncoder encoder(outputType);
encoder.skipRegisters(uniformRegister);
defineUniform(shader, uniform, uniform.name, &encoder);
}
void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform,
const std::string &fullName, unsigned int baseRegisterIndex)
const std::string &fullName, sh::HLSLBlockEncoder *encoder)
{
if (uniform.isStruct())
{
if (uniform.arraySize > 0)
for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
{
ShShaderOutput outputType = Shader::getCompilerOutputType(shader);
const unsigned int elementRegisterCount = HLSLVariableRegisterCount(uniform, outputType) / uniform.arraySize;
const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
for (unsigned int elementIndex = 0; elementIndex < uniform.arraySize; elementIndex++)
{
const unsigned int elementRegisterOffset = elementRegisterCount * elementIndex;
encoder->enterAggregateType();
for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
{
const sh::Uniform &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = fullName + ArrayString(elementIndex) + "." + field.name;
const unsigned int fieldRegisterIndex = field.registerIndex + elementRegisterOffset;
defineUniform(shader, field, fieldFullName, fieldRegisterIndex);
}
}
}
else
{
for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
{
const sh::Uniform &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = fullName + "." + field.name;
defineUniform(shader, field, fieldFullName, field.registerIndex);
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
defineUniform(shader, field, fieldFullName, encoder);
}
encoder->exitAggregateType();
}
}
else // Not a struct
{
// Arrays are treated as aggregate types
if (uniform.isArray())
{
encoder->enterAggregateType();
}
LinkedUniform *linkedUniform = getUniformByName(fullName);
if (!linkedUniform)
......@@ -1994,19 +1998,30 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform,
linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
-1, sh::BlockMemberInfo::getDefaultBlockInfo());
ASSERT(linkedUniform);
linkedUniform->registerElement = uniform.elementIndex;
linkedUniform->registerElement = encoder->getCurrentElement();
mUniforms.push_back(linkedUniform);
}
ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
if (shader == GL_FRAGMENT_SHADER)
{
linkedUniform->psRegisterIndex = baseRegisterIndex;
linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
}
else if (shader == GL_VERTEX_SHADER)
{
linkedUniform->vsRegisterIndex = baseRegisterIndex;
linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
}
else UNREACHABLE();
// Advance the uniform offset, to track registers allocation for structs
encoder->encodeType(uniform.type, uniform.arraySize, false);
// Arrays are treated as aggregate types
if (uniform.isArray())
{
encoder->exitAggregateType();
}
}
}
......
......@@ -24,6 +24,11 @@
#include "libGLESv2/renderer/d3d/VertexDataManager.h"
#include "libGLESv2/DynamicHLSL.h"
namespace sh
{
class HLSLBlockEncoder;
}
namespace rx
{
class ShaderExecutable;
......@@ -201,9 +206,9 @@ class ProgramBinary : public RefCountObject
bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
bool linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms);
void defineUniformBase(GLenum shader, const sh::Uniform &uniform);
void defineUniform(GLenum shader, const sh::Uniform &uniform, const std::string &fullName, unsigned int baseRegisterIndex);
bool linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader);
void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
void defineUniform(GLenum shader, const sh::Uniform &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog);
bool indexUniforms(InfoLog &infoLog);
static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
......
......@@ -115,6 +115,12 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
getSourceImpl(mHlsl, bufSize, length, buffer);
}
unsigned int Shader::getUniformRegister(const std::string &uniformName) const
{
ASSERT(mUniformRegisterMap.count(uniformName) > 0);
return mUniformRegisterMap.find(uniformName)->second;
}
unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const
{
ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
......@@ -373,6 +379,18 @@ void Shader::compileToHLSL(void *compiler)
ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
mActiveUniforms = *(std::vector<sh::Uniform>*)activeUniforms;
for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++)
{
const sh::Uniform &uniform = mActiveUniforms[uniformIndex];
unsigned int index = -1;
bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
UNUSED_ASSERTION_VARIABLE(result);
ASSERT(result);
mUniformRegisterMap[uniform.name] = index;
}
void *activeInterfaceBlocks;
ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
mActiveInterfaceBlocks = *(std::vector<sh::InterfaceBlock>*)activeInterfaceBlocks;
......
......@@ -87,6 +87,7 @@ class Shader
static void releaseCompiler();
static ShShaderOutput getCompilerOutputType(GLenum shader);
unsigned int getUniformRegister(const std::string &uniformName) const;
unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
bool usesDepthRange() const { return mUsesDepthRange; }
......@@ -136,6 +137,7 @@ class Shader
std::string mInfoLog;
std::vector<sh::Uniform> mActiveUniforms;
std::vector<sh::InterfaceBlock> mActiveInterfaceBlocks;
std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
ResourceManager *mResourceManager;
......
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