1 //
2 // Copyright 2013 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/hlsl/blocklayoutHLSL.h"
11
12 #include "common/mathutil.h"
13 #include "common/utilities.h"
14
15 namespace sh
16 {
17
HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy,bool transposeMatrices)18 HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices)
19 : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices)
20 {}
21
enterAggregateType(const ShaderVariable & structVar)22 void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar)
23 {
24 align(kComponentsPerRegister);
25 }
26
exitAggregateType(const ShaderVariable & structVar)27 void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {}
28
getBlockLayoutInfo(GLenum typeIn,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int * arrayStrideOut,int * matrixStrideOut)29 void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
30 const std::vector<unsigned int> &arraySizes,
31 bool isRowMajorMatrix,
32 int *arrayStrideOut,
33 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)) == kBytesPerComponent);
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() || gl::IsMatrixType(type) || !arraySizes.empty())
47 {
48 align(kComponentsPerRegister);
49 }
50
51 if (gl::IsMatrixType(type))
52 {
53 matrixStride = kComponentsPerRegister;
54
55 if (!arraySizes.empty())
56 {
57 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
58 arrayStride = kComponentsPerRegister * numRegisters;
59 }
60 }
61 else if (!arraySizes.empty())
62 {
63 arrayStride = kComponentsPerRegister;
64 }
65 else if (isPacked())
66 {
67 int numComponents = gl::VariableComponentCount(type);
68 if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister)
69 {
70 align(kComponentsPerRegister);
71 }
72 }
73
74 *matrixStrideOut = matrixStride;
75 *arrayStrideOut = arrayStride;
76 }
77
advanceOffset(GLenum typeIn,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)78 void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
79 const std::vector<unsigned int> &arraySizes,
80 bool isRowMajorMatrix,
81 int arrayStride,
82 int matrixStride)
83 {
84 GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
85
86 if (!arraySizes.empty())
87 {
88 unsigned int arraySize = gl::ArraySizeProduct(arraySizes);
89 if (arraySize > 0)
90 {
91 mCurrentOffset += arrayStride * (arraySize - 1);
92 }
93 }
94
95 if (gl::IsMatrixType(type))
96 {
97 ASSERT(matrixStride == kComponentsPerRegister);
98 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
99 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
100 mCurrentOffset += kComponentsPerRegister * (numRegisters - 1);
101 mCurrentOffset += numComponents;
102 }
103 else if (isPacked())
104 {
105 mCurrentOffset += gl::VariableComponentCount(type);
106 }
107 else
108 {
109 mCurrentOffset += kComponentsPerRegister;
110 }
111 }
112
skipRegisters(unsigned int numRegisters)113 void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
114 {
115 mCurrentOffset += (numRegisters * kComponentsPerRegister);
116 }
117
GetStrategyFor(ShShaderOutput outputType)118 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(
119 ShShaderOutput outputType)
120 {
121 switch (outputType)
122 {
123 case SH_HLSL_3_0_OUTPUT:
124 return ENCODE_LOOSE;
125 case SH_HLSL_4_1_OUTPUT:
126 case SH_HLSL_4_0_FL9_3_OUTPUT:
127 return ENCODE_PACKED;
128 default:
129 UNREACHABLE();
130 return ENCODE_PACKED;
131 }
132 }
133
134 template <class ShaderVarType>
HLSLVariableRegisterCount(const ShaderVarType & variable,HLSLBlockEncoder * encoder)135 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
136 {
137 if (variable.isStruct())
138 {
139 for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
140 {
141 encoder->enterAggregateType(variable);
142
143 for (const ShaderVariable &field : variable.fields)
144 {
145 HLSLVariableRegisterCount(field, encoder);
146 }
147
148 encoder->exitAggregateType(variable);
149 }
150 }
151 else
152 {
153 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
154 encoder->encodeType(variable.type, variable.arraySizes, false);
155 }
156 }
157
HLSLVariableRegisterCount(const ShaderVariable & variable,ShShaderOutput outputType)158 unsigned int HLSLVariableRegisterCount(const ShaderVariable &variable, ShShaderOutput outputType)
159 {
160 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true);
161 HLSLVariableRegisterCount(variable, &encoder);
162
163 const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister);
164 return static_cast<unsigned int>(
165 rx::roundUp<size_t>(encoder.getCurrentOffset(), registerBytes) / registerBytes);
166 }
167 } // namespace sh
168