зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
68fe74aabb
Коммит
24d8d675cd
|
@ -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++)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче