• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 The Khronos Group Inc.
2 // Copyright (c) 2018 Valve Corporation
3 // Copyright (c) 2018 LunarG Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef LIBSPIRV_OPT_INST_BINDLESS_CHECK_PASS_H_
18 #define LIBSPIRV_OPT_INST_BINDLESS_CHECK_PASS_H_
19 
20 #include "instrument_pass.h"
21 
22 namespace spvtools {
23 namespace opt {
24 
25 // This class/pass is designed to support the bindless (descriptor indexing)
26 // GPU-assisted validation layer of
27 // https://github.com/KhronosGroup/Vulkan-ValidationLayers. Its internal and
28 // external design may change as the layer evolves.
29 class InstBindlessCheckPass : public InstrumentPass {
30  public:
InstBindlessCheckPass(uint32_t shader_id)31   InstBindlessCheckPass(uint32_t shader_id)
32       : InstrumentPass(0, shader_id, true, true) {}
33 
34   ~InstBindlessCheckPass() override = default;
35 
36   // See optimizer.hpp for pass user documentation.
37   Status Process() override;
38 
name()39   const char* name() const override { return "inst-bindless-check-pass"; }
40 
41  private:
42   void GenDescCheckCode(BasicBlock::iterator ref_inst_itr,
43                         UptrVectorIterator<BasicBlock> ref_block_itr,
44                         uint32_t stage_idx,
45                         std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
46 
47   uint32_t GenDescCheckFunctionId();
48 
49   uint32_t GenDescCheckCall(uint32_t inst_idx, uint32_t stage_idx,
50                             uint32_t var_id, uint32_t index_id,
51                             uint32_t byte_offset, InstructionBuilder* builder);
52 
53   // Analysis data for descriptor reference components, generated by
54   // AnalyzeDescriptorReference. It is necessary and sufficient for further
55   // analysis and regeneration of the reference.
56   typedef struct RefAnalysis {
57     uint32_t desc_load_id{0};
58     uint32_t image_id{0};
59     uint32_t load_id{0};
60     uint32_t ptr_id{0};
61     uint32_t var_id{0};
62     uint32_t set{0};
63     uint32_t binding{0};
64     uint32_t desc_idx_id{0};
65     uint32_t strg_class{0};
66     Instruction* ref_inst{nullptr};
67   } RefAnalysis;
68 
69   // Return size of type |ty_id| in bytes. Use |matrix_stride| and |col_major|
70   // for matrix type, or for vector type if vector is |in_matrix|.
71   uint32_t ByteSize(uint32_t ty_id, uint32_t matrix_stride, bool col_major,
72                     bool in_matrix);
73 
74   // Return stride of type |ty_id| with decoration |stride_deco|. Return 0
75   // if not found
76   uint32_t FindStride(uint32_t ty_id, uint32_t stride_deco);
77 
78   // Generate index of last byte referenced by buffer reference |ref|
79   uint32_t GenLastByteIdx(RefAnalysis* ref, InstructionBuilder* builder);
80 
81   // Clone original image computation starting at |image_id| into |builder|.
82   // This may generate more than one instruction if necessary.
83   uint32_t CloneOriginalImage(uint32_t image_id, InstructionBuilder* builder);
84 
85   // Clone original original reference encapsulated by |ref| into |builder|.
86   // This may generate more than one instruction if necessary.
87   uint32_t CloneOriginalReference(RefAnalysis* ref,
88                                   InstructionBuilder* builder);
89 
90   // If |inst| references through an image, return the id of the image it
91   // references through. Else return 0.
92   uint32_t GetImageId(Instruction* inst);
93 
94   // Get pointee type inst of pointer value |ptr_inst|.
95   Instruction* GetPointeeTypeInst(Instruction* ptr_inst);
96 
97   // Analyze descriptor reference |ref_inst| and save components into |ref|.
98   // Return true if |ref_inst| is a descriptor reference, false otherwise.
99   bool AnalyzeDescriptorReference(Instruction* ref_inst, RefAnalysis* ref);
100 
101   // Generate instrumentation code for generic test result |check_id|, starting
102   // with |builder| of block |new_blk_ptr|, adding new blocks to |new_blocks|.
103   // Generate conditional branch to a valid or invalid branch. Generate valid
104   // block which does original reference |ref|. Generate invalid block which
105   // writes debug error output utilizing |ref|, |error_id|, |length_id| and
106   // |stage_idx|. Generate merge block for valid and invalid branches. Kill
107   // original reference.
108   void GenCheckCode(uint32_t check_id, RefAnalysis* ref,
109                     std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
110 
111   // Initialize state for instrumenting bindless checking
112   void InitializeInstBindlessCheck();
113 
114   // Apply GenDescIdxCheckCode to every instruction in module. Then apply
115   // GenDescInitCheckCode to every instruction in module.
116   Pass::Status ProcessImpl();
117 
118   // Mapping from variable to descriptor set
119   std::unordered_map<uint32_t, uint32_t> var2desc_set_;
120 
121   // Mapping from variable to binding
122   std::unordered_map<uint32_t, uint32_t> var2binding_;
123 
124   uint32_t check_desc_func_id_{0};
125 };
126 
127 }  // namespace opt
128 }  // namespace spvtools
129 
130 #endif  // LIBSPIRV_OPT_INST_BINDLESS_CHECK_PASS_H_
131