blob: be0c34075b2a2909f22abdfa1a38e25605f202b3 [file] [log] [blame]
Jamie Madill834e8b72014-04-11 13:33:58 -04001//
2// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// blocklayout.h:
7// Methods and classes related to uniform layout and packing in GLSL and HLSL.
8//
9
10#ifndef COMMON_BLOCKLAYOUT_H_
11#define COMMON_BLOCKLAYOUT_H_
12
13#include <vector>
Jamie Madillf51639a2014-06-25 16:04:57 -040014#include "angle_gl.h"
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040015#include <GLSLANG/ShaderLang.h>
Jamie Madill9fba2ba2014-04-22 14:21:00 -040016#include <cstddef>
Jamie Madill834e8b72014-04-11 13:33:58 -040017
Jamie Madillf2575982014-06-25 16:04:54 -040018namespace sh
Jamie Madill834e8b72014-04-11 13:33:58 -040019{
Jamie Madill834e8b72014-04-11 13:33:58 -040020struct ShaderVariable;
21struct InterfaceBlockField;
22struct BlockMemberInfo;
23struct Uniform;
24struct Varying;
Jamie Madillfc43d272014-07-11 17:02:02 -040025struct InterfaceBlock;
Jamie Madill834e8b72014-04-11 13:33:58 -040026
27class BlockLayoutEncoder
28{
29 public:
30 BlockLayoutEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
31
32 void encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields);
33 void encodeInterfaceBlockField(const InterfaceBlockField &field);
34 void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
35 size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
36
37 static const size_t BytesPerComponent = 4u;
38 static const unsigned int ComponentsPerRegister = 4u;
39
40 protected:
41 size_t mCurrentOffset;
42
43 void nextRegister();
44
45 virtual void enterAggregateType() = 0;
46 virtual void exitAggregateType() = 0;
47 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
48 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
49
50 private:
51 std::vector<BlockMemberInfo> *mBlockInfoOut;
52};
53
54// Block layout according to the std140 block layout
55// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
56
57class Std140BlockEncoder : public BlockLayoutEncoder
58{
59 public:
60 Std140BlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
61
62 protected:
63 virtual void enterAggregateType();
64 virtual void exitAggregateType();
65 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
66 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
67};
68
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040069// Block layout packed according to the D3D9 or default D3D10+ register packing rules
Jamie Madill834e8b72014-04-11 13:33:58 -040070// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
Jamie Madillf91ce812014-06-13 10:04:34 -040071// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040072// for everything else (D3D10+ constant blocks and all attributes/varyings).
Jamie Madill834e8b72014-04-11 13:33:58 -040073
74class HLSLBlockEncoder : public BlockLayoutEncoder
75{
76 public:
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040077 enum HLSLBlockEncoderStrategy
78 {
79 ENCODE_PACKED,
80 ENCODE_LOOSE
81 };
82
83 HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut,
84 HLSLBlockEncoderStrategy strategy);
Jamie Madill834e8b72014-04-11 13:33:58 -040085
86 virtual void enterAggregateType();
87 virtual void exitAggregateType();
Jamie Madillc600c8c2014-05-16 11:22:21 -040088 void skipRegisters(unsigned int numRegisters);
Jamie Madill834e8b72014-04-11 13:33:58 -040089
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040090 bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
91
Jamie Madill834e8b72014-04-11 13:33:58 -040092 protected:
93 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
94 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040095
96 HLSLBlockEncoderStrategy mEncoderStrategy;
Jamie Madill834e8b72014-04-11 13:33:58 -040097};
98
Jamie Madillfc43d272014-07-11 17:02:02 -040099// This method returns the data size of an interface block in HLSL, according to its layout.
100size_t HLSLInterfaceBlockDataSize(const sh::InterfaceBlock &interfaceBlock);
101
Jamie Madill834e8b72014-04-11 13:33:58 -0400102// This method assigns values to the variable's "registerIndex" and "elementIndex" fields.
103// "elementIndex" is only used for structures.
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400104void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable, ShShaderOutput outputType);
Jamie Madill834e8b72014-04-11 13:33:58 -0400105
106// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
107// class to count the number of used registers in a struct (which are individually packed according to the same rules).
108unsigned int HLSLVariableRegisterCount(const Varying &variable);
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400109unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
Jamie Madill834e8b72014-04-11 13:33:58 -0400110
111}
112
113#endif // COMMON_BLOCKLAYOUT_H_