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