blob: 93a350f0daf54f87ad98fffe6013c5d177ac0e45 [file]
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (C) 2015-2026 Google 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.
*/
#pragma once
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <string>
#include <vector>
#include "generated/error_location_helper.h"
namespace spirv {
struct ResourceInterfaceVariable;
}
namespace vvl {
class DeviceState;
}
static inline const VkSamplerCreateInfo* GetEmbeddedSampler(const VkDescriptorSetAndBindingMappingEXT& mapping) {
switch (mapping.source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
return mapping.sourceData.constantOffset.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
return mapping.sourceData.pushIndex.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
return mapping.sourceData.indirectIndex.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
return mapping.sourceData.indirectIndexArray.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
return mapping.sourceData.shaderRecordIndex.pEmbeddedSampler;
default:
return nullptr;
}
}
uint32_t CountDescriptorHeapEmbeddedSamplers(const void* pNext);
static constexpr bool IsDescriptorHeapAddr(const VkDescriptorType type) {
return (type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) || (type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) ||
(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) || (type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
(type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV);
}
static constexpr bool IsDescriptorHeapTexelBuffer(const VkDescriptorType type) {
return (type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) || (type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
}
static constexpr bool IsDescriptorHeapImage(const VkDescriptorType type) {
return (type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM) ||
(type == VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM) || (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
(type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
}
static constexpr bool IsDescriptorHeapTensor(const VkDescriptorType type) { return (type == VK_DESCRIPTOR_TYPE_TENSOR_ARM); }
vvl::Field DescriptorBufferSizeField(bool robust, VkDescriptorType type);
bool IsResourceVaribleInMapping(const VkDescriptorSetAndBindingMappingEXT& mapping,
const spirv::ResourceInterfaceVariable& resource_variable);
bool ResourceTypeMatchesBinding(VkSpirvResourceTypeFlagsEXT resource_type,
const spirv::ResourceInterfaceVariable& resource_variable);
std::string DescribeResourceTypeMismatch(VkSpirvResourceTypeFlagsEXT resource_type,
const spirv::ResourceInterfaceVariable& resource_variable);
VkDeviceSize GetDescriptorHeapAlignment(const VkPhysicalDeviceDescriptorHeapPropertiesEXT& props, VkDescriptorType type);
vvl::Field GetDescriptorHeapAlignmentField(VkDescriptorType type);
bool HasCombinedImageSamplerIndex(const VkDescriptorSetAndBindingMappingEXT& mapping);
// Way to cache vkGetPhysicalDeviceDescriptorSizeEXT as a flat array
// This is a very quick way to use the VkDescriptorType enum and knowledge of the limited VkDescriptorType allowed to make this fast
// and not making it impossible to update if a new VkDescriptorType is added later
struct DeviceExtensions;
struct CachedDescriptorSize {
void Init(const vvl::DeviceState& device_state);
VkDeviceSize GetSize(VkDescriptorType type, bool use_heap = true) const;
std::vector<VkDeviceSize> GetAllSizes(bool use_heap) const;
private:
// The number of valid descriptors that can be queried is known in the spec
// (see VU 11362)
VkDeviceSize heap_size_[14]; // VK_EXT_descriptor_heap
VkDeviceSize buffer_size_[14]; // VK_EXT_descriptor_buffer
};
// We need a way to compress the VkDescriptorType enum to cover all the "real" types
// (those seen in vkGetPhysicalDeviceDescriptorSizeEXT).
//
// This all should be capable of being packed in 4 bits as there are only 14 known types currently
enum class vvlDescriptorType : uint8_t {
// Sampler is a speical case, it is never by itself and instead is is provided along with an image
Sampler = 0x0, // VK_DESCRIPTOR_TYPE_SAMPLER
CombinedSampler = 0x1, // VK_DESCRIPTOR_TYPE_SAMPLER part of a COMBINED_IMAGE_SAMPLER
// Buffers
UniformBuffer = 0x2, // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
StorageBuffer = 0x3, // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
// RT
AccelerationStructure = 0x4, // VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
// (currently 0x5, 0x6, 0x7 are not being used)
// Images
ImageSampled = 0x8, // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
ImageStorage = 0x9, // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
ImageTexelBufferUniform = 0xA, // VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
ImageTexelBufferStorage = 0xB, // VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
ImageInputAttachment = 0xC, // VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
Invalid = 0xFF
};
inline constexpr uint8_t vvlDescriptorBufferMask = 0x2;
inline constexpr uint8_t vvlDescriptorImageMask = 0x8;
inline constexpr uint8_t vvlDescriptorMaxBit = 12; // 0xC
constexpr VkDescriptorType GetDescriptorTypeFromMask(vvlDescriptorType vvl_type) noexcept {
switch (vvl_type) {
case vvlDescriptorType::Sampler:
case vvlDescriptorType::CombinedSampler:
return VK_DESCRIPTOR_TYPE_SAMPLER;
case vvlDescriptorType::UniformBuffer:
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case vvlDescriptorType::StorageBuffer:
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
case vvlDescriptorType::AccelerationStructure:
return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
case vvlDescriptorType::ImageSampled:
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
case vvlDescriptorType::ImageStorage:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case vvlDescriptorType::ImageTexelBufferUniform:
return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
case vvlDescriptorType::ImageTexelBufferStorage:
return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
case vvlDescriptorType::ImageInputAttachment:
return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
case vvlDescriptorType::Invalid:
assert(false);
}
assert(false && "Invalid compressed descriptor type mask");
return VK_DESCRIPTOR_TYPE_MAX_ENUM;
}
constexpr vvlDescriptorType GetMaskFromDescriptorType(VkDescriptorType vk_type) noexcept {
switch (vk_type) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
return vvlDescriptorType::Sampler;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
return vvlDescriptorType::UniformBuffer;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
return vvlDescriptorType::StorageBuffer;
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
return vvlDescriptorType::AccelerationStructure;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return vvlDescriptorType::ImageSampled;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
return vvlDescriptorType::ImageStorage;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
return vvlDescriptorType::ImageTexelBufferUniform;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
return vvlDescriptorType::ImageTexelBufferStorage;
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return vvlDescriptorType::ImageInputAttachment;
default:
break;
}
assert(false && "Unsupported VkDescriptorType for compression");
return static_cast<vvlDescriptorType>(0xFF);
}