File: sl_shader_object.cpp

package info (click to toggle)
vulkan-validationlayers 1.4.321.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 47,412 kB
  • sloc: cpp: 594,175; python: 11,321; sh: 24; makefile: 20; xml: 14
file content (183 lines) | stat: -rw-r--r-- 12,164 bytes parent folder | download | duplicates (5)
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
/* Copyright (c) 2023-2024 Nintendo
 * Copyright (c) 2023-2025 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.
 */

#include "stateless/stateless_validation.h"
#include <spirv/unified1/spirv.hpp>
#include "utils/math_utils.h"

namespace stateless {

bool Device::manual_PreCallValidateCreateShadersEXT(VkDevice device, uint32_t createInfoCount,
                                                    const VkShaderCreateInfoEXT *pCreateInfos,
                                                    const VkAllocationCallbacks *pAllocator, VkShaderEXT *pShaders,
                                                    const Context &context) const {
    bool skip = false;
    const auto &error_obj = context.error_obj;

    for (uint32_t i = 0; i < createInfoCount; ++i) {
        const Location create_info_loc = error_obj.location.dot(Field::pCreateInfos, i);
        const VkShaderCreateInfoEXT &createInfo = pCreateInfos[i];
        auto pCode = reinterpret_cast<std::uintptr_t>(createInfo.pCode);

        if (createInfo.codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT) {
            if (SafeModulo(pCode, 4 * sizeof(unsigned char)) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-pCode-08493", device, create_info_loc.dot(Field::codeType),
                                 "is VK_SHADER_CODE_TYPE_SPIRV_EXT, but pCode (%p) is not aligned to 4 bytes.", createInfo.pCode);
            } else if (SafeModulo(createInfo.codeSize, 4) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-codeSize-08735", device, create_info_loc.dot(Field::codeSize),
                                 "(%" PRIu64 ") is not a multiple of 4. You might have forget to multiply by sizeof(uint32_t).",
                                 static_cast<uint64_t>(createInfo.codeSize));
            } else {
                // Can't cast this until we know it is aligned to 4 bytes or USAN will catch it
                const uint32_t first_dword = ((uint32_t *)createInfo.pCode)[0];
                if (first_dword != spv::MagicNumber) {
                    skip |= LogError("VUID-VkShaderCreateInfoEXT-pCode-08738", device, create_info_loc.dot(Field::pCode),
                                     "doesn't point to a SPIR-V module. The first dword (0x%" PRIx32
                                     ") is not the SPIR-V MagicNumber (0x07230203).",
                                     first_dword);
                }
            }

        } else if (createInfo.codeType == VK_SHADER_CODE_TYPE_BINARY_EXT) {
            if (SafeModulo(pCode, 16 * sizeof(unsigned char)) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-pCode-08492", device, create_info_loc.dot(Field::codeType),
                                 "is VK_SHADER_CODE_TYPE_BINARY_EXT, but pCode (%p) is not aligned to 16 bytes.", createInfo.pCode);
            }
        }

        const VkShaderStageFlags linkedStages = VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT |
                                                VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
                                                VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT |
                                                VK_SHADER_STAGE_FRAGMENT_BIT;
        if ((createInfo.stage & linkedStages) == 0 && (createInfo.flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT) != 0) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08412", device, create_info_loc.dot(Field::flags),
                             "includes VK_SHADER_CREATE_LINK_STAGE_BIT_EXT but the stage is %s.",
                             string_VkShaderStageFlagBits(createInfo.stage));
        }
        if ((createInfo.stage != VK_SHADER_STAGE_COMPUTE_BIT) &&
            ((createInfo.flags & VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT) != 0)) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08485", device, create_info_loc.dot(Field::flags),
                             "includes VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT but the stage is %s.",
                             string_VkShaderStageFlagBits(createInfo.stage));
        }
        if (createInfo.stage != VK_SHADER_STAGE_FRAGMENT_BIT) {
            if ((createInfo.flags & VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08486", device, create_info_loc.dot(Field::flags),
                                 "includes VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT but the stage is %s.",
                                 string_VkShaderStageFlagBits(createInfo.stage));
            }
            if ((createInfo.flags & VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08488", device, create_info_loc.dot(Field::flags),
                                 "includes VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT but the stage is %s.",
                                 string_VkShaderStageFlagBits(createInfo.stage));
            }
        }

        if (createInfo.stage != VK_SHADER_STAGE_MESH_BIT_EXT && (createInfo.flags & VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT) != 0) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08414", device, create_info_loc.dot(Field::flags),
                             "includes VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT but the stage is %s.",
                             string_VkShaderStageFlagBits(createInfo.stage));
        }

        if (createInfo.stage == VK_SHADER_STAGE_VERTEX_BIT) {
            if ((createInfo.nextStage &
                 ~(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08427", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_VERTEX_BIT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
            if ((createInfo.nextStage & ~(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08430", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
            if ((createInfo.nextStage & ~(VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08431", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_GEOMETRY_BIT) {
            if ((createInfo.nextStage & ~VK_SHADER_STAGE_FRAGMENT_BIT) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08433", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_GEOMETRY_BIT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT || createInfo.stage == VK_SHADER_STAGE_COMPUTE_BIT) {
            if (createInfo.nextStage != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08434", device, create_info_loc.dot(Field::stage),
                                 "is %s, but nextStage is %s.", string_VkShaderStageFlagBits(createInfo.stage),
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_TASK_BIT_EXT) {
            if ((createInfo.nextStage & ~VK_SHADER_STAGE_MESH_BIT_EXT) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08435", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_TASK_BIT_EXT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_MESH_BIT_EXT) {
            if ((createInfo.nextStage & ~VK_SHADER_STAGE_FRAGMENT_BIT) != 0) {
                skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08436", device, create_info_loc.dot(Field::stage),
                                 "is VK_SHADER_STAGE_MESH_BIT_EXT, but nextStage is %s.",
                                 string_VkShaderStageFlags(createInfo.nextStage).c_str());
            }
        } else if (createInfo.stage == VK_SHADER_STAGE_ALL_GRAPHICS) {
            // string_VkShaderStageFlagBits can't print these, so list manually
            skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08418", device, create_info_loc.dot(Field::stage),
                             "is VK_SHADER_STAGE_ALL_GRAPHICS.");
        } else if (createInfo.stage == VK_SHADER_STAGE_ALL) {
            // string_VkShaderStageFlagBits can't print these, so list manually
            skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08418", device, create_info_loc.dot(Field::stage),
                             "is VK_SHADER_STAGE_ALL.");
        } else if (createInfo.stage == VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08425", device, create_info_loc.dot(Field::stage),
                             "is VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI.");
        } else if (createInfo.stage == VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08426", device, create_info_loc.dot(Field::stage),
                             "is VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI.");
        }

        if (((createInfo.flags & VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT) != 0) &&
            ((createInfo.stage & (VK_SHADER_STAGE_MESH_BIT_EXT | VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_COMPUTE_BIT)) ==
             0)) {
            skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08992", device, create_info_loc.dot(Field::flags),
                             "includes VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT but the stage is %s.",
                             string_VkShaderStageFlagBits(createInfo.stage));
        }

        skip |= ValidatePushConstantRange(createInfo.pushConstantRangeCount, createInfo.pPushConstantRanges, create_info_loc);
    }

    return skip;
}

bool Device::manual_PreCallValidateGetShaderBinaryDataEXT(VkDevice device, VkShaderEXT shader, size_t *pDataSize, void *pData,
                                                          const Context &context) const {
    bool skip = false;
    const auto &error_obj = context.error_obj;

    if (pData) {
        auto ptr = reinterpret_cast<std::uintptr_t>(pData);
        if (SafeModulo(ptr, 16 * sizeof(unsigned char)) != 0) {
            skip |= LogError("VUID-vkGetShaderBinaryDataEXT-None-08499", shader, error_obj.location.dot(Field::pData),
                             "(%p) is not aligned to 16 bytes.", pData);
        }
    }

    return skip;
}
}  // namespace stateless