1*b7893ccfSSadaf Ebrahimi<!-- markdownlint-disable MD041 --> 2*b7893ccfSSadaf Ebrahimi<!-- Copyright 2015-2019 LunarG, Inc. --> 3*b7893ccfSSadaf Ebrahimi[![Khronos Vulkan][1]][2] 4*b7893ccfSSadaf Ebrahimi 5*b7893ccfSSadaf Ebrahimi[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/" 6*b7893ccfSSadaf Ebrahimi[2]: https://www.khronos.org/vulkan/ 7*b7893ccfSSadaf Ebrahimi 8*b7893ccfSSadaf Ebrahimi# GPU-Assisted Validation 9*b7893ccfSSadaf Ebrahimi 10*b7893ccfSSadaf Ebrahimi[![Creative Commons][3]][4] 11*b7893ccfSSadaf Ebrahimi 12*b7893ccfSSadaf Ebrahimi[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License" 13*b7893ccfSSadaf Ebrahimi[4]: https://creativecommons.org/licenses/by-nd/4.0/ 14*b7893ccfSSadaf Ebrahimi 15*b7893ccfSSadaf EbrahimiGPU-Assisted validation is implemented in the SPIR-V Tools optimizer and the `VK_LAYER_KHRONOS_validation layer (or, in the 16*b7893ccfSSadaf Ebrahimisoon-to-be-deprecated `VK_LAYER_LUNARG_core_validation` layer). This document covers the design of the layer portion of the 17*b7893ccfSSadaf Ebrahimiimplementation. 18*b7893ccfSSadaf Ebrahimi 19*b7893ccfSSadaf Ebrahimi## Basic Operation 20*b7893ccfSSadaf Ebrahimi 21*b7893ccfSSadaf EbrahimiThe basic operation of GPU-Assisted validation is comprised of instrumenting shader code to perform run-time checking in shaders and 22*b7893ccfSSadaf Ebrahimireporting any error conditions to the layer. 23*b7893ccfSSadaf EbrahimiThe layer then reports the errors to the user via the same reporting mechanisms used by the rest of the validation system. 24*b7893ccfSSadaf Ebrahimi 25*b7893ccfSSadaf EbrahimiThe layer instruments the shaders by passing the shader's SPIR-V bytecode to the SPIR-V optimizer component and 26*b7893ccfSSadaf Ebrahimiinstructs the optimizer to perform an instrumentation pass to add the additional instructions to perform the run-time checking. 27*b7893ccfSSadaf EbrahimiThe layer then passes the resulting modified SPIR-V bytecode to the driver as part of the process of creating a ShaderModule. 28*b7893ccfSSadaf Ebrahimi 29*b7893ccfSSadaf EbrahimiThe layer also allocates a buffer that describes the length of all descriptor arrays and the write state of each element of each array. 30*b7893ccfSSadaf EbrahimiIt only does this if the VK_EXT_descriptor_indexing extension is enabled. 31*b7893ccfSSadaf Ebrahimi 32*b7893ccfSSadaf EbrahimiAs the shader is executed, the instrumented shader code performs the run-time checks. 33*b7893ccfSSadaf EbrahimiIf a check detects an error condition, the instrumentation code writes an error record into the GPU's device memory. 34*b7893ccfSSadaf EbrahimiThis record is small and is on the order of a dozen 32-bit words. 35*b7893ccfSSadaf EbrahimiSince multiple shader stages and multiple invocations of a shader can all detect errors, the instrumentation code 36*b7893ccfSSadaf Ebrahimiwrites error records into consecutive memory locations as long as there is space available in the pre-allocated block of device memory. 37*b7893ccfSSadaf Ebrahimi 38*b7893ccfSSadaf EbrahimiThe layer inspects this device memory block after completion of a queue submission. 39*b7893ccfSSadaf EbrahimiIf the GPU had written an error record to this memory block, 40*b7893ccfSSadaf Ebrahimithe layer analyzes this error record and constructs a validation error message 41*b7893ccfSSadaf Ebrahimiwhich is then reported in the same manner as other validation messages. 42*b7893ccfSSadaf EbrahimiIf the shader was compiled with debug information (source code and SPIR-V instruction mapping to source code lines), the layer 43*b7893ccfSSadaf Ebrahimialso provides the line of shader source code that provoked the error as part of the validation error message. 44*b7893ccfSSadaf Ebrahimi 45*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Checks 46*b7893ccfSSadaf Ebrahimi 47*b7893ccfSSadaf EbrahimiThe initial release (Jan 2019) of GPU-Assisted Validation includes checking for out-of-bounds descriptor array indexing 48*b7893ccfSSadaf Ebrahimifor image/texel descriptor types. 49*b7893ccfSSadaf Ebrahimi 50*b7893ccfSSadaf EbrahimiThe second release (Apr 2019) adds validation for out-of-bounds descriptor array indexing and use of unwritten descriptors when the 51*b7893ccfSSadaf EbrahimiVK_EXT_descriptor_indexing extension is enabled. Also added (June 2019) was validation for buffer descriptors. 52*b7893ccfSSadaf Ebrahimi 53*b7893ccfSSadaf Ebrahimi### Out-of-Bounds(OOB) Descriptor Array Indexing 54*b7893ccfSSadaf Ebrahimi 55*b7893ccfSSadaf EbrahimiChecking for correct indexing of descriptor arrays is sometimes referred to as "bind-less validation". 56*b7893ccfSSadaf EbrahimiIt is called "bind-less" because a binding in a descriptor set may contain an array of like descriptors. 57*b7893ccfSSadaf EbrahimiAnd unless there is a constant or compile-time indication of which descriptor in the array is selected, 58*b7893ccfSSadaf Ebrahimithe descriptor binding status is considered to be ambiguous, leaving the actual binding to be determined at run-time. 59*b7893ccfSSadaf Ebrahimi 60*b7893ccfSSadaf EbrahimiAs an example, a fragment shader program may use a variable to index an array of combined image samplers. 61*b7893ccfSSadaf EbrahimiSuch a line might look like: 62*b7893ccfSSadaf Ebrahimi 63*b7893ccfSSadaf Ebrahimi```glsl 64*b7893ccfSSadaf EbrahimiuFragColor = light * texture(tex[tex_ind], texcoord.xy); 65*b7893ccfSSadaf Ebrahimi``` 66*b7893ccfSSadaf Ebrahimi 67*b7893ccfSSadaf EbrahimiThe array of combined image samplers is `tex` and has 6 samplers in the array. 68*b7893ccfSSadaf EbrahimiThe complete validation error message issued when `tex_ind` indexes past the array is: 69*b7893ccfSSadaf Ebrahimi 70*b7893ccfSSadaf Ebrahimi```terminal 71*b7893ccfSSadaf EbrahimiERROR : VALIDATION - Message Id Number: 0 | Message Id Name: UNASSIGNED-Image descriptor index out of bounds 72*b7893ccfSSadaf Ebrahimi Index of 6 used to index descriptor array of length 6. Command buffer (CubeDrawCommandBuf)(0xbc24b0). 73*b7893ccfSSadaf Ebrahimi Pipeline (0x45). Shader Module (0x43). Shader Instruction Index = 108. Stage = Fragment. 74*b7893ccfSSadaf Ebrahimi Fragment coord (x,y) = (419.5, 254.5). Shader validation error occurred in file: 75*b7893ccfSSadaf Ebrahimi /home/user/src/Vulkan-ValidationLayers/external/Vulkan-Tools/cube/cube.frag at line 45. 76*b7893ccfSSadaf Ebrahimi45: uFragColor = light * texture(tex[tex_ind], texcoord.xy); 77*b7893ccfSSadaf Ebrahimi``` 78*b7893ccfSSadaf EbrahimiThe VK_EXT_descriptor_indexing extension allows a shader to declare a descriptor array without specifying its size 79*b7893ccfSSadaf Ebrahimi```glsl 80*b7893ccfSSadaf Ebrahimilayout(set = 0, binding = 1) uniform sampler2D tex[]; 81*b7893ccfSSadaf Ebrahimi``` 82*b7893ccfSSadaf EbrahimiIn this case, the layer needs to tell the optimization code how big the descriptor array is so the code can determine what is out of 83*b7893ccfSSadaf Ebrahimibounds and what is not. 84*b7893ccfSSadaf Ebrahimi 85*b7893ccfSSadaf EbrahimiThe extension also allows descriptor set bindings to be partially bound, meaning that as long as the shader doesn't use certain 86*b7893ccfSSadaf Ebrahimiarray elements, those elements are not required to have been written. 87*b7893ccfSSadaf EbrahimiThe instrumentation code needs to know which elements of a descriptor array have been written, so that it can tell if one is used 88*b7893ccfSSadaf Ebrahimithat has not been written. 89*b7893ccfSSadaf Ebrahimi 90*b7893ccfSSadaf EbrahimiNote that currently, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT validation is not working and all accesses are reported as valid. 91*b7893ccfSSadaf Ebrahimi 92*b7893ccfSSadaf Ebrahimi 93*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Options 94*b7893ccfSSadaf Ebrahimi 95*b7893ccfSSadaf EbrahimiHere are the options related to activating GPU-Assisted Validation: 96*b7893ccfSSadaf Ebrahimi 97*b7893ccfSSadaf Ebrahimi1. Enable GPU-Assisted Validation - GPU-Assisted Validation is off by default and must be enabled. 98*b7893ccfSSadaf Ebrahimi 99*b7893ccfSSadaf Ebrahimi GPU-Assisted Validation is disabled by default because the shader instrumentation may introduce significant 100*b7893ccfSSadaf Ebrahimi shader performance degradation and additional resource consumption. 101*b7893ccfSSadaf Ebrahimi GPU-Assisted Validation requires additional resources such as device memory and descriptors. 102*b7893ccfSSadaf Ebrahimi It is desirable for the user to opt-in to this feature because of these requirements. 103*b7893ccfSSadaf Ebrahimi In addition, there are several limitations that may adversely affect application behavior, 104*b7893ccfSSadaf Ebrahimi as described later in this document. 105*b7893ccfSSadaf Ebrahimi 106*b7893ccfSSadaf Ebrahimi2. Reserve a Descriptor Set Binding Slot - Modifies the value of the `VkPhysicalDeviceLimits::maxBoundDescriptorSets` 107*b7893ccfSSadaf Ebrahimi property to return a value one less than the actual device's value to "reserve" a descriptor set binding slot for use by GPU validation. 108*b7893ccfSSadaf Ebrahimi 109*b7893ccfSSadaf Ebrahimi This option is likely only of interest to applications that dynamically adjust their descriptor set bindings to adjust for 110*b7893ccfSSadaf Ebrahimi the limits of the device. 111*b7893ccfSSadaf Ebrahimi 112*b7893ccfSSadaf Ebrahimi### Enabling and Specifying Options with a Configuration File 113*b7893ccfSSadaf Ebrahimi 114*b7893ccfSSadaf EbrahimiThe existing layer configuration file mechanism can be used to enable GPU-Assisted Validation. 115*b7893ccfSSadaf EbrahimiThis mechanism is described on the 116*b7893ccfSSadaf Ebrahimi[LunarXchange website](https://vulkan.lunarg.com/doc/sdk/latest/windows/layer_configuration.html), 117*b7893ccfSSadaf Ebrahimiin the "Layers Overview and Configuration" document. 118*b7893ccfSSadaf Ebrahimi 119*b7893ccfSSadaf EbrahimiTo turn on GPU validation, add the following to your layer settings file, which is often 120*b7893ccfSSadaf Ebrahiminamed `vk_layer_settings.txt`. 121*b7893ccfSSadaf Ebrahimi 122*b7893ccfSSadaf Ebrahimi```code 123*b7893ccfSSadaf Ebrahimikhronos_validation.gpu_validation = all 124*b7893ccfSSadaf Ebrahimi``` 125*b7893ccfSSadaf Ebrahimi 126*b7893ccfSSadaf EbrahimiTo turn on GPU validation and request to reserve a binding slot: 127*b7893ccfSSadaf Ebrahimi 128*b7893ccfSSadaf Ebrahimi```code 129*b7893ccfSSadaf Ebrahimikhronos_validation.gpu_validation = all,reserve_binding_slot 130*b7893ccfSSadaf Ebrahimi``` 131*b7893ccfSSadaf Ebrahimi 132*b7893ccfSSadaf EbrahimiNote: When using the core_validation layer, the above settings should use `lunarg_core_validation` in place of 133*b7893ccfSSadaf Ebrahimi`khronos_validation`. 134*b7893ccfSSadaf Ebrahimi 135*b7893ccfSSadaf EbrahimiSome platforms do not support configuration of the validation layers with this configuration file. 136*b7893ccfSSadaf EbrahimiPrograms running on these platforms must then use the programmatic interface. 137*b7893ccfSSadaf Ebrahimi 138*b7893ccfSSadaf Ebrahimi### Enabling and Specifying Options with the Programmatic Interface 139*b7893ccfSSadaf Ebrahimi 140*b7893ccfSSadaf EbrahimiThe `VK_EXT_validation_features` extension can be used to enable GPU-Assisted Validation at CreateInstance time. 141*b7893ccfSSadaf Ebrahimi 142*b7893ccfSSadaf EbrahimiHere is sample code illustrating how to enable it: 143*b7893ccfSSadaf Ebrahimi 144*b7893ccfSSadaf Ebrahimi```C 145*b7893ccfSSadaf EbrahimiVkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT}; 146*b7893ccfSSadaf EbrahimiVkValidationFeaturesEXT features = {}; 147*b7893ccfSSadaf Ebrahimifeatures.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; 148*b7893ccfSSadaf Ebrahimifeatures.enabledValidationFeatureCount = 1; 149*b7893ccfSSadaf Ebrahimifeatures.pEnabledValidationFeatures = enables; 150*b7893ccfSSadaf Ebrahimi 151*b7893ccfSSadaf EbrahimiVkInstanceCreateInfo info = {}; 152*b7893ccfSSadaf Ebrahimiinfo.pNext = &features; 153*b7893ccfSSadaf Ebrahimi``` 154*b7893ccfSSadaf Ebrahimi 155*b7893ccfSSadaf EbrahimiUse the `VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT` enum to reserve a binding slot. 156*b7893ccfSSadaf Ebrahimi 157*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Limitations 158*b7893ccfSSadaf Ebrahimi 159*b7893ccfSSadaf EbrahimiThere are several limitations that may impede the operation of GPU-Assisted Validation: 160*b7893ccfSSadaf Ebrahimi 161*b7893ccfSSadaf Ebrahimi### Vulkan 1.1 162*b7893ccfSSadaf Ebrahimi 163*b7893ccfSSadaf EbrahimiVulkan 1.1 or later is required because the GPU instrumentation code uses SPIR-V 1.3 features. 164*b7893ccfSSadaf EbrahimiVulkan 1,1 is required to ensure that SPIR-V 1.3 is available. 165*b7893ccfSSadaf Ebrahimi 166*b7893ccfSSadaf Ebrahimi### Descriptor Types 167*b7893ccfSSadaf Ebrahimi 168*b7893ccfSSadaf EbrahimiThe current implementation works with image, texel, and buffer descriptor types. 169*b7893ccfSSadaf EbrahimiA complete list appears later in this document. 170*b7893ccfSSadaf Ebrahimi 171*b7893ccfSSadaf Ebrahimi### Descriptor Set Binding Limit 172*b7893ccfSSadaf Ebrahimi 173*b7893ccfSSadaf EbrahimiThis is probably the most important limitation and is related to the 174*b7893ccfSSadaf Ebrahimi`VkPhysicalDeviceLimits::maxBoundDescriptorSets` device limit. 175*b7893ccfSSadaf Ebrahimi 176*b7893ccfSSadaf EbrahimiWhen applications use all the available descriptor set binding slots, 177*b7893ccfSSadaf EbrahimiGPU-Assisted Validation cannot be performed because it needs a descriptor set to 178*b7893ccfSSadaf Ebrahimilocate the memory for writing the error report record. 179*b7893ccfSSadaf Ebrahimi 180*b7893ccfSSadaf EbrahimiThis problem is most likely to occur on devices, often mobile, that support only the 181*b7893ccfSSadaf Ebrahimiminimum required value for `VkPhysicalDeviceLimits::maxBoundDescriptorSets`, which is 4. 182*b7893ccfSSadaf EbrahimiSome applications may be written to use 4 slots since this is the highest value that 183*b7893ccfSSadaf Ebrahimiis guaranteed by the specification. 184*b7893ccfSSadaf EbrahimiWhen such an application using 4 slots runs on a device with only 4 slots, 185*b7893ccfSSadaf Ebrahimithen GPU-Assisted Validation cannot be performed. 186*b7893ccfSSadaf Ebrahimi 187*b7893ccfSSadaf EbrahimiIn this implementation, this condition is detected and gracefully recovered from by 188*b7893ccfSSadaf Ebrahimibuilding the graphics pipeline with non-instrumented shaders instead of instrumented ones. 189*b7893ccfSSadaf EbrahimiAn error message is also displayed informing the user of the condition. 190*b7893ccfSSadaf Ebrahimi 191*b7893ccfSSadaf EbrahimiApplications don't have many options in this situation and it is anticipated that 192*b7893ccfSSadaf Ebrahimichanging the application to free a slot is difficult. 193*b7893ccfSSadaf Ebrahimi 194*b7893ccfSSadaf Ebrahimi### Device Memory 195*b7893ccfSSadaf Ebrahimi 196*b7893ccfSSadaf EbrahimiGPU-Assisted Validation does allocate device memory for the error report buffers, and if 197*b7893ccfSSadaf Ebrahimidescriptor indexing is enabled, for the input buffer of descriptor sizes and write state. 198*b7893ccfSSadaf EbrahimiThis can lead to a greater chance of memory exhaustion, especially in cases where 199*b7893ccfSSadaf Ebrahimithe application is trying to use all of the available memory. 200*b7893ccfSSadaf EbrahimiThe extra memory allocations are also not visible to the application, making it 201*b7893ccfSSadaf Ebrahimiimpossible for the application to account for them. 202*b7893ccfSSadaf Ebrahimi 203*b7893ccfSSadaf EbrahimiNote that if descriptor indexing is enabled, the input buffer size will be equal to 204*b7893ccfSSadaf Ebrahimi(1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count) words of memory where 205*b7893ccfSSadaf Ebrahimibinding_count is the binding number of the largest binding in the set. 206*b7893ccfSSadaf EbrahimiThis means that sparsely populated sets and sets with a very large binding will cause 207*b7893ccfSSadaf Ebrahimithe input buffer to be much larger than it could be with more densely packed binding numbers. 208*b7893ccfSSadaf EbrahimiAs a best practice, when using GPU-Assisted Validation with descriptor indexing enabled, 209*b7893ccfSSadaf Ebrahimimake sure descriptor bindings are densely packed. 210*b7893ccfSSadaf Ebrahimi 211*b7893ccfSSadaf EbrahimiIf GPU-Assisted Validation device memory allocations fail, the device could become 212*b7893ccfSSadaf Ebrahimiunstable because some previously-built pipelines may contain instrumented shaders. 213*b7893ccfSSadaf EbrahimiThis is a condition that is nearly impossible to recover from, so the layer just 214*b7893ccfSSadaf Ebrahimiprints an error message and refrains from any further allocations or instrumentations. 215*b7893ccfSSadaf EbrahimiThere is a reasonable chance to recover from these conditions, 216*b7893ccfSSadaf Ebrahimiespecially if the instrumentation does not write any error records. 217*b7893ccfSSadaf Ebrahimi 218*b7893ccfSSadaf Ebrahimi### Descriptors 219*b7893ccfSSadaf Ebrahimi 220*b7893ccfSSadaf EbrahimiThis is roughly the same problem as the device memory problem mentioned above, 221*b7893ccfSSadaf Ebrahimibut for descriptors. 222*b7893ccfSSadaf EbrahimiAny failure to allocate a descriptor set means that the instrumented shader code 223*b7893ccfSSadaf Ebrahimiwon't have a place to write error records, resulting in unpredictable device 224*b7893ccfSSadaf Ebrahimibehavior. 225*b7893ccfSSadaf Ebrahimi 226*b7893ccfSSadaf Ebrahimi### Other Device Limits 227*b7893ccfSSadaf Ebrahimi 228*b7893ccfSSadaf EbrahimiThis implementation uses additional resources that may count against the following limits, 229*b7893ccfSSadaf Ebrahimiand possibly others: 230*b7893ccfSSadaf Ebrahimi 231*b7893ccfSSadaf Ebrahimi* `maxMemoryAllocationCount` 232*b7893ccfSSadaf Ebrahimi* `maxBoundDescriptorSets` 233*b7893ccfSSadaf Ebrahimi* `maxPerStageDescriptorStorageBuffers` 234*b7893ccfSSadaf Ebrahimi* `maxPerStageResources` 235*b7893ccfSSadaf Ebrahimi* `maxDescriptorSetStorageBuffers` 236*b7893ccfSSadaf Ebrahimi* `maxFragmentCombinedOutputResources` 237*b7893ccfSSadaf Ebrahimi 238*b7893ccfSSadaf EbrahimiThe implementation does not take steps to avoid exceeding these limits 239*b7893ccfSSadaf Ebrahimiand does not update the tracking performed by other validation functions. 240*b7893ccfSSadaf Ebrahimi 241*b7893ccfSSadaf Ebrahimi### A Note About the `VK_EXT_buffer_device_address` Extension 242*b7893ccfSSadaf Ebrahimi 243*b7893ccfSSadaf EbrahimiThe recently introduced `VK_EXT_buffer_device_address` extension can be used 244*b7893ccfSSadaf Ebrahimito implement GPU-Assisted Validation without some of the limitations described above. 245*b7893ccfSSadaf EbrahimiThis approach would use this extension to obtain a GPU device pointer to a storage 246*b7893ccfSSadaf Ebrahimibuffer and make it available to the shader via a specialization constant. 247*b7893ccfSSadaf EbrahimiThis technique removes the need to create descriptors, use a descriptor set slot, 248*b7893ccfSSadaf Ebrahimimodify pipeline layouts, etc, and would relax some of the limitations listed above. 249*b7893ccfSSadaf Ebrahimi 250*b7893ccfSSadaf EbrahimiThis alternate implementation is under consideration. 251*b7893ccfSSadaf Ebrahimi 252*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Internal Design 253*b7893ccfSSadaf Ebrahimi 254*b7893ccfSSadaf EbrahimiThis section may be of interest to readers who are interested on how GPU-Assisted Validation is implemented. 255*b7893ccfSSadaf EbrahimiIt isn't necessarily required for using the feature. 256*b7893ccfSSadaf Ebrahimi 257*b7893ccfSSadaf Ebrahimi### General 258*b7893ccfSSadaf Ebrahimi 259*b7893ccfSSadaf EbrahimiIn general, the implementation does: 260*b7893ccfSSadaf Ebrahimi 261*b7893ccfSSadaf Ebrahimi* For each draw, dispatch, and trace rays call, allocate a buffer with enough device memory to hold a single debug output record written by the 262*b7893ccfSSadaf Ebrahimi instrumented shader code. 263*b7893ccfSSadaf Ebrahimi If descriptor indexing is enabled, calculate the amount of memory needed to describe the descriptor arrays sizes and 264*b7893ccfSSadaf Ebrahimi write states and allocate device memory and a buffer for input to the instrumented shader. 265*b7893ccfSSadaf Ebrahimi The Vulkan Memory Allocator is used to handle this efficiently. 266*b7893ccfSSadaf Ebrahimi 267*b7893ccfSSadaf Ebrahimi There is probably little advantage in providing a larger output buffer in order to obtain more debug records. 268*b7893ccfSSadaf Ebrahimi It is likely, especially for fragment shaders, that multiple errors occurring near each other have the same root cause. 269*b7893ccfSSadaf Ebrahimi 270*b7893ccfSSadaf Ebrahimi A block is allocated on a per draw basis to make it possible to associate a shader debug error record with 271*b7893ccfSSadaf Ebrahimi a draw within a command buffer. 272*b7893ccfSSadaf Ebrahimi This is done partly to give the user more information in the error report, namely the command buffer handle/name and the draw within that command buffer. 273*b7893ccfSSadaf Ebrahimi An alternative design allocates this block on a per-device or per-queue basis and should work. 274*b7893ccfSSadaf Ebrahimi However, it is not possible to identify the command buffer that causes the error if multiple command buffers 275*b7893ccfSSadaf Ebrahimi are submitted at once. 276*b7893ccfSSadaf Ebrahimi* For each draw, dispatch, and trace rays call, allocate a descriptor set and update it to point to the block of device memory just allocated. 277*b7893ccfSSadaf Ebrahimi If descriptor indexing is enabled, also update the descriptor set to point to the allocated input buffer. 278*b7893ccfSSadaf Ebrahimi Fill the input buffer with the size and write state information for each descriptor array. 279*b7893ccfSSadaf Ebrahimi There is a descriptor set manager to handle this efficiently. 280*b7893ccfSSadaf Ebrahimi Also make an additional call down the chain to create a bind descriptor set command to bind our descriptor set at the desired index. 281*b7893ccfSSadaf Ebrahimi This has the effect of binding the device memory block belonging to this draw so that the GPU instrumentation 282*b7893ccfSSadaf Ebrahimi writes into this buffer for when the draw is executed. 283*b7893ccfSSadaf Ebrahimi The end result is that each draw call has its own buffer containing GPU instrumentation error 284*b7893ccfSSadaf Ebrahimi records, if any occurred while executing that draw. 285*b7893ccfSSadaf Ebrahimi* Determine the descriptor set binding index that is eventually used to bind the descriptor set just allocated and updated. 286*b7893ccfSSadaf Ebrahimi Usually, it is `VkPhysicalDeviceLimits::maxBoundDescriptorSets` minus one. 287*b7893ccfSSadaf Ebrahimi For devices that have a very high or no limit on this bound, pick an index that isn't too high, but above most other device 288*b7893ccfSSadaf Ebrahimi maxima such as 32. 289*b7893ccfSSadaf Ebrahimi* When creating a ShaderModule, pass the SPIR-V bytecode to the SPIR-V optimizer to perform the instrumentation pass. 290*b7893ccfSSadaf Ebrahimi Pass the desired descriptor set binding index to the optimizer via a parameter so that the instrumented 291*b7893ccfSSadaf Ebrahimi code knows which descriptor to use for writing error report data to the memory block. 292*b7893ccfSSadaf Ebrahimi If descriptor indexing is enabled, turn on OOB and write state checking in the instrumentation pass. 293*b7893ccfSSadaf Ebrahimi Use the instrumented bytecode to create the ShaderModule. 294*b7893ccfSSadaf Ebrahimi* For all pipeline layouts, add our descriptor set to the layout, at the binding index determined earlier. 295*b7893ccfSSadaf Ebrahimi Fill any gaps with empty descriptor sets. 296*b7893ccfSSadaf Ebrahimi 297*b7893ccfSSadaf Ebrahimi If the incoming layout already has a descriptor set placed at our desired index, the layer must not add its 298*b7893ccfSSadaf Ebrahimi descriptor set to the layout, replacing the one in the incoming layout. 299*b7893ccfSSadaf Ebrahimi Instead, the layer leaves the layout alone and later replaces the instrumented shaders with 300*b7893ccfSSadaf Ebrahimi non-instrumented ones when the pipeline layout is later used to create a graphics pipeline. 301*b7893ccfSSadaf Ebrahimi The layer issues an error message to report this condition. 302*b7893ccfSSadaf Ebrahimi* When creating a GraphicsPipeline, ComputePipeline, or RayTracingPipeline, check to see if the pipeline is using the debug binding index. 303*b7893ccfSSadaf Ebrahimi If it is, replace the instrumented shaders in the pipeline with non-instrumented ones. 304*b7893ccfSSadaf Ebrahimi* Before calling QueueSubmit, if descriptor indexing is enabled, check to see if there were any unwritten descriptors that were declared 305*b7893ccfSSadaf Ebrahimi update-after-bind. 306*b7893ccfSSadaf Ebrahimi If there were, update the write state of those elements. 307*b7893ccfSSadaf Ebrahimi* After calling QueueSubmit, perform a wait on the queue to allow the queue to finish executing. 308*b7893ccfSSadaf Ebrahimi Then map and examine the device memory block for each draw or trace ray command that was submitted. 309*b7893ccfSSadaf Ebrahimi If any debug record is found, generate a validation error message for each record found. 310*b7893ccfSSadaf Ebrahimi 311*b7893ccfSSadaf EbrahimiThe above describes only the high-level details of GPU-Assisted Validation operation. 312*b7893ccfSSadaf EbrahimiMore detail is found in the discussion of the individual hooked functions below. 313*b7893ccfSSadaf Ebrahimi 314*b7893ccfSSadaf Ebrahimi### Initialization 315*b7893ccfSSadaf Ebrahimi 316*b7893ccfSSadaf EbrahimiWhen the validation layer loads, it examines the user options from both the layer settings file and the 317*b7893ccfSSadaf Ebrahimi`VK_EXT_validation_features` extension. 318*b7893ccfSSadaf EbrahimiNote that it also processes the subsumed `VK_EXT_validation_flags` extension for simple backwards compatibility. 319*b7893ccfSSadaf EbrahimiFrom these options, the layer sets instance-scope flags in the validation layer tracking data to indicate if 320*b7893ccfSSadaf EbrahimiGPU-Assisted Validation has been requested, along with any other associated options. 321*b7893ccfSSadaf Ebrahimi 322*b7893ccfSSadaf Ebrahimi### "Calling Down the Chain" 323*b7893ccfSSadaf Ebrahimi 324*b7893ccfSSadaf EbrahimiMuch of the GPU-Assisted Validation implementation involves making "application level" Vulkan API 325*b7893ccfSSadaf Ebrahimicalls outside of the application's API usage to create resources and perform its required operations 326*b7893ccfSSadaf Ebrahimiinside of the validation layer. 327*b7893ccfSSadaf EbrahimiThese calls are not routed up through the top of the loader/layer/driver call stack via the loader. 328*b7893ccfSSadaf EbrahimiInstead, they are simply dispatched via the containing layer's dispatch table. 329*b7893ccfSSadaf Ebrahimi 330*b7893ccfSSadaf EbrahimiThese calls therefore don't pass through any validation checks that occur before the gpu validation checks are run. 331*b7893ccfSSadaf EbrahimiThis doesn't present any particular problem, but it does raise some issues: 332*b7893ccfSSadaf Ebrahimi 333*b7893ccfSSadaf Ebrahimi* The additional API calls are not fully validated 334*b7893ccfSSadaf Ebrahimi 335*b7893ccfSSadaf Ebrahimi This implies that this additional code may never be checked for validation errors. 336*b7893ccfSSadaf Ebrahimi To address this, the code can "just" be written carefully so that it is "valid" Vulkan, 337*b7893ccfSSadaf Ebrahimi which is hard to do. 338*b7893ccfSSadaf Ebrahimi 339*b7893ccfSSadaf Ebrahimi Or, this code can be checked by loading a khronos validation layer with 340*b7893ccfSSadaf Ebrahimi GPU validation enabled on top of "normal" standard validation in the 341*b7893ccfSSadaf Ebrahimi layer stack, which effectively validates the API usage of this code. 342*b7893ccfSSadaf Ebrahimi This sort of checking is performed by layer developers to check that the additional 343*b7893ccfSSadaf Ebrahimi Vulkan usage is valid. 344*b7893ccfSSadaf Ebrahimi 345*b7893ccfSSadaf Ebrahimi This validation can be accomplished by: 346*b7893ccfSSadaf Ebrahimi 347*b7893ccfSSadaf Ebrahimi * Building the validation layer with a hack to force GPU-Assisted Validation to be enabled. 348*b7893ccfSSadaf Ebrahimi Can't use the exposed mechanisms because we probably don't want it on twice. 349*b7893ccfSSadaf Ebrahimi * Rename this layer binary to something else like "khronos_validation2" to keep it apart from the 350*b7893ccfSSadaf Ebrahimi "normal" khronos validation. 351*b7893ccfSSadaf Ebrahimi * Create a new JSON file with the new layer name. 352*b7893ccfSSadaf Ebrahimi * Set up the layer stack so that the "khronos_validation2" layer is on top of or before the actual khronos 353*b7893ccfSSadaf Ebrahimi validation layer 354*b7893ccfSSadaf Ebrahimi * Then run tests and check for validation errors pointing to API usage in the "khronos_validation2" layer. 355*b7893ccfSSadaf Ebrahimi 356*b7893ccfSSadaf Ebrahimi This should only need to be done after making any major changes to the implementation. 357*b7893ccfSSadaf Ebrahimi 358*b7893ccfSSadaf Ebrahimi Another approach involves capturing an application trace with `vktrace` and then playing 359*b7893ccfSSadaf Ebrahimi it back with `vkreplay`. 360*b7893ccfSSadaf Ebrahimi 361*b7893ccfSSadaf Ebrahimi* The additional API calls are not state-tracked 362*b7893ccfSSadaf Ebrahimi 363*b7893ccfSSadaf Ebrahimi This means that things like device memory allocations and descriptor allocations are not 364*b7893ccfSSadaf Ebrahimi tracked and do not show up in any of the bookkeeping performed by the validation layers. 365*b7893ccfSSadaf Ebrahimi For example, any device memory allocation performed by GPU-Assisted Validation won't be 366*b7893ccfSSadaf Ebrahimi counted towards the maximum number of allocations allowed by a device. 367*b7893ccfSSadaf Ebrahimi This could lead to an early allocation failure that is not accompanied by a validation error. 368*b7893ccfSSadaf Ebrahimi 369*b7893ccfSSadaf Ebrahimi This shortcoming is left as not addressed in this implementation because it is anticipated that 370*b7893ccfSSadaf Ebrahimi a later implementation of GPU-Assisted Validation using the `VK_EXT_buffer_device_address` 371*b7893ccfSSadaf Ebrahimi extension will have less of a need to allocate these 372*b7893ccfSSadaf Ebrahimi tracked resources and it therefore becomes less of an issue. 373*b7893ccfSSadaf Ebrahimi 374*b7893ccfSSadaf Ebrahimi### Code Structure and Relationship to the Core Validation Layer 375*b7893ccfSSadaf Ebrahimi 376*b7893ccfSSadaf EbrahimiThe GPU-Assisted Validation code is largely contained in one 377*b7893ccfSSadaf Ebrahimi[file](https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/layers/gpu_validation.cpp), with "hooks" in 378*b7893ccfSSadaf Ebrahimithe other validation code that call functions in this file. 379*b7893ccfSSadaf EbrahimiThese hooks in the validation code look something like this: 380*b7893ccfSSadaf Ebrahimi 381*b7893ccfSSadaf Ebrahimi```C 382*b7893ccfSSadaf Ebrahimiif (GetEnables(dev_data)->gpu_validation) { 383*b7893ccfSSadaf Ebrahimi GpuPreCallRecordDestroyPipeline(dev_data, pipeline_state); 384*b7893ccfSSadaf Ebrahimi} 385*b7893ccfSSadaf Ebrahimi``` 386*b7893ccfSSadaf Ebrahimi 387*b7893ccfSSadaf EbrahimiThe GPU-Assisted Validation code is linked into the shared library for the khronos and core validation layers. 388*b7893ccfSSadaf Ebrahimi 389*b7893ccfSSadaf Ebrahimi#### Review of Khronos Validation Code Structure 390*b7893ccfSSadaf Ebrahimi 391*b7893ccfSSadaf EbrahimiEach function for a Vulkan API command intercepted in the khronos validation layer is usually split up 392*b7893ccfSSadaf Ebrahimiinto several decomposed functions in order to organize the implementation. 393*b7893ccfSSadaf EbrahimiThese functions take the form of: 394*b7893ccfSSadaf Ebrahimi 395*b7893ccfSSadaf Ebrahimi* PreCallValidate<foo>: Perform validation steps before calling down the chain 396*b7893ccfSSadaf Ebrahimi* PostCallValidate<foo>: Perform validation steps after calling down the chain 397*b7893ccfSSadaf Ebrahimi* PreCallRecord<foo>: Perform state recording before calling down the chain 398*b7893ccfSSadaf Ebrahimi* PostCallRecord<foo>: Perform state recording after calling down the chain 399*b7893ccfSSadaf Ebrahimi 400*b7893ccfSSadaf EbrahimiThe GPU-Assisted Validation functions follow this pattern not by hooking into the top-level validation API shim, but 401*b7893ccfSSadaf Ebrahimiby hooking one of these decomposed functions. 402*b7893ccfSSadaf Ebrahimi 403*b7893ccfSSadaf EbrahimiThe design of each hooked function follows: 404*b7893ccfSSadaf Ebrahimi 405*b7893ccfSSadaf Ebrahimi#### GpuPreCallRecordCreateDevice 406*b7893ccfSSadaf Ebrahimi 407*b7893ccfSSadaf Ebrahimi* Modify the `VkPhysicalDeviceFeatures` to turn on two additional physical device features: 408*b7893ccfSSadaf Ebrahimi * `fragmentStoresAndAtomics` 409*b7893ccfSSadaf Ebrahimi * `vertexPipelineStoresAndAtomics` 410*b7893ccfSSadaf Ebrahimi 411*b7893ccfSSadaf Ebrahimi#### GpuPostCallRecordCreateDevice 412*b7893ccfSSadaf Ebrahimi 413*b7893ccfSSadaf Ebrahimi* Determine and record (save in device state) the desired descriptor set binding index. 414*b7893ccfSSadaf Ebrahimi* Initialize Vulkan Memory Allocator 415*b7893ccfSSadaf Ebrahimi * Determine error record block size based on the maximum size of the error record and alignment limits of the device. 416*b7893ccfSSadaf Ebrahimi* Initialize descriptor set manager 417*b7893ccfSSadaf Ebrahimi* Make a descriptor set layout to describe our descriptor set 418*b7893ccfSSadaf Ebrahimi* Make a descriptor set layout to describe a "dummy" descriptor set that contains no descriptors 419*b7893ccfSSadaf Ebrahimi * This is used to "pad" pipeline layouts to fill any gaps between the used bind indices and our bind index 420*b7893ccfSSadaf Ebrahimi* Record these objects in the per-device state 421*b7893ccfSSadaf Ebrahimi 422*b7893ccfSSadaf Ebrahimi#### GpuPreCallRecordDestroyDevice 423*b7893ccfSSadaf Ebrahimi 424*b7893ccfSSadaf Ebrahimi* Destroy descriptor set layouts created in CreateDevice 425*b7893ccfSSadaf Ebrahimi* Clean up descriptor set manager 426*b7893ccfSSadaf Ebrahimi* Clean up Vulkan Memory Allocator (VMA) 427*b7893ccfSSadaf Ebrahimi* Clean up device state 428*b7893ccfSSadaf Ebrahimi 429*b7893ccfSSadaf Ebrahimi#### GpuAllocateValidationResources 430*b7893ccfSSadaf Ebrahimi 431*b7893ccfSSadaf Ebrahimi* For each Draw, Dispatch, or TraceRays call: 432*b7893ccfSSadaf Ebrahimi * Get a descriptor set from the descriptor set manager 433*b7893ccfSSadaf Ebrahimi * Get an output buffer and associated memory from VMA 434*b7893ccfSSadaf Ebrahimi * If descriptor indexing is enabled, get an input buffer and fill with descriptor array information 435*b7893ccfSSadaf Ebrahimi * Update (write) the descriptor set with the memory info 436*b7893ccfSSadaf Ebrahimi * Check to see if the layout for the pipeline just bound is using our selected bind index 437*b7893ccfSSadaf Ebrahimi * If no conflict, add an additional command to the command buffer to bind our descriptor set at our selected index 438*b7893ccfSSadaf Ebrahimi* Record the above objects in the per-CB state 439*b7893ccfSSadaf EbrahimiNote that the Draw and Dispatch calls include vkCmdDraw, vkCmdDrawIndexed, vkCmdDrawIndirect, vkCmdDrawIndexedIndirect, vkCmdDispatch, vkCmdDispatchIndirect, and vkCmdTraceRaysNV. 440*b7893ccfSSadaf Ebrahimi 441*b7893ccfSSadaf Ebrahimi#### GpuPreCallRecordFreeCommandBuffers 442*b7893ccfSSadaf Ebrahimi 443*b7893ccfSSadaf Ebrahimi* For each command buffer: 444*b7893ccfSSadaf Ebrahimi * Destroy the VMA buffer(s), releasing the memory 445*b7893ccfSSadaf Ebrahimi * Give the descriptor sets back to the descriptor set manager 446*b7893ccfSSadaf Ebrahimi * Clean up CB state 447*b7893ccfSSadaf Ebrahimi 448*b7893ccfSSadaf Ebrahimi#### GpuOverrideDispatchCreateShaderModule 449*b7893ccfSSadaf Ebrahimi 450*b7893ccfSSadaf EbrahimiThis function is called from PreCallRecordCreateShaderModule. 451*b7893ccfSSadaf EbrahimiThis routine sets up to call the SPIR-V optimizer to run the "BindlessCheckPass", replacing the original SPIR-V with the instrumented SPIR-V 452*b7893ccfSSadaf Ebrahimiwhich is then used in the call down the chain to CreateShaderModule. 453*b7893ccfSSadaf Ebrahimi 454*b7893ccfSSadaf EbrahimiThis function generates a "unique shader ID" that is passed to the SPIR-V optimizer, 455*b7893ccfSSadaf Ebrahimiwhich the instrumented code puts in the debug error record to identify the shader. 456*b7893ccfSSadaf EbrahimiThis ID is returned by this function so it can be recorded in the shader module at PostCallRecord time. 457*b7893ccfSSadaf EbrahimiIt would have been convenient to use the shader module handle returned from the driver to use as this shader ID. 458*b7893ccfSSadaf EbrahimiBut the shader needs to be instrumented before creating the shader module and therefore the handle is not available to use 459*b7893ccfSSadaf Ebrahimias this ID to pass to the optimizer. 460*b7893ccfSSadaf EbrahimiTherefore, the layer keeps a "counter" in per-device state that is incremented each time a shader is instrumented 461*b7893ccfSSadaf Ebrahimito generate unique IDs. 462*b7893ccfSSadaf EbrahimiThis unique ID is given to the SPIR-V optimizer and is stored in the shader module state tracker after the shader module is created, which creates the necessary association between the ID and the shader module. 463*b7893ccfSSadaf Ebrahimi 464*b7893ccfSSadaf EbrahimiThe process of instrumenting the SPIR-V also includes passing the selected descriptor set binding index 465*b7893ccfSSadaf Ebrahimito the SPIR-V optimizer which the instrumented 466*b7893ccfSSadaf Ebrahimicode uses to locate the memory block used to write the debug error record. 467*b7893ccfSSadaf EbrahimiAn instrumented shader is now "hard-wired" to write error records via the descriptor set at that binding 468*b7893ccfSSadaf Ebrahimiif it detects an error. 469*b7893ccfSSadaf EbrahimiThis implies that the instrumented shaders should only be allowed to run when the correct bindings are in place. 470*b7893ccfSSadaf Ebrahimi 471*b7893ccfSSadaf EbrahimiThe original SPIR-V bytecode is left stored in the shader module tracking data. 472*b7893ccfSSadaf EbrahimiThis is important because the layer may need to replace the instrumented shader with the original shader if, for example, 473*b7893ccfSSadaf Ebrahimithere is a binding index conflict. 474*b7893ccfSSadaf EbrahimiThe application cannot destroy the shader module until it has used the shader module to create the pipeline. 475*b7893ccfSSadaf EbrahimiThis ensures that the original SPIR-V bytecode is available if we need it to replace the instrumented shader. 476*b7893ccfSSadaf Ebrahimi 477*b7893ccfSSadaf Ebrahimi#### GpuOverrideDispatchCreatePipelineLayout 478*b7893ccfSSadaf Ebrahimi 479*b7893ccfSSadaf EbrahimiThis is function is called through PreCallRecordCreatePipelineLayout. 480*b7893ccfSSadaf Ebrahimi 481*b7893ccfSSadaf Ebrahimi* Check for a descriptor set binding index conflict. 482*b7893ccfSSadaf Ebrahimi * If there is one, issue an error message and leave the pipeline layout unmodified 483*b7893ccfSSadaf Ebrahimi * If no conflict, for each pipeline layout: 484*b7893ccfSSadaf Ebrahimi * Create a new pipeline layout 485*b7893ccfSSadaf Ebrahimi * Copy the original descriptor set layouts into the new pipeline layout 486*b7893ccfSSadaf Ebrahimi * Pad the new pipeline layout with dummy descriptor set layouts up to but not including the last one 487*b7893ccfSSadaf Ebrahimi * Add our descriptor set layout as the last one in the new pipeline layout 488*b7893ccfSSadaf Ebrahimi* Create the pipeline layouts by calling down the chain with the original or modified create info 489*b7893ccfSSadaf Ebrahimi 490*b7893ccfSSadaf Ebrahimi#### GpuPreCallQueueSubmit 491*b7893ccfSSadaf Ebrahimi 492*b7893ccfSSadaf Ebrahimi* For each primary and secondary command buffer in the submission: 493*b7893ccfSSadaf Ebrahimi * Call helper function to see if there are any update after bind descriptors whose write state may need to be updated 494*b7893ccfSSadaf Ebrahimi and if so, map the input buffer and update the state. 495*b7893ccfSSadaf Ebrahimi 496*b7893ccfSSadaf Ebrahimi#### GpuPostCallQueueSubmit 497*b7893ccfSSadaf Ebrahimi 498*b7893ccfSSadaf Ebrahimi* Submit a command buffer containing a memory barrier to make GPU writes available to the host domain. 499*b7893ccfSSadaf Ebrahimi* Call QueueWaitIdle. 500*b7893ccfSSadaf Ebrahimi* For each primary and secondary command buffer in the submission: 501*b7893ccfSSadaf Ebrahimi * Call a helper function to process the instrumentation debug buffers (described later) 502*b7893ccfSSadaf Ebrahimi 503*b7893ccfSSadaf Ebrahimi#### GpuPreCallValidateCmdWaitEvents 504*b7893ccfSSadaf Ebrahimi 505*b7893ccfSSadaf Ebrahimi* Report an error about a possible deadlock if CmdWaitEvents is recorded with VK_PIPELINE_STAGE_HOST_BIT set. 506*b7893ccfSSadaf Ebrahimi 507*b7893ccfSSadaf Ebrahimi#### GpuPreCallRecordCreateGraphicsPipelines 508*b7893ccfSSadaf Ebrahimi 509*b7893ccfSSadaf Ebrahimi* Examine the pipelines to see if any use the debug descriptor set binding index 510*b7893ccfSSadaf Ebrahimi* For those that do: 511*b7893ccfSSadaf Ebrahimi * Create non-instrumented shader modules from the saved original SPIR-V 512*b7893ccfSSadaf Ebrahimi * Modify the CreateInfo data to use these non-instrumented shaders. 513*b7893ccfSSadaf Ebrahimi * This prevents instrumented shaders from using the application's descriptor set. 514*b7893ccfSSadaf Ebrahimi 515*b7893ccfSSadaf Ebrahimi#### GpuPostCallRecordCreateGraphicsPipelines 516*b7893ccfSSadaf Ebrahimi 517*b7893ccfSSadaf Ebrahimi* For every shader in the pipeline: 518*b7893ccfSSadaf Ebrahimi * Destroy the shader module created in GpuPreCallRecordCreateGraphicsPipelines, if any 519*b7893ccfSSadaf Ebrahimi * These are found in the CreateInfo used to create the pipeline and not in the shader_module 520*b7893ccfSSadaf Ebrahimi * Create a shader tracking record that saves: 521*b7893ccfSSadaf Ebrahimi * shader module handle 522*b7893ccfSSadaf Ebrahimi * unique shader id 523*b7893ccfSSadaf Ebrahimi * graphics pipeline handle 524*b7893ccfSSadaf Ebrahimi * shader bytecode if it contains debug info 525*b7893ccfSSadaf Ebrahimi 526*b7893ccfSSadaf EbrahimiThis tracker is used to attach the shader bytecode to the shader in case it is needed 527*b7893ccfSSadaf Ebrahimilater to get the shader source code debug info. 528*b7893ccfSSadaf Ebrahimi 529*b7893ccfSSadaf EbrahimiThe current shader module tracker in the validation code stores the bytecode, 530*b7893ccfSSadaf Ebrahimibut this tracker has the same life cycle as the shader module itself. 531*b7893ccfSSadaf EbrahimiIt is possible for the application to destroy the shader module after 532*b7893ccfSSadaf Ebrahimicreating graphics pipeline and before submitting work that uses the shader, 533*b7893ccfSSadaf Ebrahimimaking the shader bytecode unavailable if needed for later analysis. 534*b7893ccfSSadaf EbrahimiTherefore, the bytecode must be saved at this opportunity. 535*b7893ccfSSadaf Ebrahimi 536*b7893ccfSSadaf EbrahimiThis tracker exists as long as the graphics pipeline exists, 537*b7893ccfSSadaf Ebrahimiso the graphics pipeline handle is also stored in this tracker so that it can 538*b7893ccfSSadaf Ebrahimibe looked up when the graphics pipeline is destroyed. 539*b7893ccfSSadaf EbrahimiAt that point, it is safe to free the bytecode since the pipeline is never used again. 540*b7893ccfSSadaf Ebrahimi 541*b7893ccfSSadaf Ebrahimi#### GpuPreCallRecordDestroyPipeline 542*b7893ccfSSadaf Ebrahimi 543*b7893ccfSSadaf Ebrahimi* Find the shader tracker(s) with the graphics pipeline handle and free the tracker, along with any bytecode it has stored in it. 544*b7893ccfSSadaf Ebrahimi 545*b7893ccfSSadaf Ebrahimi### Shader Instrumentation Scope 546*b7893ccfSSadaf Ebrahimi 547*b7893ccfSSadaf EbrahimiThe shader instrumentation process performed by the SPIR-V optimizer applies descriptor index bounds checking 548*b7893ccfSSadaf Ebrahimito descriptors of the following types: 549*b7893ccfSSadaf Ebrahimi 550*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_STORAGE_IMAGE 551*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 552*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 553*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER 554*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER 555*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 556*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_STORAGE_BUFFER 557*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC 558*b7893ccfSSadaf Ebrahimi VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC 559*b7893ccfSSadaf Ebrahimi 560*b7893ccfSSadaf EbrahimiInstrumentation is applied to the following SPIR-V operations: 561*b7893ccfSSadaf Ebrahimi 562*b7893ccfSSadaf Ebrahimi OpImageSampleImplicitLod 563*b7893ccfSSadaf Ebrahimi OpImageSampleExplicitLod 564*b7893ccfSSadaf Ebrahimi OpImageSampleDrefImplicitLod 565*b7893ccfSSadaf Ebrahimi OpImageSampleDrefExplicitLod 566*b7893ccfSSadaf Ebrahimi OpImageSampleProjImplicitLod 567*b7893ccfSSadaf Ebrahimi OpImageSampleProjExplicitLod 568*b7893ccfSSadaf Ebrahimi OpImageSampleProjDrefImplicitLod 569*b7893ccfSSadaf Ebrahimi OpImageSampleProjDrefExplicitLod 570*b7893ccfSSadaf Ebrahimi OpImageGather 571*b7893ccfSSadaf Ebrahimi OpImageDrefGather 572*b7893ccfSSadaf Ebrahimi OpImageQueryLod 573*b7893ccfSSadaf Ebrahimi OpImageSparseSampleImplicitLod 574*b7893ccfSSadaf Ebrahimi OpImageSparseSampleExplicitLod 575*b7893ccfSSadaf Ebrahimi OpImageSparseSampleDrefImplicitLod 576*b7893ccfSSadaf Ebrahimi OpImageSparseSampleDrefExplicitLod 577*b7893ccfSSadaf Ebrahimi OpImageSparseSampleProjImplicitLod 578*b7893ccfSSadaf Ebrahimi OpImageSparseSampleProjExplicitLod 579*b7893ccfSSadaf Ebrahimi OpImageSparseSampleProjDrefImplicitLod 580*b7893ccfSSadaf Ebrahimi OpImageSparseSampleProjDrefExplicitLod 581*b7893ccfSSadaf Ebrahimi OpImageSparseGather 582*b7893ccfSSadaf Ebrahimi OpImageSparseDrefGather 583*b7893ccfSSadaf Ebrahimi OpImageFetch 584*b7893ccfSSadaf Ebrahimi OpImageRead 585*b7893ccfSSadaf Ebrahimi OpImageQueryFormat 586*b7893ccfSSadaf Ebrahimi OpImageQueryOrder 587*b7893ccfSSadaf Ebrahimi OpImageQuerySizeLod 588*b7893ccfSSadaf Ebrahimi OpImageQuerySize 589*b7893ccfSSadaf Ebrahimi OpImageQueryLevels 590*b7893ccfSSadaf Ebrahimi OpImageQuerySamples 591*b7893ccfSSadaf Ebrahimi OpImageSparseFetch 592*b7893ccfSSadaf Ebrahimi OpImageSparseRead 593*b7893ccfSSadaf Ebrahimi OpImageWrite 594*b7893ccfSSadaf Ebrahimi 595*b7893ccfSSadaf EbrahimiAlso, OpLoad and OpStore with an AccessChain into a base of OpVariable with 596*b7893ccfSSadaf Ebrahimieither Uniform or StorageBuffer storage class and a type which is either a 597*b7893ccfSSadaf Ebrahimistruct decorated with Block, or a runtime or statically-sized array of such 598*b7893ccfSSadaf Ebrahimia struct. 599*b7893ccfSSadaf Ebrahimi 600*b7893ccfSSadaf Ebrahimi 601*b7893ccfSSadaf Ebrahimi### Shader Instrumentation Error Record Format 602*b7893ccfSSadaf Ebrahimi 603*b7893ccfSSadaf EbrahimiThe instrumented shader code generates "error records" in a specific format. 604*b7893ccfSSadaf Ebrahimi 605*b7893ccfSSadaf EbrahimiThis description includes the support for future GPU-Assisted Validation features 606*b7893ccfSSadaf Ebrahimisuch as checking for uninitialized descriptors in the partially-bound scenario. 607*b7893ccfSSadaf EbrahimiThese items are not used in the current implementation for descriptor array 608*b7893ccfSSadaf Ebrahimibounds checking, but are provided here to complete the description of the 609*b7893ccfSSadaf Ebrahimierror record format. 610*b7893ccfSSadaf Ebrahimi 611*b7893ccfSSadaf EbrahimiThe format of this buffer is as follows: 612*b7893ccfSSadaf Ebrahimi 613*b7893ccfSSadaf Ebrahimi```C 614*b7893ccfSSadaf Ebrahimistruct DebugOutputBuffer_t 615*b7893ccfSSadaf Ebrahimi{ 616*b7893ccfSSadaf Ebrahimi uint DataWrittenLength; 617*b7893ccfSSadaf Ebrahimi uint Data[]; 618*b7893ccfSSadaf Ebrahimi} 619*b7893ccfSSadaf Ebrahimi``` 620*b7893ccfSSadaf Ebrahimi 621*b7893ccfSSadaf Ebrahimi`DataWrittenLength` is the number of uint32_t words that have been attempted to be written. 622*b7893ccfSSadaf EbrahimiIt should be initialized to 0. 623*b7893ccfSSadaf Ebrahimi 624*b7893ccfSSadaf EbrahimiThe `Data` array is the uint32_t words written by the shaders of the pipeline to record bindless validation errors. 625*b7893ccfSSadaf EbrahimiAll elements of `Data` should be initialized to 0. 626*b7893ccfSSadaf EbrahimiNote that the `Data` array has runtime length. 627*b7893ccfSSadaf EbrahimiThe shader queries the length of the `Data` array to make sure that it does not write past the end of `Data`. 628*b7893ccfSSadaf EbrahimiThe shader only writes complete records. 629*b7893ccfSSadaf EbrahimiThe layer uses the length of `Data` to control the number of records written by the shaders. 630*b7893ccfSSadaf Ebrahimi 631*b7893ccfSSadaf EbrahimiThe `DataWrittenLength` is atomically updated by the shaders so that shaders do not overwrite each others data. 632*b7893ccfSSadaf EbrahimiThe shader takes the value it gets from the atomic update. 633*b7893ccfSSadaf EbrahimiIf the value plus the record length is greater than the length of `Data`, it does not write the record. 634*b7893ccfSSadaf Ebrahimi 635*b7893ccfSSadaf EbrahimiGiven this protocol, the value in `DataWrittenLength` is not very meaningful if it is greater than the length of `Data`. 636*b7893ccfSSadaf EbrahimiHowever, the format of the written records plus the fact that `Data` is initialized to 0 should be enough to determine 637*b7893ccfSSadaf Ebrahimithe records that were written. 638*b7893ccfSSadaf Ebrahimi 639*b7893ccfSSadaf Ebrahimi### Record Format 640*b7893ccfSSadaf Ebrahimi 641*b7893ccfSSadaf EbrahimiThe format of an output record is the following: 642*b7893ccfSSadaf Ebrahimi 643*b7893ccfSSadaf Ebrahimi Word 0: Record size 644*b7893ccfSSadaf Ebrahimi Word 1: Shader ID 645*b7893ccfSSadaf Ebrahimi Word 2: Instruction Index 646*b7893ccfSSadaf Ebrahimi Word 3: Stage 647*b7893ccfSSadaf Ebrahimi <Stage-Specific Words> 648*b7893ccfSSadaf Ebrahimi <Validation-Specific Words> 649*b7893ccfSSadaf Ebrahimi 650*b7893ccfSSadaf EbrahimiThe Record Size is the number of words in this record, including the the Record Size. 651*b7893ccfSSadaf Ebrahimi 652*b7893ccfSSadaf EbrahimiThe Shader ID is a handle that was provided by the layer when the shader was instrumented. 653*b7893ccfSSadaf Ebrahimi 654*b7893ccfSSadaf EbrahimiThe Instruction Index is the instruction within the original function at which the error occurred. 655*b7893ccfSSadaf EbrahimiFor bindless, this will be the instruction which consumes the descriptor in question, 656*b7893ccfSSadaf Ebrahimior the instruction that consumes the OpSampledImage that consumes the descriptor. 657*b7893ccfSSadaf Ebrahimi 658*b7893ccfSSadaf EbrahimiThe Stage is the integer value used in SPIR-V for each of the Execution Models: 659*b7893ccfSSadaf Ebrahimi 660*b7893ccfSSadaf Ebrahimi| Stage | Value | 661*b7893ccfSSadaf Ebrahimi|---------------|:-----:| 662*b7893ccfSSadaf Ebrahimi|Vertex |0 | 663*b7893ccfSSadaf Ebrahimi|TessCtrl |1 | 664*b7893ccfSSadaf Ebrahimi|TessEval |2 | 665*b7893ccfSSadaf Ebrahimi|Geometry |3 | 666*b7893ccfSSadaf Ebrahimi|Fragment |4 | 667*b7893ccfSSadaf Ebrahimi|Compute |5 | 668*b7893ccfSSadaf Ebrahimi|RayGenerationNV|5313 | 669*b7893ccfSSadaf Ebrahimi|IntersectionNV |5314 | 670*b7893ccfSSadaf Ebrahimi|AnyHitNV |5315 | 671*b7893ccfSSadaf Ebrahimi|ClosestHitNV |5316 | 672*b7893ccfSSadaf Ebrahimi|MissNV |5317 | 673*b7893ccfSSadaf Ebrahimi|CallableNV |5318 | 674*b7893ccfSSadaf Ebrahimi 675*b7893ccfSSadaf Ebrahimi### Stage Specific Words 676*b7893ccfSSadaf Ebrahimi 677*b7893ccfSSadaf EbrahimiThese are words that identify which "instance" of the shader the validation error occurred in. 678*b7893ccfSSadaf EbrahimiHere are words for each stage: 679*b7893ccfSSadaf Ebrahimi 680*b7893ccfSSadaf Ebrahimi| Stage | Word 0 | Word 1 | World 2 | 681*b7893ccfSSadaf Ebrahimi|---------------|------------------|------------|------------| 682*b7893ccfSSadaf Ebrahimi|Vertex |VertexID |InstanceID | unused | 683*b7893ccfSSadaf Ebrahimi|Tess* |InvocationID |unused | unused | 684*b7893ccfSSadaf Ebrahimi|Geometry |PrimitiveID |InvocationID| unused | 685*b7893ccfSSadaf Ebrahimi|Fragment |FragCoord.x |FragCoord.y | unused | 686*b7893ccfSSadaf Ebrahimi|Compute |GlobalInvocationID|unused | unused | 687*b7893ccfSSadaf Ebrahimi|RayGenerationNV|LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 688*b7893ccfSSadaf Ebrahimi|IntersectionNV |LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 689*b7893ccfSSadaf Ebrahimi|AnyHitNV |LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 690*b7893ccfSSadaf Ebrahimi|ClosestHitNV |LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 691*b7893ccfSSadaf Ebrahimi|MissNV |LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 692*b7893ccfSSadaf Ebrahimi|CallableNV |LaunchIdNV.x |LaunchIdNV.y|LaunchIdNV.z| 693*b7893ccfSSadaf Ebrahimi 694*b7893ccfSSadaf Ebrahimi"unused" means not relevant, but still present. 695*b7893ccfSSadaf Ebrahimi 696*b7893ccfSSadaf Ebrahimi### Validation-Specific Words 697*b7893ccfSSadaf Ebrahimi 698*b7893ccfSSadaf EbrahimiThese are words that are specific to the validation being done. 699*b7893ccfSSadaf EbrahimiFor bindless validation, they are variable. 700*b7893ccfSSadaf Ebrahimi 701*b7893ccfSSadaf EbrahimiThe first word is the Error Code. 702*b7893ccfSSadaf Ebrahimi 703*b7893ccfSSadaf EbrahimiFor the *OutOfBounds errors, two words will follow: Word0:DescriptorIndex, Word1:DescriptorArrayLength 704*b7893ccfSSadaf Ebrahimi 705*b7893ccfSSadaf EbrahimiFor the *Uninitialized errors, one word will follow: Word0:DescriptorIndex 706*b7893ccfSSadaf Ebrahimi 707*b7893ccfSSadaf Ebrahimi| Error | Code | Word 0 | Word 1 | 708*b7893ccfSSadaf Ebrahimi|-----------------------------|:----:|----------------|-----------------------| 709*b7893ccfSSadaf Ebrahimi|IndexOutOfBounds |0 |Descriptor Index|Descriptor Array Length| 710*b7893ccfSSadaf Ebrahimi|DescriptorUninitialized |1 |Descriptor Index|unused | 711*b7893ccfSSadaf Ebrahimi 712*b7893ccfSSadaf EbrahimiSo the words written for an image descriptor bounds error in a fragment shader is: 713*b7893ccfSSadaf Ebrahimi 714*b7893ccfSSadaf Ebrahimi Word 0: Record size (9) 715*b7893ccfSSadaf Ebrahimi Word 1: Shader ID 716*b7893ccfSSadaf Ebrahimi Word 2: Instruction Index 717*b7893ccfSSadaf Ebrahimi Word 3: Stage (4:Fragment) 718*b7893ccfSSadaf Ebrahimi Word 4: FragCoord.x 719*b7893ccfSSadaf Ebrahimi Word 5: FragCoord.y 720*b7893ccfSSadaf Ebrahimi Word 6: Error (0: ImageIndexOutOfBounds) 721*b7893ccfSSadaf Ebrahimi Word 7: DescriptorIndex 722*b7893ccfSSadaf Ebrahimi Word 8: DescriptorArrayLength 723*b7893ccfSSadaf Ebrahimi 724*b7893ccfSSadaf EbrahimiIf another error is encountered, that record is written starting at Word 10, if the whole record will not overflow Data. 725*b7893ccfSSadaf EbrahimiIf overflow will happen, no words are written.. 726*b7893ccfSSadaf Ebrahimi 727*b7893ccfSSadaf EbrahimiThe validation layer can continue to read valid records until it sees a Record Length of 0 or the end of Data is reached. 728*b7893ccfSSadaf Ebrahimi 729*b7893ccfSSadaf Ebrahimi#### Programmatic interface 730*b7893ccfSSadaf Ebrahimi 731*b7893ccfSSadaf EbrahimiThe programmatic interface for the above informal description is codified in the 732*b7893ccfSSadaf Ebrahimi[SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools) repository in file 733*b7893ccfSSadaf Ebrahimi[`instrument.hpp`](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/include/spirv-tools/instrument.hpp). 734*b7893ccfSSadaf EbrahimiIt consists largely of integer constant definitions for the codes and values mentioned above and 735*b7893ccfSSadaf Ebrahimioffsets into the record for locating each item. 736*b7893ccfSSadaf Ebrahimi 737*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Error Report 738*b7893ccfSSadaf Ebrahimi 739*b7893ccfSSadaf EbrahimiThis is a fairly simple process of mapping the debug report buffer associated with 740*b7893ccfSSadaf Ebrahimieach draw in the command buffer that was just submitted and looking to see if the GPU instrumentation 741*b7893ccfSSadaf Ebrahimicode wrote anything. 742*b7893ccfSSadaf EbrahimiEach draw in the command buffer should have a corresponding result buffer in the command buffer's list of result buffers. 743*b7893ccfSSadaf EbrahimiThe report generating code loops through the result buffers, maps each of them, checks for errors, and unmaps them. 744*b7893ccfSSadaf EbrahimiThe layer clears the buffer to zeros when it is allocated and after processing any 745*b7893ccfSSadaf Ebrahimibuffer that was written to. 746*b7893ccfSSadaf EbrahimiThe instrumented shader code expects these buffers to be cleared to zeros before it 747*b7893ccfSSadaf Ebrahimiwrites to them. 748*b7893ccfSSadaf Ebrahimi 749*b7893ccfSSadaf EbrahimiThe layer then prepares a "common" validation error message containing: 750*b7893ccfSSadaf Ebrahimi 751*b7893ccfSSadaf Ebrahimi* command buffer handle - This is easily obtained because we are looping over the command 752*b7893ccfSSadaf Ebrahimi buffers just submitted. 753*b7893ccfSSadaf Ebrahimi* draw number - keep track of how many draws we've processed for a given command buffer. 754*b7893ccfSSadaf Ebrahimi* pipeline handle - The shader tracker discussed earlier contains this handle 755*b7893ccfSSadaf Ebrahimi* shader module handle - The "Shader ID" (Word 1 in the record) is used to lookup 756*b7893ccfSSadaf Ebrahimi the shader tracker which is then used to obtain the shader module and pipeline handles 757*b7893ccfSSadaf Ebrahimi* instruction index - This is the SPIR-V instruction index where the invalid array access occurred. 758*b7893ccfSSadaf Ebrahimi It is not that useful by itself, since the user would have to use it to locate a SPIR-V instruction 759*b7893ccfSSadaf Ebrahimi in a SPIR-V disassembly and somehow relate it back to the shader source code. 760*b7893ccfSSadaf Ebrahimi But it could still be useful to some and it is easy to report. 761*b7893ccfSSadaf Ebrahimi The user can build the shader with debug information to get source-level information. 762*b7893ccfSSadaf Ebrahimi 763*b7893ccfSSadaf EbrahimiFor all objects, the layer also looks up the objects in the Debug Utils object name map in 764*b7893ccfSSadaf Ebrahimicase the application used that extension to name any objects. 765*b7893ccfSSadaf EbrahimiIf a name exists for that object, it is included in the error message. 766*b7893ccfSSadaf Ebrahimi 767*b7893ccfSSadaf EbrahimiThe layer then adds on error message text obtained from decoding the stage-specific and 768*b7893ccfSSadaf Ebrahimivalidation-specific data as described earlier. 769*b7893ccfSSadaf Ebrahimi 770*b7893ccfSSadaf EbrahimiThis completes the error report when there is no source-level debug information in the shader. 771*b7893ccfSSadaf Ebrahimi 772*b7893ccfSSadaf Ebrahimi### Source-Level Debug Information 773*b7893ccfSSadaf Ebrahimi 774*b7893ccfSSadaf EbrahimiThis is one of the more complicated and code-heavy parts of the GPU-Assisted Validation feature 775*b7893ccfSSadaf Ebrahimiand all it really does is display source-level information when the shader is compiled 776*b7893ccfSSadaf Ebrahimiwith debugging info (`-g` option in the case of `glslangValidator`). 777*b7893ccfSSadaf Ebrahimi 778*b7893ccfSSadaf EbrahimiThe process breaks down into two steps: 779*b7893ccfSSadaf Ebrahimi 780*b7893ccfSSadaf Ebrahimi#### OpLine Processing 781*b7893ccfSSadaf Ebrahimi 782*b7893ccfSSadaf EbrahimiThe SPIR-V generator (e.g., glslangValidator) places an OpLine SPIR-V instruction in the 783*b7893ccfSSadaf Ebrahimishader program ahead of code generated for each source code statement. 784*b7893ccfSSadaf EbrahimiThe OpLine instruction contains the filename id (for an OpString), 785*b7893ccfSSadaf Ebrahimithe source code line number and the source code column number. 786*b7893ccfSSadaf EbrahimiIt is possible to have two source code statements on the same line in the source file, 787*b7893ccfSSadaf Ebrahimiwhich explains the need for the column number. 788*b7893ccfSSadaf Ebrahimi 789*b7893ccfSSadaf EbrahimiThe layer scans the SPIR-V looking for the last OpLine instruction that appears before the instruction 790*b7893ccfSSadaf Ebrahimiat the instruction index obtained from the debug report. 791*b7893ccfSSadaf EbrahimiThis OpLine then contains the correct filename id, line number, and column number of the 792*b7893ccfSSadaf Ebrahimistatement causing the error. 793*b7893ccfSSadaf EbrahimiThe filename itself is obtained by scanning the SPIR-V again for an OpString instruction that 794*b7893ccfSSadaf Ebrahimimatches the id from the OpLine. 795*b7893ccfSSadaf EbrahimiThis OpString contains the text string representing the filename. 796*b7893ccfSSadaf EbrahimiThis information is added to the validation error message. 797*b7893ccfSSadaf Ebrahimi 798*b7893ccfSSadaf EbrahimiFor online compilation when there is no "file", only the line number information is reported. 799*b7893ccfSSadaf Ebrahimi 800*b7893ccfSSadaf Ebrahimi#### OpSource Processing 801*b7893ccfSSadaf Ebrahimi 802*b7893ccfSSadaf EbrahimiThe SPIR-V built with source-level debug info also contains OpSource instructions that 803*b7893ccfSSadaf Ebrahimihave a string containing the source code, delimited by newlines. 804*b7893ccfSSadaf EbrahimiDue to possible pre-processing, the layer just cannot simply use the source file line number 805*b7893ccfSSadaf Ebrahimifrom the OpLine to index into this set of source code lines. 806*b7893ccfSSadaf Ebrahimi 807*b7893ccfSSadaf EbrahimiInstead, the correct source code line is found by first locating the "#line" directive in the 808*b7893ccfSSadaf Ebrahimisource that specifies a line number closest to and less than the source line number reported 809*b7893ccfSSadaf Ebrahimiby the OpLine located in the previous step. 810*b7893ccfSSadaf EbrahimiThe correct "#line" directive must also match its filename, if specified, 811*b7893ccfSSadaf Ebrahimiwith the filename from the OpLine. 812*b7893ccfSSadaf Ebrahimi 813*b7893ccfSSadaf EbrahimiThen the difference between the "#line" line number and the OpLine line number is added 814*b7893ccfSSadaf Ebrahimito the place where the "#line" was found to locate the actual line of source, which is 815*b7893ccfSSadaf Ebrahimithen added to the validation error message. 816*b7893ccfSSadaf Ebrahimi 817*b7893ccfSSadaf EbrahimiFor example, if the OpLine line number is 15, and there is a "#line 10" on line 40 818*b7893ccfSSadaf Ebrahimiin the OpSource source, then line 45 in the OpSource contains the correct source line. 819*b7893ccfSSadaf Ebrahimi 820*b7893ccfSSadaf Ebrahimi### Shader Instrumentation Input Record Format 821*b7893ccfSSadaf Ebrahimi 822*b7893ccfSSadaf EbrahimiAlthough the input buffer is a linear array of unsigned integers, conceptually there are arrays within the linear array 823*b7893ccfSSadaf Ebrahimi 824*b7893ccfSSadaf EbrahimiWord 1 starts an array (denoted by sets_to_sizes) that is number_of_sets long, with an index that indicates the start of that set's entries in the sizes array 825*b7893ccfSSadaf Ebrahimi 826*b7893ccfSSadaf EbrahimiAfter the sets_to_sizes array is the sizes array, that contains the array size (or 1 if descriptor is not an array) of each descriptor in the set. Bindings with no descriptor are filled in with zeros 827*b7893ccfSSadaf Ebrahimi 828*b7893ccfSSadaf EbrahimiAfter the sizes array is the sets_to_bindings array that for each descriptor set, indexes into the bindings_to_written array. Word 0 contains the index that is the start of the sets_to_bindings array 829*b7893ccfSSadaf Ebrahimi 830*b7893ccfSSadaf EbrahimiAfter the sets_to_bindings array, is the bindings_to_written array that for each binding in the set, indexes to the start of that binding's entries in the written array 831*b7893ccfSSadaf Ebrahimi 832*b7893ccfSSadaf EbrahimiLastly comes the written array, which indicates whether a given binding / array element has been written 833*b7893ccfSSadaf Ebrahimi 834*b7893ccfSSadaf EbrahimiExample: 835*b7893ccfSSadaf Ebrahimi``` 836*b7893ccfSSadaf EbrahimiAssume Descriptor Set 0 looks like: And Descriptor Set 1 looks like: 837*b7893ccfSSadaf Ebrahimi Binding Binding 838*b7893ccfSSadaf Ebrahimi 0 Array[3] 2 Array[4] 839*b7893ccfSSadaf Ebrahimi 1 Non Array 3 Array[5] 840*b7893ccfSSadaf Ebrahimi 3 Array[2] 841*b7893ccfSSadaf Ebrahimi 842*b7893ccfSSadaf EbrahimiHere is what the input buffer should look like: 843*b7893ccfSSadaf Ebrahimi 844*b7893ccfSSadaf Ebrahimi Index of sets_to_sizes sizes sets_to_bindings bindings_to_written written 845*b7893ccfSSadaf Ebrahimi sets_to_bindings 846*b7893ccfSSadaf Ebrahimi 847*b7893ccfSSadaf Ebrahimi 0 |11| sets_to_bindings 1 |3| set 0 sizes start at 3 3 |3| S0B0 11 |13| set 0 bindings start at 13 13 |21| S0B0 21 |1| S0B0I0 was written 848*b7893ccfSSadaf Ebrahimi starts at 11 2 |7| set 1 sizes start at 7 4 |1| S0B1 12 |17| set 1 bindings start at 17 14 |24| S0B1 22 |1| S0B0I1 was written 849*b7893ccfSSadaf Ebrahimi 5 |0| S0B2 15 |0 | S0B2 23 |1| S0B0I3 was written 850*b7893ccfSSadaf Ebrahimi 6 |2| S0B3 16 |25| S0B3 24 |1| S0B1 was written 851*b7893ccfSSadaf Ebrahimi 7 |0| S1B0 17 |0 | S1B0 25 |1| S0B3I0 was written 852*b7893ccfSSadaf Ebrahimi 8 |0| S1B1 18 |0 | S1B1 26 |1| S0B3I1 was written 853*b7893ccfSSadaf Ebrahimi 9 |4| S1B2 19 |27| S1B2 27 |0| S1B2I0 was not written 854*b7893ccfSSadaf Ebrahimi 10 |5| S1B3 20 |31| S1B3 28 |1| S1B2I1 was written 855*b7893ccfSSadaf Ebrahimi 29 |1| S1B2I2 was written 856*b7893ccfSSadaf Ebrahimi 30 |1| S1B2I3 was written 857*b7893ccfSSadaf Ebrahimi 31 |1| S1B3I0 was written 858*b7893ccfSSadaf Ebrahimi 32 |1| S1B3I1 was written 859*b7893ccfSSadaf Ebrahimi 33 |1| S1B3I2 was written 860*b7893ccfSSadaf Ebrahimi 34 |1| S1B3I3 was written 861*b7893ccfSSadaf Ebrahimi 35 |1| S1B3I4 was written 862*b7893ccfSSadaf Ebrahimi``` 863*b7893ccfSSadaf EbrahimiAlternately, you could describe the array size and write state data as: 864*b7893ccfSSadaf Ebrahimi(set = s, binding = b, index = i) is not initialized if 865*b7893ccfSSadaf Ebrahimi``` 866*b7893ccfSSadaf EbrahimiInput[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] == 0 867*b7893ccfSSadaf Ebrahimi``` 868*b7893ccfSSadaf Ebrahimiand the array's size = Input[ Input[ s + 1 ] + b ] 869*b7893ccfSSadaf Ebrahimi 870*b7893ccfSSadaf Ebrahimi## GPU-Assisted Validation Testing 871*b7893ccfSSadaf Ebrahimi 872*b7893ccfSSadaf EbrahimiValidation Layer Tests (VLTs) exist for GPU-Assisted Validation. 873*b7893ccfSSadaf EbrahimiThey cannot be run with the "mock ICD" in headless CI environments because they need to 874*b7893ccfSSadaf Ebrahimiactually execute shaders. 875*b7893ccfSSadaf EbrahimiBut they are still useful to run on real devices to check for regressions. 876*b7893ccfSSadaf Ebrahimi 877*b7893ccfSSadaf EbrahimiThere isn't anything else that remarkable or different about these tests. 878*b7893ccfSSadaf EbrahimiThey activate GPU-Assisted Validation via the programmatic 879*b7893ccfSSadaf Ebrahimiinterface as described earlier. 880*b7893ccfSSadaf Ebrahimi 881*b7893ccfSSadaf EbrahimiThe tests exercise the extraction of source code information when the shader 882*b7893ccfSSadaf Ebrahimiis built with debug info. 883