Fix register packing for structs in d3d9.

Fixes WebGL test misc/shader-with-array-of-structs-uniform

BUG=angle:656

Change-Id: If79a19db4d40bab9110422f7876de32e7f85e506
Reviewed-on: https://chromium-review.googlesource.com/200620
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
This commit is contained in:
Vladimir Vukicevic 2014-05-27 12:07:51 -04:00 коммит произвёл Jamie Madill
Родитель 68fe74aabb
Коммит 24d8d675cd
5 изменённых файлов: 59 добавлений и 25 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -34,4 +34,4 @@ out
lib/*
Makefile
*.Makefile
*~

Просмотреть файл

@ -155,8 +155,9 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool
}
}
HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut)
: BlockLayoutEncoder(blockInfoOut)
HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut, HLSLBlockEncoderStrategy strategy)
: BlockLayoutEncoder(blockInfoOut),
mEncoderStrategy(strategy)
{
}
@ -177,9 +178,18 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b
int matrixStride = 0;
int arrayStride = 0;
if (gl::IsMatrixType(type))
// if variables are not to be packed, or we're about to
// pack a matrix or array, skip to the start of the next
// register
if (!isPacked() ||
gl::IsMatrixType(type) ||
arraySize > 0)
{
nextRegister();
}
if (gl::IsMatrixType(type))
{
matrixStride = ComponentsPerRegister;
if (arraySize > 0)
@ -190,10 +200,9 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b
}
else if (arraySize > 0)
{
nextRegister();
arrayStride = ComponentsPerRegister;
}
else
else if (isPacked())
{
int numComponents = gl::UniformComponentCount(type);
if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
@ -221,10 +230,14 @@ void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool i
mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
mCurrentOffset += numComponents;
}
else
else if (isPacked())
{
mCurrentOffset += gl::UniformComponentCount(type);
}
else
{
mCurrentOffset += ComponentsPerRegister;
}
}
void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
@ -232,7 +245,8 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
mCurrentOffset += (numRegisters * ComponentsPerRegister);
}
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, HLSLBlockEncoder *encoder, const std::vector<gl::BlockMemberInfo> &blockInfo)
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, HLSLBlockEncoder *encoder,
const std::vector<gl::BlockMemberInfo> &blockInfo, ShShaderOutput outputType)
{
// because this method computes offsets (element indexes) instead of any total sizes,
// we can ignore the array size of the variable
@ -245,14 +259,14 @@ void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *va
for (size_t fieldIndex = 0; fieldIndex < variable->fields.size(); fieldIndex++)
{
HLSLVariableGetRegisterInfo(baseRegisterIndex, &variable->fields[fieldIndex], encoder, blockInfo);
HLSLVariableGetRegisterInfo(baseRegisterIndex, &variable->fields[fieldIndex], encoder, blockInfo, outputType);
}
// Since the above loop only encodes one element of an array, ensure we don't lose track of the
// current register offset
if (variable->isArray())
{
unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable) / variable->arraySize);
unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable, outputType) / variable->arraySize);
encoder->skipRegisters(structRegisterCount * (variable->arraySize - 1));
}
@ -268,11 +282,13 @@ void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *va
}
}
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable)
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, ShShaderOutput outputType)
{
std::vector<BlockMemberInfo> blockInfo;
HLSLBlockEncoder encoder(&blockInfo);
HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo);
HLSLBlockEncoder encoder(&blockInfo,
outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE
: HLSLBlockEncoder::ENCODE_PACKED);
HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo, outputType);
}
template <class ShaderVarType>
@ -301,16 +317,19 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
unsigned int HLSLVariableRegisterCount(const Varying &variable)
{
HLSLBlockEncoder encoder(NULL);
HLSLBlockEncoder encoder(NULL, HLSLBlockEncoder::ENCODE_PACKED);
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
}
unsigned int HLSLVariableRegisterCount(const Uniform &variable)
unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
{
HLSLBlockEncoder encoder(NULL);
HLSLBlockEncoder encoder(NULL,
outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE
: HLSLBlockEncoder::ENCODE_PACKED);
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);

Просмотреть файл

@ -14,6 +14,7 @@
#define GL_APICALL
#include <GLES3/gl3.h>
#include <GLES2/gl2.h>
#include <GLSLANG/ShaderLang.h>
#include <cstddef>
namespace gl
@ -67,31 +68,44 @@ class Std140BlockEncoder : public BlockLayoutEncoder
virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
};
// Block layout packed according to the default D3D11 register packing rules
// Block layout packed according to the D3D9 or default D3D10+ register packing rules
// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
// The strategy should be ENCODE_LOOSE for D3D9 constnat blocks, and ENCODE_PACKED
// for everything else (D3D10+ constant blocks and all attributes/varyings).
class HLSLBlockEncoder : public BlockLayoutEncoder
{
public:
HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
enum HLSLBlockEncoderStrategy
{
ENCODE_PACKED,
ENCODE_LOOSE
};
HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut,
HLSLBlockEncoderStrategy strategy);
virtual void enterAggregateType();
virtual void exitAggregateType();
void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
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);
HLSLBlockEncoderStrategy mEncoderStrategy;
};
// This method assigns values to the variable's "registerIndex" and "elementIndex" fields.
// "elementIndex" is only used for structures.
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable);
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable, ShShaderOutput outputType);
// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
// class to count the number of used registers in a struct (which are individually packed according to the same rules).
unsigned int HLSLVariableRegisterCount(const Varying &variable);
unsigned int HLSLVariableRegisterCount(const Uniform &variable);
unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
}

Просмотреть файл

@ -483,7 +483,7 @@ void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newL
case gl::BLOCKLAYOUT_SHARED:
case gl::BLOCKLAYOUT_PACKED:
{
gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo);
gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED);
hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
interfaceBlock->dataSize = hlslEncoder.getBlockSize();
}
@ -3940,7 +3940,7 @@ gl::Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &n
}
// assign register offset information -- this will override the information in any sub-structures.
HLSLVariableGetRegisterInfo(registerIndex, &structUniform);
HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
output.push_back(structUniform);
@ -4008,11 +4008,11 @@ int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString
if (IsSampler(type.getBasicType()))
{
mSamplerRegister += gl::HLSLVariableRegisterCount(uniform);
mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
}
else
{
mUniformRegister += gl::HLSLVariableRegisterCount(uniform);
mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
}
return registerIndex;

Просмотреть файл

@ -1847,7 +1847,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const gl::Uniform &constant, In
{
if (constant.arraySize > 0)
{
const unsigned int elementRegisterCount = HLSLVariableRegisterCount(constant) / constant.arraySize;
ShShaderOutput outputType = Shader::getCompilerOutputType(shader);
const unsigned int elementRegisterCount = HLSLVariableRegisterCount(constant, outputType) / constant.arraySize;
for (unsigned int elementIndex = 0; elementIndex < constant.arraySize; elementIndex++)
{