1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
// Copyright (c) 2021-2026 The Khronos Group Inc.
// Copyright (c) 2021-2026 Valve Corporation
// Copyright (c) 2021-2026 LunarG, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Values used between the GLSL shaders and the GPU-AV logic
// NOTE: This header is included by the instrumentation shaders and glslang doesn't support #pragma once
#ifndef GPU_ERROR_HEADER_H
#define GPU_ERROR_HEADER_H
#include "gpuav_error_codes.h"
#ifdef __cplusplus
#include <cstdint>
namespace gpuav {
namespace glsl {
using uint = unsigned int;
#endif
// GPU-AV Error record structure:
// ------------------------------
// /---------------------------------
// | Error header
// | - Record size
// | - Shader Id
// | - Instruction Id
// | - Shader stage Id
// | - Shader stage info (3 integers)
// | - Action command index in command buffer
// | - Command resources index
// | - Error group (Id unique to the shader/instrumentation code that wrote the error)
// | - subcode (maps to VUIDs)
// | --------------------------------
// | Error specific parameters
// \---------------------------------
// Error Header offsets:
// ---------------------
// The following are offsets to fields common to all records
// Each record first contains the size of the record in 32-bit words, including
// the size word.
const int kHeader_ErrorRecordSizeOffset = 0;
// We compress the |shader id|, |error group| and |error sub code| in a single dword
// |shader id| is used to map back the VkShaderMoudle/Pipeline/ShaderObject
// |error group| maps to which instrumentation pass is from
// |error sub code| is how we can map things to a single VUID
const int kHeader_ShaderIdErrorOffset = 1;
// This is the ordinal position of the instruction within the SPIR-V shader
// which generated the validation error.
//
// This also is the stage which generated the validation error.
const int kHeader_StageInstructionIdOffset = 2;
// Each stage will contain different values in the next set of words of the
// record used to identify which instantiation of the shader generated the
// validation error.
const int kHeader_StageInfoOffset_0 = 3;
const int kHeader_StageInfoOffset_1 = 4;
const int kHeader_StageInfoOffset_2 = 5;
// Compressed dword to know where the error came from in the API
const int kHeader_ActionIdErrorLoggerIdOffset = 6;
const int kHeaderSize = 7;
const int kInst_LogError_ParameterOffset_0 = kHeaderSize;
const int kInst_LogError_ParameterOffset_1 = kHeaderSize + 1;
const int kInst_LogError_ParameterOffset_2 = kHeaderSize + 2;
// kHeader_ShaderIdErrorOffset
// ---
// This dword is split up as
// | 31 ..... 24 | 23 ......... 18 | 17 ................. 0 |
// | Error Group | Error Sub Group | Instrumented Shader Id |
//
// These limits are reasonable and will be awhile until we go past them
// When moved to slang from GLSL, can add staic asserts
const int kErrorSubCode_Shift = 18;
const int kErrorSubCode_Mask = 0x3F << kErrorSubCode_Shift; // 32 slot
const int kErrorGroup_Shift = 24;
const int kErrorGroup_Mask = 0xFF << kErrorGroup_Shift; // 256 slots
// kHeader_StageInstructionIdOffset
// ---
// This dword is split up as
// | 31 .. 27 | 26 ...... 0 |
// | Stage Id | Instruction Id |
// We control and know there are under 32 shader stages
// We can assume shader are under 128MB
const int kStageId_Shift = 27;
const int kStageId_Mask = 0x1F << kStageId_Shift; // 32 slot
const int kInstructionId_Mask = 0x7FFFFFF;
// kHeader_ActionIdErrorLoggerIdOffset
// ---
// This dword is split up as
// | 31 ..... 16 | 15 ................. 0 |
// | Error Group | Instrumented Shader Id |
// Note we have a limit (cst::indices_count) but for simplicity, divide in half until find need to adjust.
const int kActionId_Shift = 16;
const int kActionId_Mask = 0xFFFF << kActionId_Shift; // 64k slot
const int kErrorLoggerId_Mask = 0xFFFF;
// Error specific parameters offsets:
// ----------------------------------
// Descriptor Indexing
// ---
// This dword is split up as
// | 31 ........ 27 | 26 ............................................ 0 |
// | Descriptor Set | Global Descriptor index (with binding LUT offset) |
// We only allow for 32 sets (see kDebugInputBindlessMaxDescSets)
// We use a LUT per set that knows which binding the "global" Descriptor Index value lives
const int kInst_DescriptorIndexing_SetShift = 27;
const int kInst_DescriptorIndexing_SetMask = 0x1F << kInst_DescriptorIndexing_SetShift; // 32 slot
const int kInst_DescriptorIndexing_IndexMask = 0x7FFFFFF;
// Buffer device addresses
// ---
// Payload contains 3 pieces of data, compressed into a single uint32_t
// We can be safe that assume alignment we don't need these upper 2 bytes
// Note - if needed, we could use log2(alignment) as it must be a Power-of-Two
// | 31 | 30 | 29 ........................ 0 |
// | is write | is struct | Alignment OR Access Byte Size |
const uint kInst_BuffAddrAccess_PayloadShiftIsWrite = 31;
const uint kInst_BuffAddrAccess_PayloadShiftIsStruct = 30;
const uint kInst_BuffAddrAccess_PayloadMaskAccessInfo = 0x3FFFFFFF;
// kErrorGroup_InstMeshShading
// ---
// This dword is split up as
// | 31 ........ 16 | 15 .............. 0 |
// | OutputVertices | OutputPrimitivesEXT |
// This is because the limits for both of these on all known devices is 1024
const int kInst_MeshShading_OutputVerticesShift = 16;
const int kInst_MeshShading_OutputPrimitivesMask = 0xFFFF;
// Validation commands shaders
// ---
const int kValCmd_ErrorPayloadDword_0 = kHeaderSize;
const int kValCmd_ErrorPayloadDword_1 = kHeaderSize + 1;
const int kValCmd_ErrorPayloadDword_2 = kHeaderSize + 2;
const int kValCmd_ErrorPayloadDword_3 = kHeaderSize + 3;
const int kValCmd_ErrorPayloadDword_4 = kHeaderSize + 4;
// Sizes/Counts
// -------------------
const int kErrorRecordSize = kHeaderSize + 5;
const int kErrorRecordCounts = 4096; // Maximum number of errors a command buffer can hold. Arbitrary value
const int kErrorBufferByteSize = 4 * kErrorRecordSize * kErrorRecordCounts + 2 * 4; // 2 * 4 bytes to store flags and errors count
#ifdef __cplusplus
} // namespace glsl
#endif
// DebugPrintf
// ---
const int kDebugPrintf_OutputBuffer_DWordsCount = 0;
const int kDebugPrintf_OutputBuffer_Data = 1;
#ifdef __cplusplus
[[maybe_unused]] static inline uint32_t GetErrorGroup(const uint32_t* error_record) {
return error_record[glsl::kHeader_ShaderIdErrorOffset] >> glsl::kErrorGroup_Shift;
}
[[maybe_unused]] static inline uint32_t GetSubError(const uint32_t* error_record) {
return (error_record[glsl::kHeader_ShaderIdErrorOffset] & glsl::kErrorSubCode_Mask) >> glsl::kErrorSubCode_Shift;
}
} // namespace gpuav
#endif
#endif
|