• 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 INCLUDE_SPIRV_TOOLS_INSTRUMENT_HPP_
18 #define INCLUDE_SPIRV_TOOLS_INSTRUMENT_HPP_
19 
20 // Shader Instrumentation Interface
21 //
22 // This file provides an external interface for applications that wish to
23 // communicate with shaders instrumented by passes created by:
24 //
25 //   CreateInstBindlessCheckPass
26 //   CreateInstBuffAddrCheckPass
27 //   CreateInstDebugPrintfPass
28 //
29 // More detailed documentation of these routines can be found in optimizer.hpp
30 
31 namespace spvtools {
32 
33 // Stream Output Buffer Offsets
34 //
35 // The following values provide offsets into the output buffer struct
36 // generated by InstrumentPass::GenDebugStreamWrite. This method is utilized
37 // by InstBindlessCheckPass, InstBuffAddrCheckPass, and InstDebugPrintfPass.
38 //
39 // The first member of the debug output buffer contains the next available word
40 // in the data stream to be written. Shaders will atomically read and update
41 // this value so as not to overwrite each others records. This value must be
42 // initialized to zero
43 static const int kDebugOutputSizeOffset = 0;
44 
45 // The second member of the output buffer is the start of the stream of records
46 // written by the instrumented shaders. Each record represents a validation
47 // error. The format of the records is documented below.
48 static const int kDebugOutputDataOffset = 1;
49 
50 // Common Stream Record Offsets
51 //
52 // The following are offsets to fields which are common to all records written
53 // to the output stream.
54 //
55 // Each record first contains the size of the record in 32-bit words, including
56 // the size word.
57 static const int kInstCommonOutSize = 0;
58 
59 // This is the shader id passed by the layer when the instrumentation pass is
60 // created.
61 static const int kInstCommonOutShaderId = 1;
62 
63 // This is the ordinal position of the instruction within the SPIR-V shader
64 // which generated the validation error.
65 static const int kInstCommonOutInstructionIdx = 2;
66 
67 // This is the stage which generated the validation error. This word is used
68 // to determine the contents of the next two words in the record.
69 // 0:Vert, 1:TessCtrl, 2:TessEval, 3:Geom, 4:Frag, 5:Compute
70 static const int kInstCommonOutStageIdx = 3;
71 static const int kInstCommonOutCnt = 4;
72 
73 // Stage-specific Stream Record Offsets
74 //
75 // Each stage will contain different values in the next set of words of the
76 // record used to identify which instantiation of the shader generated the
77 // validation error.
78 //
79 // Vertex Shader Output Record Offsets
80 static const int kInstVertOutVertexIndex = kInstCommonOutCnt;
81 static const int kInstVertOutInstanceIndex = kInstCommonOutCnt + 1;
82 static const int kInstVertOutUnused = kInstCommonOutCnt + 2;
83 
84 // Frag Shader Output Record Offsets
85 static const int kInstFragOutFragCoordX = kInstCommonOutCnt;
86 static const int kInstFragOutFragCoordY = kInstCommonOutCnt + 1;
87 static const int kInstFragOutUnused = kInstCommonOutCnt + 2;
88 
89 // Compute Shader Output Record Offsets
90 static const int kInstCompOutGlobalInvocationIdX = kInstCommonOutCnt;
91 static const int kInstCompOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
92 static const int kInstCompOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
93 
94 // Tessellation Control Shader Output Record Offsets
95 static const int kInstTessCtlOutInvocationId = kInstCommonOutCnt;
96 static const int kInstTessCtlOutPrimitiveId = kInstCommonOutCnt + 1;
97 static const int kInstTessCtlOutUnused = kInstCommonOutCnt + 2;
98 
99 // Tessellation Eval Shader Output Record Offsets
100 static const int kInstTessEvalOutPrimitiveId = kInstCommonOutCnt;
101 static const int kInstTessEvalOutTessCoordU = kInstCommonOutCnt + 1;
102 static const int kInstTessEvalOutTessCoordV = kInstCommonOutCnt + 2;
103 
104 // Geometry Shader Output Record Offsets
105 static const int kInstGeomOutPrimitiveId = kInstCommonOutCnt;
106 static const int kInstGeomOutInvocationId = kInstCommonOutCnt + 1;
107 static const int kInstGeomOutUnused = kInstCommonOutCnt + 2;
108 
109 // Ray Tracing Shader Output Record Offsets
110 static const int kInstRayTracingOutLaunchIdX = kInstCommonOutCnt;
111 static const int kInstRayTracingOutLaunchIdY = kInstCommonOutCnt + 1;
112 static const int kInstRayTracingOutLaunchIdZ = kInstCommonOutCnt + 2;
113 
114 // Mesh Shader Output Record Offsets
115 static const int kInstMeshOutGlobalInvocationIdX = kInstCommonOutCnt;
116 static const int kInstMeshOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
117 static const int kInstMeshOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
118 
119 // Task Shader Output Record Offsets
120 static const int kInstTaskOutGlobalInvocationIdX = kInstCommonOutCnt;
121 static const int kInstTaskOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
122 static const int kInstTaskOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
123 
124 // Size of Common and Stage-specific Members
125 static const int kInstStageOutCnt = kInstCommonOutCnt + 3;
126 
127 // Validation Error Code Offset
128 //
129 // This identifies the validation error. It also helps to identify
130 // how many words follow in the record and their meaning.
131 static const int kInstValidationOutError = kInstStageOutCnt;
132 
133 // Validation-specific Output Record Offsets
134 //
135 // Each different validation will generate a potentially different
136 // number of words at the end of the record giving more specifics
137 // about the validation error.
138 //
139 // A bindless bounds error will output the index and the bound.
140 static const int kInstBindlessBoundsOutDescIndex = kInstStageOutCnt + 1;
141 static const int kInstBindlessBoundsOutDescBound = kInstStageOutCnt + 2;
142 static const int kInstBindlessBoundsOutUnused = kInstStageOutCnt + 3;
143 static const int kInstBindlessBoundsOutCnt = kInstStageOutCnt + 4;
144 
145 // A descriptor uninitialized error will output the index.
146 static const int kInstBindlessUninitOutDescIndex = kInstStageOutCnt + 1;
147 static const int kInstBindlessUninitOutUnused = kInstStageOutCnt + 2;
148 static const int kInstBindlessUninitOutUnused2 = kInstStageOutCnt + 3;
149 static const int kInstBindlessUninitOutCnt = kInstStageOutCnt + 4;
150 
151 // A buffer out-of-bounds error will output the descriptor
152 // index, the buffer offset and the buffer size
153 static const int kInstBindlessBuffOOBOutDescIndex = kInstStageOutCnt + 1;
154 static const int kInstBindlessBuffOOBOutBuffOff = kInstStageOutCnt + 2;
155 static const int kInstBindlessBuffOOBOutBuffSize = kInstStageOutCnt + 3;
156 static const int kInstBindlessBuffOOBOutCnt = kInstStageOutCnt + 4;
157 
158 // A buffer address unalloc error will output the 64-bit pointer in
159 // two 32-bit pieces, lower bits first.
160 static const int kInstBuffAddrUnallocOutDescPtrLo = kInstStageOutCnt + 1;
161 static const int kInstBuffAddrUnallocOutDescPtrHi = kInstStageOutCnt + 2;
162 static const int kInstBuffAddrUnallocOutCnt = kInstStageOutCnt + 3;
163 
164 // Maximum Output Record Member Count
165 static const int kInstMaxOutCnt = kInstStageOutCnt + 4;
166 
167 // Validation Error Codes
168 //
169 // These are the possible validation error codes.
170 static const int kInstErrorBindlessBounds = 0;
171 static const int kInstErrorBindlessUninit = 1;
172 static const int kInstErrorBuffAddrUnallocRef = 2;
173 static const int kInstErrorBindlessBuffOOB = 3;
174 static const int kInstErrorBuffOOBUniform = 4;
175 static const int kInstErrorBuffOOBStorage = 5;
176 static const int kInstErrorBuffOOBUniformTexel = 6;
177 static const int kInstErrorBuffOOBStorageTexel = 7;
178 
179 // Direct Input Buffer Offsets
180 //
181 // The following values provide member offsets into the input buffers
182 // consumed by InstrumentPass::GenDebugDirectRead(). This method is utilized
183 // by InstBindlessCheckPass.
184 //
185 // The only object in an input buffer is a runtime array of unsigned
186 // integers. Each validation will have its own formatting of this array.
187 static const int kDebugInputDataOffset = 0;
188 
189 // Debug Buffer Bindings
190 //
191 // These are the bindings for the different buffers which are
192 // read or written by the instrumentation passes.
193 //
194 // This is the output buffer written by InstBindlessCheckPass,
195 // InstBuffAddrCheckPass, and possibly other future validations.
196 static const int kDebugOutputBindingStream = 0;
197 
198 // The binding for the input buffer read by InstBindlessCheckPass.
199 static const int kDebugInputBindingBindless = 1;
200 
201 // The binding for the input buffer read by InstBuffAddrCheckPass.
202 static const int kDebugInputBindingBuffAddr = 2;
203 
204 // This is the output buffer written by InstDebugPrintfPass.
205 static const int kDebugOutputPrintfStream = 3;
206 
207 // Bindless Validation Input Buffer Format
208 //
209 // An input buffer for bindless validation consists of a single array of
210 // unsigned integers we will call Data[]. This array is formatted as follows.
211 //
212 // At offset kDebugInputBindlessInitOffset in Data[] is a single uint which
213 // gives an offset to the start of the bindless initialization data. More
214 // specifically, if the following value is zero, we know that the descriptor at
215 // (set = s, binding = b, index = i) is not initialized; if the value is
216 // non-zero, and the descriptor points to a buffer, the value is the length of
217 // the buffer in bytes and can be used to check for out-of-bounds buffer
218 // references:
219 // Data[ i + Data[ b + Data[ s + Data[ kDebugInputBindlessInitOffset ] ] ] ]
220 static const int kDebugInputBindlessInitOffset = 0;
221 
222 // At offset kDebugInputBindlessOffsetLengths is some number of uints which
223 // provide the bindless length data. More specifically, the number of
224 // descriptors at (set=s, binding=b) is:
225 // Data[ Data[ s + kDebugInputBindlessOffsetLengths ] + b ]
226 static const int kDebugInputBindlessOffsetLengths = 1;
227 
228 // Buffer Device Address Input Buffer Format
229 //
230 // An input buffer for buffer device address validation consists of a single
231 // array of unsigned 64-bit integers we will call Data[]. This array is
232 // formatted as follows:
233 //
234 // At offset kDebugInputBuffAddrPtrOffset is a list of sorted valid buffer
235 // addresses. The list is terminated with the address 0xffffffffffffffff.
236 // If 0x0 is not a valid buffer address, this address is inserted at the
237 // start of the list.
238 //
239 static const int kDebugInputBuffAddrPtrOffset = 1;
240 //
241 // At offset kDebugInputBuffAddrLengthOffset in Data[] is a single uint64 which
242 // gives an offset to the start of the buffer length data. More
243 // specifically, for a buffer whose pointer is located at input buffer offset
244 // i, the length is located at:
245 //
246 // Data[ i - kDebugInputBuffAddrPtrOffset
247 //         + Data[ kDebugInputBuffAddrLengthOffset ] ]
248 //
249 // The length associated with the 0xffffffffffffffff address is zero. If
250 // not a valid buffer, the length associated with the 0x0 address is zero.
251 static const int kDebugInputBuffAddrLengthOffset = 0;
252 
253 }  // namespace spvtools
254 
255 #endif  // INCLUDE_SPIRV_TOOLS_INSTRUMENT_HPP_
256