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
25 namespace android {
26 namespace spirit {
27
TEST(BuilderTest,testBuildAndSerialize)28 TEST(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 m->addString("Foo Bar Baz");
48
49 auto FloatTy = m->getFloatType(32);
50 auto VF4Ty = m->getVectorType(FloatTy, 4);
51 auto ArrTy = m->getRuntimeArrayType(VF4Ty);
52 ArrTy->decorate(Decoration::ArrayStride)->addExtraOperand(16);
53 auto StructTy = m->getStructType(ArrTy);
54 StructTy->decorate(Decoration::BufferBlock);
55 StructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
56
57 auto StructPtrTy = m->getPointerType(StorageClass::Uniform, StructTy);
58
59 auto InputBuffer = b.MakeVariable(StructPtrTy, StorageClass::Uniform);
60 InputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
61 InputBuffer->decorate(Decoration::Binding)->addExtraOperand(2);
62 m->addVariable(InputBuffer);
63
64 auto ArrTy2 = m->getRuntimeArrayType(VF4Ty);
65 ArrTy2->decorate(Decoration::ArrayStride)->addExtraOperand(16);
66
67 auto StructTy2 = m->getStructType(ArrTy2);
68 StructTy2->decorate(Decoration::BufferBlock);
69 StructTy2->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
70
71 auto StructPtrTy2 = m->getPointerType(StorageClass::Uniform, StructTy2);
72 auto OutputBuffer = b.MakeVariable(StructPtrTy2, StorageClass::Uniform);
73 OutputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
74 OutputBuffer->decorate(Decoration::Binding)->addExtraOperand(1);
75 m->addVariable(OutputBuffer);
76
77 auto VoidTy = m->getVoidType();
78 auto FuncTy = m->getFunctionType(VoidTy, nullptr, 0);
79
80 auto UIntTy = m->getUnsignedIntType(32);
81 auto V3UIntTy = m->getVectorType(UIntTy, 3);
82 auto V3UIntPtrTy = m->getPointerType(StorageClass::Input, V3UIntTy);
83
84 auto InvocationID = m->getInvocationId();
85
86 auto ConstFour = m->getConstant(UIntTy, 4);
87 auto ConstOne = m->getConstant(UIntTy, 1);
88 #if 0
89 auto GSize = b.MakeVariable(V3UIntPtrTy, StorageClass::Input);
90 GSize->decorate(Decoration::BuiltIn)->addExtraOperand(BuiltIn::WorkgroupSize);
91 m->addVariable(GSize);
92 #endif
93
94 auto GNum = m->getNumWorkgroups();
95
96 const char *funcName = "invert";
97
98 auto Func = b.MakeFunctionDefinition(VoidTy, FunctionControl::None, FuncTy);
99 // TODO: Add method setName() to class FunctionDefinition
100 // Func->setName(funcName); // I.e., OpName %func funcName
101 m->addFunctionDefinition(Func);
102
103 auto Blk = b.MakeBlock();
104 Func->addBlock(Blk);
105
106 Blk->addInstruction(b.MakeLabel());
107
108 auto IntTy = m->getIntType(32);
109 auto ConstZero = m->getConstant(UIntTy, 0);
110 auto UIntPtrTy = m->getPointerType(StorageClass::Input, UIntTy);
111
112 auto IID = b.MakeLoad(V3UIntTy, InvocationID);
113 Blk->addInstruction(IID);
114
115 auto XValue = b.MakeCompositeExtract(UIntTy, IID, {0});
116 Blk->addInstruction(XValue);
117
118 auto YValue = b.MakeCompositeExtract(UIntTy, IID, {1});
119 Blk->addInstruction(YValue);
120
121 #if 0
122 auto PtrToGSizeX = b.MakeAccessChain(UIntPtrTy, GSize, {ConstZero});
123 Blk->addInstruction(PtrToGSizeX);
124
125 auto GSizeX = b.MakeLoad(UIntTy, PtrToGSizeX);
126 Blk->addInstruction(GSizeX);
127 #else
128 auto &GSizeX = ConstOne;
129 #endif
130
131 auto Tmp1 = b.MakeIMul(UIntTy, YValue, GSizeX);
132 Blk->addInstruction(Tmp1);
133
134 auto PtrToGNumX = b.MakeAccessChain(UIntPtrTy, GNum, {ConstZero});
135 Blk->addInstruction(PtrToGNumX);
136
137 auto GNumX = b.MakeLoad(UIntTy, PtrToGNumX);
138 Blk->addInstruction(GNumX);
139
140 auto OffsetY = b.MakeIMul(UIntTy, Tmp1, GNumX);
141 Blk->addInstruction(OffsetY);
142
143 auto Index = b.MakeIAdd(UIntTy, OffsetY, XValue);
144 Blk->addInstruction(Index);
145
146 auto VF4PtrTy = m->getPointerType(StorageClass::Function, VF4Ty);
147 auto Ptr = b.MakeAccessChain(VF4PtrTy, InputBuffer, {ConstZero, Index});
148 Blk->addInstruction(Ptr);
149
150 auto Value = b.MakeLoad(VF4Ty, Ptr);
151 Blk->addInstruction(Value);
152
153 // Here is the place to do something about the value. As is, this is a copy
154 // kernel.
155 auto ConstOneF = m->getConstant(FloatTy, 1.0f);
156 auto ConstOneVF4 = m->getConstantComposite(VF4Ty, ConstOneF, ConstOneF,
157 ConstOneF, ConstOneF);
158 auto Result = b.MakeFSub(VF4Ty, ConstOneVF4, Value);
159 Blk->addInstruction(Result);
160
161 auto OutPtr = b.MakeAccessChain(VF4PtrTy, OutputBuffer, {ConstZero, Index});
162 Blk->addInstruction(OutPtr);
163
164 Blk->addInstruction(b.MakeStore(OutPtr, Result));
165 Blk->addInstruction(b.MakeReturn());
166
167 m->addEntryPoint(
168 b.MakeEntryPointDefinition(ExecutionModel::GLCompute, Func, funcName)
169 ->addToInterface(InvocationID)
170 ->addToInterface(GNum)
171 // ->addToInterface(GSize)
172 ->setLocalSize(1, 1, 1));
173
174 EXPECT_EQ(1, countEntity<MemoryModelInst>(m));
175 EXPECT_EQ(1, countEntity<EntryPointInst>(m));
176 EXPECT_EQ(3, countEntity<LoadInst>(m));
177 EXPECT_EQ(1, countEntity<ReturnInst>(m));
178 EXPECT_EQ(1, countEntity<ExecutionModeInst>(m));
179 EXPECT_EQ(2, countEntity<TypeRuntimeArrayInst>(m));
180 EXPECT_EQ(2, countEntity<TypeStructInst>(m));
181 EXPECT_EQ(5, countEntity<TypePointerInst>(m));
182 EXPECT_EQ(1, countEntity<StringInst>(m));
183
184 m->consolidateAnnotations();
185
186 auto words = Serialize<Module>(m);
187
188 auto m1 = Deserialize<Module>(words);
189 ASSERT_NE(nullptr, m1);
190
191 auto words1 = Serialize<Module>(m1);
192
193 EXPECT_TRUE(words == words1);
194 }
195
TEST(BuilderTest,testLoadAndModify)196 TEST(BuilderTest, testLoadAndModify) {
197 static const std::string testDataPath(
198 "frameworks/rs/rsov/compiler/spirit/test_data/");
199 const std::string &fullPath = getAbsolutePath(testDataPath + "greyscale.spv");
200
201 Module *m = Deserialize<Module>(readFile<uint32_t>(fullPath.c_str()));
202
203 ASSERT_NE(nullptr, m);
204
205 std::unique_ptr<Module> mDeleter(m);
206
207 Builder b;
208
209 auto IntTy = m->getIntType(32);
210 auto FuncTy = m->getFunctionType(IntTy, {IntTy});
211
212 auto Func = b.MakeFunctionDefinition(IntTy, FunctionControl::None, FuncTy);
213 // TODO: Add method setName() to class FunctionDefinition
214 // Func->setName(funcName); // I.e., OpName %func funcName
215 m->addFunctionDefinition(Func);
216
217 auto Blk = b.MakeBlock();
218 Func->addBlock(Blk);
219
220 Blk->addInstruction(b.MakeReturn());
221
222 m->consolidateAnnotations();
223
224 auto words = Serialize<Module>(m);
225
226 auto m1 = Deserialize<Module>(words);
227 ASSERT_NE(nullptr, m1);
228
229 auto words1 = Serialize<Module>(m1);
230
231 EXPECT_TRUE(words == words1);
232 }
233
234 } // namespace spirit
235 } // namespace android
236