blob: 28459a34da02fd4478008c053cea53e7cbb348c4 [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 Madill834e8b72014-04-11 13:33:58 -040014#include <GLES3/gl3.h>
15#include <GLES2/gl2.h>
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040016#include <GLSLANG/ShaderLang.h>
Jamie Madill9fba2ba2014-04-22 14:21:00 -040017#include <cstddef>
Jamie Madill834e8b72014-04-11 13:33:58 -040018
19namespace gl
20{
21
22struct ShaderVariable;
23struct InterfaceBlockField;
24struct BlockMemberInfo;
25struct Uniform;
26struct Varying;
27
28class BlockLayoutEncoder
29{
30 public:
31 BlockLayoutEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
32
33 void encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields);
34 void encodeInterfaceBlockField(const InterfaceBlockField &field);
35 void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
36 size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
37
38 static const size_t BytesPerComponent = 4u;
39 static const unsigned int ComponentsPerRegister = 4u;
40
41 protected:
42 size_t mCurrentOffset;
43
44 void nextRegister();
45
46 virtual void enterAggregateType() = 0;
47 virtual void exitAggregateType() = 0;
48 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
49 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
50
51 private:
52 std::vector<BlockMemberInfo> *mBlockInfoOut;
53};
54
55// Block layout according to the std140 block layout
56// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
57
58class Std140BlockEncoder : public BlockLayoutEncoder
59{
60 public:
61 Std140BlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
62
63 protected:
64 virtual void enterAggregateType();
65 virtual void exitAggregateType();
66 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
67 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
68};
69
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040070// Block layout packed according to the D3D9 or default D3D10+ register packing rules
Jamie Madill834e8b72014-04-11 13:33:58 -040071// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
Jamie Madillf91ce812014-06-13 10:04:34 -040072// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040073// for everything else (D3D10+ constant blocks and all attributes/varyings).
Jamie Madill834e8b72014-04-11 13:33:58 -040074
75class HLSLBlockEncoder : public BlockLayoutEncoder
76{
77 public:
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040078 enum HLSLBlockEncoderStrategy
79 {
80 ENCODE_PACKED,
81 ENCODE_LOOSE
82 };
83
84 HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut,
85 HLSLBlockEncoderStrategy strategy);
Jamie Madill834e8b72014-04-11 13:33:58 -040086
87 virtual void enterAggregateType();
88 virtual void exitAggregateType();
Jamie Madillc600c8c2014-05-16 11:22:21 -040089 void skipRegisters(unsigned int numRegisters);
Jamie Madill834e8b72014-04-11 13:33:58 -040090
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040091 bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
92
Jamie Madill834e8b72014-04-11 13:33:58 -040093 protected:
94 virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
95 virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -040096
97 HLSLBlockEncoderStrategy mEncoderStrategy;
Jamie Madill834e8b72014-04-11 13:33:58 -040098};
99
100// This method assigns values to the variable's "registerIndex" and "elementIndex" fields.
101// "elementIndex" is only used for structures.
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400102void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable, ShShaderOutput outputType);
Jamie Madill834e8b72014-04-11 13:33:58 -0400103
104// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
105// class to count the number of used registers in a struct (which are individually packed according to the same rules).
106unsigned int HLSLVariableRegisterCount(const Varying &variable);
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400107unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
Jamie Madill834e8b72014-04-11 13:33:58 -0400108
109}
110
111#endif // COMMON_BLOCKLAYOUT_H_