builder_test.cpp revision 3e5fbb6faf66488ba49c9d2396350ae567dba315
1/*
2 * Copyright 2017, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "builder.h"
18
19#include "file_utils.h"
20#include "instructions.h"
21#include "module.h"
22#include "test_utils.h"
23#include "gtest/gtest.h"
24
25namespace android {
26namespace spirit {
27
28TEST(BuilderTest, testBuildAndSerialize) {
29  Builder b;
30
31  Module *m = b.MakeModule();
32
33  ASSERT_NE(nullptr, m);
34
35  m->addCapability(Capability::Shader);
36  m->addCapability(Capability::Addresses);
37  m->setMemoryModel(AddressingModel::Physical32, MemoryModel::GLSL450);
38
39  m->addExtInstImport("GLSL.std.450");
40
41  // Shall we explicitly create the debug info section first?
42  m->addSource(SourceLanguage::GLSL, 450);
43  m->addSourceExtension("GL_ARB_separate_shader_objects");
44  m->addSourceExtension("GL_ARB_shading_language_420pack");
45  m->addSourceExtension("GL_GOOGLE_cpp_style_line_directive");
46  m->addSourceExtension("GL_GOOGLE_include_directive");
47
48  auto FloatTy = m->getFloatType(32);
49  auto VF4Ty = m->getVectorType(FloatTy, 4);
50  auto ArrTy = m->getRuntimeArrayType(VF4Ty);
51  ArrTy->decorate(Decoration::ArrayStride)->addExtraOperand(16);
52  auto StructTy = m->getStructType(ArrTy);
53  StructTy->decorate(Decoration::BufferBlock);
54  StructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
55
56  auto StructPtrTy = m->getPointerType(StorageClass::Uniform, StructTy);
57
58  auto InputBuffer = b.MakeVariable(StructPtrTy, StorageClass::Uniform);
59  InputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
60  InputBuffer->decorate(Decoration::Binding)->addExtraOperand(2);
61  m->addVariable(InputBuffer);
62
63  auto ArrTy2 = m->getRuntimeArrayType(VF4Ty);
64  ArrTy2->decorate(Decoration::ArrayStride)->addExtraOperand(16);
65
66  auto StructTy2 = m->getStructType(ArrTy2);
67  StructTy2->decorate(Decoration::BufferBlock);
68  StructTy2->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
69
70  auto StructPtrTy2 = m->getPointerType(StorageClass::Uniform, StructTy2);
71  auto OutputBuffer = b.MakeVariable(StructPtrTy2, StorageClass::Uniform);
72  OutputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
73  OutputBuffer->decorate(Decoration::Binding)->addExtraOperand(1);
74  m->addVariable(OutputBuffer);
75
76  auto VoidTy = m->getVoidType();
77  auto FuncTy = m->getFunctionType(VoidTy, nullptr, 0);
78
79  auto UIntTy = m->getUnsignedIntType(32);
80  auto V3UIntTy = m->getVectorType(UIntTy, 3);
81  auto V3UIntPtrTy = m->getPointerType(StorageClass::Input, V3UIntTy);
82
83  auto InvocationID = m->getInvocationId();
84
85  auto ConstFour = m->getConstant(UIntTy, 4);
86  auto ConstOne = m->getConstant(UIntTy, 1);
87#if 0
88  auto GSize = b.MakeVariable(V3UIntPtrTy, StorageClass::Input);
89  GSize->decorate(Decoration::BuiltIn)->addExtraOperand(BuiltIn::WorkgroupSize);
90  m->addVariable(GSize);
91#endif
92
93  auto GNum = m->getNumWorkgroups();
94
95  const char *funcName = "invert";
96
97  auto Func = b.MakeFunctionDefinition(VoidTy, FunctionControl::None, FuncTy);
98  // TODO: Add method setName() to class FunctionDefinition
99  // Func->setName(funcName);  // I.e., OpName %func funcName
100  m->addFunctionDefinition(Func);
101
102  auto Blk = b.MakeBlock();
103  Func->addBlock(Blk);
104
105  Blk->addInstruction(b.MakeLabel());
106
107  auto IntTy = m->getIntType(32);
108  auto ConstZero = m->getConstant(UIntTy, 0);
109  auto UIntPtrTy = m->getPointerType(StorageClass::Input, UIntTy);
110
111  auto IID = b.MakeLoad(V3UIntTy, InvocationID);
112  Blk->addInstruction(IID);
113
114  auto XValue = b.MakeCompositeExtract(UIntTy, IID, {0});
115  Blk->addInstruction(XValue);
116
117  auto YValue = b.MakeCompositeExtract(UIntTy, IID, {1});
118  Blk->addInstruction(YValue);
119
120#if 0
121  auto PtrToGSizeX = b.MakeAccessChain(UIntPtrTy, GSize, {ConstZero});
122  Blk->addInstruction(PtrToGSizeX);
123
124  auto GSizeX = b.MakeLoad(UIntTy, PtrToGSizeX);
125  Blk->addInstruction(GSizeX);
126#else
127  auto &GSizeX = ConstOne;
128#endif
129
130  auto Tmp1 = b.MakeIMul(UIntTy, YValue, GSizeX);
131  Blk->addInstruction(Tmp1);
132
133  auto PtrToGNumX = b.MakeAccessChain(UIntPtrTy, GNum, {ConstZero});
134  Blk->addInstruction(PtrToGNumX);
135
136  auto GNumX = b.MakeLoad(UIntTy, PtrToGNumX);
137  Blk->addInstruction(GNumX);
138
139  auto OffsetY = b.MakeIMul(UIntTy, Tmp1, GNumX);
140  Blk->addInstruction(OffsetY);
141
142  auto Index = b.MakeIAdd(UIntTy, OffsetY, XValue);
143  Blk->addInstruction(Index);
144
145  auto VF4PtrTy = m->getPointerType(StorageClass::Function, VF4Ty);
146  auto Ptr = b.MakeAccessChain(VF4PtrTy, InputBuffer, {ConstZero, Index});
147  Blk->addInstruction(Ptr);
148
149  auto Value = b.MakeLoad(VF4Ty, Ptr);
150  Blk->addInstruction(Value);
151
152  // Here is the place to do something about the value. As is, this is a copy
153  // kernel.
154  auto ConstOneF = m->getConstant(FloatTy, 1.0f);
155  auto ConstOneVF4 = m->getConstantComposite(VF4Ty, ConstOneF, ConstOneF,
156                                             ConstOneF, ConstOneF);
157  auto Result = b.MakeFSub(VF4Ty, ConstOneVF4, Value);
158  Blk->addInstruction(Result);
159
160  auto OutPtr = b.MakeAccessChain(VF4PtrTy, OutputBuffer, {ConstZero, Index});
161  Blk->addInstruction(OutPtr);
162
163  Blk->addInstruction(b.MakeStore(OutPtr, Result));
164  Blk->addInstruction(b.MakeReturn());
165
166  m->addEntryPoint(
167      b.MakeEntryPointDefinition(ExecutionModel::GLCompute, Func, funcName)
168          ->addToInterface(InvocationID)
169          ->addToInterface(GNum)
170          //          ->addToInterface(GSize)
171          ->setLocalSize(1, 1, 1));
172
173  EXPECT_EQ(1, countEntity<MemoryModelInst>(m));
174  EXPECT_EQ(1, countEntity<EntryPointInst>(m));
175  EXPECT_EQ(3, countEntity<LoadInst>(m));
176  EXPECT_EQ(1, countEntity<ReturnInst>(m));
177  EXPECT_EQ(1, countEntity<ExecutionModeInst>(m));
178  EXPECT_EQ(2, countEntity<TypeRuntimeArrayInst>(m));
179  EXPECT_EQ(2, countEntity<TypeStructInst>(m));
180  EXPECT_EQ(5, countEntity<TypePointerInst>(m));
181
182  m->consolidateAnnotations();
183
184  auto words = Serialize<Module>(m);
185
186  auto m1 = Deserialize<Module>(words);
187  ASSERT_NE(nullptr, m1);
188
189  auto words1 = Serialize<Module>(m1);
190
191  EXPECT_TRUE(words == words1);
192}
193
194TEST(BuilderTest, testLoadAndModify) {
195  static const std::string testDataPath(
196      "frameworks/rs/rsov/compiler/spirit/test_data/");
197  const std::string &fullPath = getAbsolutePath(testDataPath + "greyscale.spv");
198
199  Module *m = Deserialize<Module>(readFile<uint32_t>(fullPath.c_str()));
200
201  ASSERT_NE(nullptr, m);
202
203  std::unique_ptr<Module> mDeleter(m);
204
205  Builder b;
206
207  auto IntTy = m->getIntType(32);
208  auto FuncTy = m->getFunctionType(IntTy, {IntTy});
209
210  auto Func = b.MakeFunctionDefinition(IntTy, FunctionControl::None, FuncTy);
211  // TODO: Add method setName() to class FunctionDefinition
212  // Func->setName(funcName);  // I.e., OpName %func funcName
213  m->addFunctionDefinition(Func);
214
215  auto Blk = b.MakeBlock();
216  Func->addBlock(Blk);
217
218  Blk->addInstruction(b.MakeReturn());
219
220  m->consolidateAnnotations();
221
222  auto words = Serialize<Module>(m);
223
224  auto m1 = Deserialize<Module>(words);
225  ASSERT_NE(nullptr, m1);
226
227  auto words1 = Serialize<Module>(m1);
228
229  EXPECT_TRUE(words == words1);
230}
231
232} // namespace spirit
233} // namespace android
234