blob: 43119248eb91e3590bbf79576bec6da7f72f1d09 [file] [log] [blame]
Daniel Bratell73941de2015-02-25 14:34:49 +01001//
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.cpp:
7// Implementation for block layout classes and methods.
8//
9
10#include "compiler/translator/blocklayoutHLSL.h"
11
12#include "common/mathutil.h"
13#include "common/utilities.h"
14
15namespace sh
16{
17
18HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
19 : mEncoderStrategy(strategy),
20 mTransposeMatrices(false)
21{
22}
23
24void HLSLBlockEncoder::enterAggregateType()
25{
26 nextRegister();
27}
28
29void HLSLBlockEncoder::exitAggregateType()
30{
31}
32
33void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
34{
35 GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
36
37 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
38 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
39
40 int matrixStride = 0;
41 int arrayStride = 0;
42
43 // if variables are not to be packed, or we're about to
44 // pack a matrix or array, skip to the start of the next
45 // register
46 if (!isPacked() ||
47 gl::IsMatrixType(type) ||
48 arraySize > 0)
49 {
50 nextRegister();
51 }
52
53 if (gl::IsMatrixType(type))
54 {
55 matrixStride = ComponentsPerRegister;
56
57 if (arraySize > 0)
58 {
59 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
60 arrayStride = ComponentsPerRegister * numRegisters;
61 }
62 }
63 else if (arraySize > 0)
64 {
65 arrayStride = ComponentsPerRegister;
66 }
67 else if (isPacked())
68 {
69 int numComponents = gl::VariableComponentCount(type);
70 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
71 {
72 nextRegister();
73 }
74 }
75
76 *matrixStrideOut = matrixStride;
77 *arrayStrideOut = arrayStride;
78}
79
80void HLSLBlockEncoder::advanceOffset(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
81{
82 GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
83
84 if (arraySize > 0)
85 {
86 mCurrentOffset += arrayStride * (arraySize - 1);
87 }
88
89 if (gl::IsMatrixType(type))
90 {
91 ASSERT(matrixStride == ComponentsPerRegister);
92 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
93 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
94 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
95 mCurrentOffset += numComponents;
96 }
97 else if (isPacked())
98 {
99 mCurrentOffset += gl::VariableComponentCount(type);
100 }
101 else
102 {
103 mCurrentOffset += ComponentsPerRegister;
104 }
105}
106
107void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
108{
109 mCurrentOffset += (numRegisters * ComponentsPerRegister);
110}
111
112HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
113{
114 switch (outputType)
115 {
Olli Etuaho9b4e8622015-12-22 15:53:22 +0200116 case SH_HLSL_3_0_OUTPUT:
117 return ENCODE_LOOSE;
118 case SH_HLSL_4_1_OUTPUT:
119 case SH_HLSL_4_0_FL9_3_OUTPUT:
120 return ENCODE_PACKED;
121 default:
122 UNREACHABLE();
123 return ENCODE_PACKED;
Daniel Bratell73941de2015-02-25 14:34:49 +0100124 }
125}
126
127template <class ShaderVarType>
128void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
129{
130 if (variable.isStruct())
131 {
132 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
133 {
134 encoder->enterAggregateType();
135
136 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
137 {
138 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
139 }
140
141 encoder->exitAggregateType();
142 }
143 }
144 else
145 {
146 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
147 encoder->encodeType(variable.type, variable.arraySize, false);
148 }
149}
150
151unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices)
152{
153 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
154 encoder.setTransposeMatrices(transposeMatrices);
155 HLSLVariableRegisterCount(variable, &encoder);
156
157 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
158 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
159}
160
161unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
162{
163 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill9d82be82015-07-20 14:36:50 -0400164 encoder.setTransposeMatrices(true);
Daniel Bratell73941de2015-02-25 14:34:49 +0100165 HLSLVariableRegisterCount(variable, &encoder);
166
167 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
168 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
169}
170
171}