diff --git a/.gitignore b/.gitignore index 90e2adcc5..ff5ddbc96 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ out lib/* Makefile *.Makefile - +*~ diff --git a/src/common/blocklayout.cpp b/src/common/blocklayout.cpp index f7c9b8f42..a0c9289d7 100644 --- a/src/common/blocklayout.cpp +++ b/src/common/blocklayout.cpp @@ -155,8 +155,9 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool } } -HLSLBlockEncoder::HLSLBlockEncoder(std::vector *blockInfoOut) - : BlockLayoutEncoder(blockInfoOut) +HLSLBlockEncoder::HLSLBlockEncoder(std::vector *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 &blockInfo) +void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, HLSLBlockEncoder *encoder, + const std::vector &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 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 @@ -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(rx::roundUp(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); diff --git a/src/common/blocklayout.h b/src/common/blocklayout.h index 6fadd0856..a9dca60a4 100644 --- a/src/common/blocklayout.h +++ b/src/common/blocklayout.h @@ -14,6 +14,7 @@ #define GL_APICALL #include #include +#include #include 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 *blockInfoOut); + enum HLSLBlockEncoderStrategy + { + ENCODE_PACKED, + ENCODE_LOOSE + }; + + HLSLBlockEncoder(std::vector *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); } diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp index d747ddd57..2d7818b64 100644 --- a/src/compiler/translator/OutputHLSL.cpp +++ b/src/compiler/translator/OutputHLSL.cpp @@ -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; diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp index cf7640723..8525ffbd3 100644 --- a/src/libGLESv2/ProgramBinary.cpp +++ b/src/libGLESv2/ProgramBinary.cpp @@ -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++) {