blob: ac12a48dd147c574ecc78f979109c296724149ec [file] [log] [blame]
/* Copyright (c) 2018-2023 The Khronos Group Inc.
* Copyright (c) 2018-2023 Valve Corporation
* Copyright (c) 2018-2023 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 "gpu_subclasses.h"
#include "gpu_validation.h"
gpuav_state::DescriptorHeap::DescriptorHeap(GpuAssisted &gpu_dev, uint32_t max_descriptors)
: max_descriptors_(max_descriptors), allocator_(gpu_dev.vmaAllocator) {
// If max_descriptors_ is 0, GPU-AV aborted during vkCreateDevice(). We still need to
// support calls into this class as no-ops if this happens.
if (max_descriptors_ == 0) {
return;
}
VkBufferCreateInfo buffer_info = vku::InitStruct<VkBufferCreateInfo>();
buffer_info.size = ((max_descriptors_ + 31) & ~31) * sizeof(uint32_t);
buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
VmaAllocationCreateInfo alloc_info{};
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
[[maybe_unused]] VkResult result;
result = vmaCreateBuffer(allocator_, &buffer_info, &alloc_info, &buffer_, &allocation_, nullptr);
assert(result == VK_SUCCESS);
result = vmaMapMemory(allocator_, allocation_, reinterpret_cast<void **>(&gpu_heap_state_));
assert(result == VK_SUCCESS);
memset(gpu_heap_state_, 0, static_cast<size_t>(buffer_info.size));
auto buffer_device_address_info = vku::InitStruct<VkBufferDeviceAddressInfo>();
buffer_device_address_info.buffer = buffer_;
// We cannot rely on device_extensions here, since we may be enabling BDA support even
// though the application has not requested it.
if (gpu_dev.api_version >= VK_API_VERSION_1_2) {
device_address_ = DispatchGetBufferDeviceAddress(gpu_dev.device, &buffer_device_address_info);
} else {
device_address_ = DispatchGetBufferDeviceAddressKHR(gpu_dev.device, &buffer_device_address_info);
}
assert(device_address_ != 0);
}
gpuav_state::DescriptorHeap::~DescriptorHeap() {
if (max_descriptors_ > 0) {
vmaUnmapMemory(allocator_, allocation_);
gpu_heap_state_ = nullptr;
vmaDestroyBuffer(allocator_, buffer_, allocation_);
}
}
gpuav_state::DescriptorId gpuav_state::DescriptorHeap::NextId(const VulkanTypedHandle &handle) {
if (max_descriptors_ == 0) {
return 0;
}
gpuav_state::DescriptorId result;
auto guard = Lock();
assert(alloc_map_.size() < max_descriptors_);
do {
result = next_id_++;
if (next_id_ == max_descriptors_) {
next_id_ = 1;
result = next_id_;
}
} while (alloc_map_.count(result) > 0);
alloc_map_[result] = handle;
gpu_heap_state_[result/32] |= 1u << (result & 31);
return result;
}
void gpuav_state::DescriptorHeap::DeleteId(gpuav_state::DescriptorId id) {
if (max_descriptors_ > 0) {
auto guard = Lock();
// Note: We don't mess with next_id_ here because ids should be signed in LRU order.
gpu_heap_state_[id/32] &= ~(1u << (id & 31));
alloc_map_.erase(id);
}
}
gpuav_state::Buffer::Buffer(ValidationStateTracker *dev_data, VkBuffer buff, const VkBufferCreateInfo *pCreateInfo,
DescriptorHeap &desc_heap_)
: BUFFER_STATE(dev_data, buff, pCreateInfo),
desc_heap(desc_heap_),
id(desc_heap.NextId(VulkanTypedHandle(buff, kVulkanObjectTypeBuffer))) {}
void gpuav_state::Buffer::Destroy() {
desc_heap.DeleteId(id);
BUFFER_STATE::Destroy();
}
void gpuav_state::Buffer::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
BUFFER_STATE::NotifyInvalidate(invalid_nodes, unlink);
}
gpuav_state::BufferView::BufferView(const std::shared_ptr<BUFFER_STATE> &bf, VkBufferView bv, const VkBufferViewCreateInfo *ci,
VkFormatFeatureFlags2KHR buf_ff, DescriptorHeap &desc_heap_)
: BUFFER_VIEW_STATE(bf, bv, ci, buf_ff),
desc_heap(desc_heap_),
id(desc_heap.NextId(VulkanTypedHandle(bv, kVulkanObjectTypeBufferView))) {}
void gpuav_state::BufferView::Destroy() {
desc_heap.DeleteId(id);
BUFFER_VIEW_STATE::Destroy();
}
void gpuav_state::BufferView::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
BUFFER_VIEW_STATE::NotifyInvalidate(invalid_nodes, unlink);
}
gpuav_state::ImageView::ImageView(const std::shared_ptr<IMAGE_STATE> &image_state, VkImageView iv, const VkImageViewCreateInfo *ci,
VkFormatFeatureFlags2KHR ff, const VkFilterCubicImageViewImageFormatPropertiesEXT &cubic_props,
DescriptorHeap &desc_heap_)
: IMAGE_VIEW_STATE(image_state, iv, ci, ff, cubic_props),
desc_heap(desc_heap_),
id(desc_heap.NextId(VulkanTypedHandle(iv, kVulkanObjectTypeImageView))) {}
void gpuav_state::ImageView::Destroy() {
desc_heap.DeleteId(id);
IMAGE_VIEW_STATE::Destroy();
}
void gpuav_state::ImageView::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
IMAGE_VIEW_STATE::NotifyInvalidate(invalid_nodes, unlink);
}
gpuav_state::Sampler::Sampler(const VkSampler s, const VkSamplerCreateInfo *pci, DescriptorHeap &desc_heap_)
: SAMPLER_STATE(s, pci), desc_heap(desc_heap_), id(desc_heap.NextId(VulkanTypedHandle(s, kVulkanObjectTypeSampler))) {}
void gpuav_state::Sampler::Destroy() {
desc_heap.DeleteId(id);
SAMPLER_STATE::Destroy();
}
void gpuav_state::Sampler::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
SAMPLER_STATE::NotifyInvalidate(invalid_nodes, unlink);
}
gpuav_state::AccelerationStructureKHR::AccelerationStructureKHR(VkAccelerationStructureKHR as,
const VkAccelerationStructureCreateInfoKHR *ci,
std::shared_ptr<BUFFER_STATE> &&buf_state, VkDeviceAddress address,
DescriptorHeap &desc_heap_)
: ACCELERATION_STRUCTURE_STATE_KHR(as, ci, std::move(buf_state), address),
desc_heap(desc_heap_),
id(desc_heap.NextId(VulkanTypedHandle(as, kVulkanObjectTypeAccelerationStructureKHR))) {}
void gpuav_state::AccelerationStructureKHR::Destroy() {
desc_heap.DeleteId(id);
ACCELERATION_STRUCTURE_STATE_KHR::Destroy();
}
void gpuav_state::AccelerationStructureKHR::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
ACCELERATION_STRUCTURE_STATE_KHR::NotifyInvalidate(invalid_nodes, unlink);
}
gpuav_state::AccelerationStructureNV::AccelerationStructureNV(VkDevice device, VkAccelerationStructureNV as,
const VkAccelerationStructureCreateInfoNV *ci,
DescriptorHeap &desc_heap_)
: ACCELERATION_STRUCTURE_STATE_NV(device, as, ci),
desc_heap(desc_heap_),
id(desc_heap.NextId(VulkanTypedHandle(as, kVulkanObjectTypeAccelerationStructureNV))) {}
void gpuav_state::AccelerationStructureNV::Destroy() {
desc_heap.DeleteId(id);
ACCELERATION_STRUCTURE_STATE_NV::Destroy();
}
void gpuav_state::AccelerationStructureNV::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
desc_heap.DeleteId(id);
ACCELERATION_STRUCTURE_STATE_NV::NotifyInvalidate(invalid_nodes, unlink);
}