blob: 61b6ed74559daa129ea2ea7c2415ab105789d588 [file] [log] [blame]
Jamie Madillf91ce812014-06-13 10:04:34 -04001//
2// Copyright (c) 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// UniformHLSL.cpp:
7// Methods for GLSL to HLSL translation for uniforms and interface blocks.
8//
9
10#include "OutputHLSL.h"
11#include "common/blocklayout.h"
12#include "common/utilities.h"
13#include "compiler/translator/UniformHLSL.h"
14#include "compiler/translator/StructureHLSL.h"
15#include "compiler/translator/util.h"
16#include "compiler/translator/UtilsHLSL.h"
Jamie Madill54ad4f82014-09-03 09:40:46 -040017#include "compiler/translator/TranslatorHLSL.h"
Jamie Madillf91ce812014-06-13 10:04:34 -040018
19namespace sh
20{
21
Jamie Madillf91ce812014-06-13 10:04:34 -040022static const char *UniformRegisterPrefix(const TType &type)
23{
24 if (IsSampler(type.getBasicType()))
25 {
26 return "s";
27 }
28 else
29 {
30 return "c";
31 }
32}
33
Jamie Madillf91ce812014-06-13 10:04:34 -040034static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
35{
36 const TType &fieldType = *field.type();
37 const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
38 ASSERT(matrixPacking != EmpUnspecified);
39 TStructure *structure = fieldType.getStruct();
40
41 if (fieldType.isMatrix())
42 {
43 // Use HLSL row-major packing for GLSL column-major matrices
44 const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
45 return matrixPackString + " " + TypeString(fieldType);
46 }
47 else if (structure)
48 {
49 // Use HLSL row-major packing for GLSL column-major matrices
50 return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
51 blockStorage == EbsStd140);
52 }
53 else
54 {
55 return TypeString(fieldType);
56 }
57}
58
59static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
60{
61 return DecoratePrivate(interfaceBlock.name()) + "_type";
62}
63
Jamie Madill54ad4f82014-09-03 09:40:46 -040064UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator)
Jamie Madillf91ce812014-06-13 10:04:34 -040065 : mUniformRegister(0),
66 mInterfaceBlockRegister(0),
67 mSamplerRegister(0),
68 mStructureHLSL(structureHLSL),
Jamie Madill54ad4f82014-09-03 09:40:46 -040069 mOutputType(translator->getOutputType()),
70 mUniforms(translator->getUniforms())
Jamie Madillf91ce812014-06-13 10:04:34 -040071{}
72
73void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
74{
75 mUniformRegister = registerCount;
76}
77
78void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
79{
80 mInterfaceBlockRegister = registerCount;
81}
82
Jamie Madill54ad4f82014-09-03 09:40:46 -040083const Uniform *UniformHLSL::findUniformByName(const TString &name) const
84{
85 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
86 {
87 if (mUniforms[uniformIndex].name == name.c_str())
88 {
89 return &mUniforms[uniformIndex];
90 }
91 }
92
93 UNREACHABLE();
94 return NULL;
95}
96
Jamie Madill9fe25e92014-07-18 10:33:08 -040097unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
Jamie Madillf91ce812014-06-13 10:04:34 -040098{
Jamie Madill9fe25e92014-07-18 10:33:08 -040099 unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
Jamie Madillf91ce812014-06-13 10:04:34 -0400100
Jamie Madill54ad4f82014-09-03 09:40:46 -0400101 const Uniform *uniform = findUniformByName(name);
102 ASSERT(uniform);
Jamie Madill77f74852014-07-08 15:02:34 -0400103
Jamie Madill54ad4f82014-09-03 09:40:46 -0400104 mUniformRegisterMap[uniform->name] = registerIndex;
Jamie Madillf91ce812014-06-13 10:04:34 -0400105
Jamie Madill54ad4f82014-09-03 09:40:46 -0400106 unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
107
108 if (gl::IsSampler(uniform->type))
Jamie Madillf91ce812014-06-13 10:04:34 -0400109 {
Jamie Madill77f74852014-07-08 15:02:34 -0400110 mSamplerRegister += registerCount;
Jamie Madillf91ce812014-06-13 10:04:34 -0400111 }
112 else
113 {
Jamie Madill77f74852014-07-08 15:02:34 -0400114 mUniformRegister += registerCount;
Jamie Madillf91ce812014-06-13 10:04:34 -0400115 }
116
117 return registerIndex;
118}
119
Jamie Madillf91ce812014-06-13 10:04:34 -0400120TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
121{
122 TString uniforms;
123
124 for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
125 uniformIt != referencedUniforms.end(); uniformIt++)
126 {
127 const TIntermSymbol &uniform = *uniformIt->second;
128 const TType &type = uniform.getType();
129 const TString &name = uniform.getSymbol();
130
Jamie Madill9fe25e92014-07-18 10:33:08 -0400131 unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
Jamie Madillf91ce812014-06-13 10:04:34 -0400132
133 if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
134 {
135 uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
136 " : register(s" + str(registerIndex) + ");\n";
137
138 uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
139 " : register(t" + str(registerIndex) + ");\n";
140 }
141 else
142 {
143 const TStructure *structure = type.getStruct();
Shannon Woodsbc75f362014-08-11 14:08:19 -0400144 // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
Shannon Woodsb8c0a832014-08-15 16:41:12 -0400145 // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
146 // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are
147 // permitted.
Shannon Woodsbc75f362014-08-11 14:08:19 -0400148 const TString &typeName = ((structure && !structure->name().empty()) ?
149 QualifiedStructNameString(*structure, false, false) : TypeString(type));
Jamie Madillf91ce812014-06-13 10:04:34 -0400150
151 const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
152
153 uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
154 }
155 }
156
157 return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
158}
159
160TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
161{
162 TString interfaceBlocks;
163
164 for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
165 interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
166 {
167 const TType &nodeType = interfaceBlockIt->second->getType();
168 const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
Jamie Madillf91ce812014-06-13 10:04:34 -0400169
170 unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
Jamie Madilld4116ff2014-07-11 17:02:01 -0400171 unsigned int activeRegister = mInterfaceBlockRegister;
172
Jamie Madill54ad4f82014-09-03 09:40:46 -0400173 mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
Jamie Madillf91ce812014-06-13 10:04:34 -0400174 mInterfaceBlockRegister += std::max(1u, arraySize);
175
Jamie Madill54ad4f82014-09-03 09:40:46 -0400176 // FIXME: interface block field names
Jamie Madillf91ce812014-06-13 10:04:34 -0400177
178 if (interfaceBlock.hasInstanceName())
179 {
180 interfaceBlocks += interfaceBlockStructString(interfaceBlock);
181 }
182
183 if (arraySize > 0)
184 {
185 for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
186 {
Jamie Madilld4116ff2014-07-11 17:02:01 -0400187 interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
Jamie Madillf91ce812014-06-13 10:04:34 -0400188 }
189 }
190 else
191 {
Jamie Madilld4116ff2014-07-11 17:02:01 -0400192 interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
Jamie Madillf91ce812014-06-13 10:04:34 -0400193 }
194 }
195
196 return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
197}
198
199TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
200{
201 const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
202 const TString &blockName = interfaceBlock.name() + arrayIndexString;
203 TString hlsl;
204
205 hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
206 "{\n";
207
208 if (interfaceBlock.hasInstanceName())
209 {
210 hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " +
211 interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
212 }
213 else
214 {
215 const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
216 hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
217 }
218
219 hlsl += "};\n\n";
220
221 return hlsl;
222}
223
224TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
225{
226 if (!interfaceBlock.hasInstanceName())
227 {
228 return "";
229 }
230 else if (interfaceBlock.isArray())
231 {
232 return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
233 }
234 else
235 {
236 return Decorate(interfaceBlock.instanceName());
237 }
238}
239
240TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
241{
242 TString hlsl;
243
244 Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
245
246 for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
247 {
248 const TField &field = *interfaceBlock.fields()[typeIndex];
249 const TType &fieldType = *field.type();
250
251 if (blockStorage == EbsStd140)
252 {
253 // 2 and 3 component vector types in some cases need pre-padding
Jamie Madill33a74bd2014-08-18 15:47:59 -0400254 hlsl += padHelper.prePaddingString(fieldType);
Jamie Madillf91ce812014-06-13 10:04:34 -0400255 }
256
257 hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) +
258 " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";
259
260 // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
261 if (blockStorage == EbsStd140)
262 {
263 const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
264 hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
265 }
266 }
267
268 return hlsl;
269}
270
271TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
272{
273 const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
274
275 return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
276 "{\n" +
277 interfaceBlockMembersString(interfaceBlock, blockStorage) +
278 "};\n\n";
279}
280
Jamie Madillf91ce812014-06-13 10:04:34 -0400281}