Home | History | Annotate | Download | only in spirit
      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