blob: f32cf2cf89049bfd3853c97f18085316e4e4fd30 [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 {
116 case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
117 case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
118 default: UNREACHABLE(); return ENCODE_PACKED;
119 }
120}
121
122template <class ShaderVarType>
123void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
124{
125 if (variable.isStruct())
126 {
127 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
128 {
129 encoder->enterAggregateType();
130
131 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
132 {
133 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
134 }
135
136 encoder->exitAggregateType();
137 }
138 }
139 else
140 {
141 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
142 encoder->encodeType(variable.type, variable.arraySize, false);
143 }
144}
145
146unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices)
147{
148 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
149 encoder.setTransposeMatrices(transposeMatrices);
150 HLSLVariableRegisterCount(variable, &encoder);
151
152 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
153 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
154}
155
156unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
157{
158 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
159 HLSLVariableRegisterCount(variable, &encoder);
160
161 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
162 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
163}
164
165}