Hash :
f4780c1c
Author :
Date :
2015-02-11T16:33:11
Use correct non-square register count in structs. For struct varyings with nested structs, we would count registers incorrectly, and produce D3D link errors. This fixes tests in the dEQP's shaders.linkage.varying.struct. BUG=angle:910 Change-Id: I47ea6dba36bf57cf94a7e7f30997c6c9096c2b40 Reviewed-on: https://chromium-review.googlesource.com/247243 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//
// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// blocklayout.h:
// Methods and classes related to uniform layout and packing in GLSL and HLSL.
//
#ifndef COMMON_BLOCKLAYOUT_H_
#define COMMON_BLOCKLAYOUT_H_
#include <cstddef>
#include <vector>
#include "angle_gl.h"
#include <GLSLANG/ShaderLang.h>
namespace sh
{
struct ShaderVariable;
struct InterfaceBlockField;
struct Uniform;
struct Varying;
struct InterfaceBlock;
struct COMPILER_EXPORT BlockMemberInfo
{
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
arrayStride(arrayStride),
matrixStride(matrixStride),
isRowMajorMatrix(isRowMajorMatrix)
{}
static BlockMemberInfo getDefaultBlockInfo()
{
return BlockMemberInfo(-1, -1, -1, false);
}
int offset;
int arrayStride;
int matrixStride;
bool isRowMajorMatrix;
};
class COMPILER_EXPORT BlockLayoutEncoder
{
public:
BlockLayoutEncoder();
BlockMemberInfo 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; }
virtual void enterAggregateType() = 0;
virtual void exitAggregateType() = 0;
static const size_t BytesPerComponent = 4u;
static const unsigned int ComponentsPerRegister = 4u;
static size_t getBlockRegister(const BlockMemberInfo &info);
static size_t getBlockRegisterElement(const BlockMemberInfo &info);
protected:
size_t mCurrentOffset;
void nextRegister();
virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
};
// Block layout according to the std140 block layout
// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder
{
public:
Std140BlockEncoder();
virtual void enterAggregateType();
virtual void exitAggregateType();
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);
};
// 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 constant blocks, and ENCODE_PACKED
// for everything else (D3D10+ constant blocks and all attributes/varyings).
class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder
{
public:
enum HLSLBlockEncoderStrategy
{
ENCODE_PACKED,
ENCODE_LOOSE
};
HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy);
virtual void enterAggregateType();
virtual void exitAggregateType();
void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
void setTransposeMatrices(bool enabled) { mTransposeMatrices = enabled; }
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);
HLSLBlockEncoderStrategy mEncoderStrategy;
bool mTransposeMatrices;
};
// 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).
COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices);
COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
}
#endif // COMMON_BLOCKLAYOUT_H_