Commit 24d8d675 by Vladimir Vukicevic Committed by Jamie Madill

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/200620Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarNicolas Capens <nicolascapens@chromium.org>
parent 68fe74aa
...@@ -34,4 +34,4 @@ out ...@@ -34,4 +34,4 @@ out
lib/* lib/*
Makefile Makefile
*.Makefile *.Makefile
*~
...@@ -155,8 +155,9 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool ...@@ -155,8 +155,9 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool
} }
} }
HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut) HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut, HLSLBlockEncoderStrategy strategy)
: BlockLayoutEncoder(blockInfoOut) : BlockLayoutEncoder(blockInfoOut),
mEncoderStrategy(strategy)
{ {
} }
...@@ -177,9 +178,18 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b ...@@ -177,9 +178,18 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b
int matrixStride = 0; int matrixStride = 0;
int arrayStride = 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(); nextRegister();
}
if (gl::IsMatrixType(type))
{
matrixStride = ComponentsPerRegister; matrixStride = ComponentsPerRegister;
if (arraySize > 0) if (arraySize > 0)
...@@ -190,10 +200,9 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b ...@@ -190,10 +200,9 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b
} }
else if (arraySize > 0) else if (arraySize > 0)
{ {
nextRegister();
arrayStride = ComponentsPerRegister; arrayStride = ComponentsPerRegister;
} }
else else if (isPacked())
{ {
int numComponents = gl::UniformComponentCount(type); int numComponents = gl::UniformComponentCount(type);
if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
...@@ -221,10 +230,14 @@ void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool i ...@@ -221,10 +230,14 @@ void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool i
mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
mCurrentOffset += numComponents; mCurrentOffset += numComponents;
} }
else else if (isPacked())
{ {
mCurrentOffset += gl::UniformComponentCount(type); mCurrentOffset += gl::UniformComponentCount(type);
} }
else
{
mCurrentOffset += ComponentsPerRegister;
}
} }
void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
...@@ -232,7 +245,8 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) ...@@ -232,7 +245,8 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
mCurrentOffset += (numRegisters * ComponentsPerRegister); 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, // because this method computes offsets (element indexes) instead of any total sizes,
// we can ignore the array size of the variable // we can ignore the array size of the variable
...@@ -245,14 +259,14 @@ void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *va ...@@ -245,14 +259,14 @@ void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *va
for (size_t fieldIndex = 0; fieldIndex < variable->fields.size(); fieldIndex++) 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 // Since the above loop only encodes one element of an array, ensure we don't lose track of the
// current register offset // current register offset
if (variable->isArray()) if (variable->isArray())
{ {
unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable) / variable->arraySize); unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable, outputType) / variable->arraySize);
encoder->skipRegisters(structRegisterCount * (variable->arraySize - 1)); encoder->skipRegisters(structRegisterCount * (variable->arraySize - 1));
} }
...@@ -268,11 +282,13 @@ void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *va ...@@ -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; std::vector<BlockMemberInfo> blockInfo;
HLSLBlockEncoder encoder(&blockInfo); HLSLBlockEncoder encoder(&blockInfo,
HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo); outputType == SH_HLSL9_OUTPUT ? HLSLBlockEncoder::ENCODE_LOOSE
: HLSLBlockEncoder::ENCODE_PACKED);
HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo, outputType);
} }
template <class ShaderVarType> template <class ShaderVarType>
...@@ -301,16 +317,19 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * ...@@ -301,16 +317,19 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
unsigned int HLSLVariableRegisterCount(const Varying &variable) unsigned int HLSLVariableRegisterCount(const Varying &variable)
{ {
HLSLBlockEncoder encoder(NULL); HLSLBlockEncoder encoder(NULL, HLSLBlockEncoder::ENCODE_PACKED);
HLSLVariableRegisterCount(variable, &encoder); HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes); 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); HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define GL_APICALL #define GL_APICALL
#include <GLES3/gl3.h> #include <GLES3/gl3.h>
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <GLSLANG/ShaderLang.h>
#include <cstddef> #include <cstddef>
namespace gl namespace gl
...@@ -67,31 +68,44 @@ class Std140BlockEncoder : public BlockLayoutEncoder ...@@ -67,31 +68,44 @@ class Std140BlockEncoder : public BlockLayoutEncoder
virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); 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 // 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 class HLSLBlockEncoder : public BlockLayoutEncoder
{ {
public: public:
HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut); enum HLSLBlockEncoderStrategy
{
ENCODE_PACKED,
ENCODE_LOOSE
};
HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut,
HLSLBlockEncoderStrategy strategy);
virtual void enterAggregateType(); virtual void enterAggregateType();
virtual void exitAggregateType(); virtual void exitAggregateType();
void skipRegisters(unsigned int numRegisters); void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
protected: protected:
virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); 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); 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. // This method assigns values to the variable's "registerIndex" and "elementIndex" fields.
// "elementIndex" is only used for structures. // "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 // 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). // 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 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 ...@@ -483,7 +483,7 @@ void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newL
case gl::BLOCKLAYOUT_SHARED: case gl::BLOCKLAYOUT_SHARED:
case gl::BLOCKLAYOUT_PACKED: case gl::BLOCKLAYOUT_PACKED:
{ {
gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo); gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED);
hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields); hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
interfaceBlock->dataSize = hlslEncoder.getBlockSize(); interfaceBlock->dataSize = hlslEncoder.getBlockSize();
} }
...@@ -3940,7 +3940,7 @@ gl::Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &n ...@@ -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. // assign register offset information -- this will override the information in any sub-structures.
HLSLVariableGetRegisterInfo(registerIndex, &structUniform); HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
output.push_back(structUniform); output.push_back(structUniform);
...@@ -4008,11 +4008,11 @@ int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString ...@@ -4008,11 +4008,11 @@ int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString
if (IsSampler(type.getBasicType())) if (IsSampler(type.getBasicType()))
{ {
mSamplerRegister += gl::HLSLVariableRegisterCount(uniform); mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
} }
else else
{ {
mUniformRegister += gl::HLSLVariableRegisterCount(uniform); mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
} }
return registerIndex; return registerIndex;
......
...@@ -1847,7 +1847,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const gl::Uniform &constant, In ...@@ -1847,7 +1847,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const gl::Uniform &constant, In
{ {
if (constant.arraySize > 0) 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++) for (unsigned int elementIndex = 0; elementIndex < constant.arraySize; elementIndex++)
{ {
......
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