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 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 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