blob: 119a00ea06662a017ee53382eb4774f5bc7fcc0b [file] [edit]
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-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.
*/
#include "state_tracker/ray_tracing_state.h"
#include "state_tracker/state_tracker.h"
namespace vvl {
AccelerationStructureKHR::AccelerationStructureKHR(vvl::DeviceState& device_state,
const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
VkAccelerationStructureKHR handle)
: StateObject(handle, kVulkanObjectTypeAccelerationStructureKHR),
create_info(std::in_place_type<CreateInfo1>, pCreateInfo, device_state.Get<vvl::Buffer>(pCreateInfo->buffer)) {
auto& ci_1 = std::get<CreateInfo1>(create_info);
if (ci_1.buffer_state) {
VkDeviceAddress buffer_address = 0;
if (ci_1.buffer_state->deviceAddress != 0) {
buffer_address = ci_1.buffer_state->deviceAddress;
} else if (ci_1.buffer_state->Binding()) {
buffer_address = device_state.GetBufferDeviceAddressHelper(ci_1.buffer_state->VkHandle());
}
device_address_range = {buffer_address + pCreateInfo->offset, pCreateInfo->size};
}
}
AccelerationStructureKHR::AccelerationStructureKHR(vvl::DeviceState& device_state,
const VkAccelerationStructureCreateInfo2KHR* pCreateInfo,
VkAccelerationStructureKHR handle)
: StateObject(handle, kVulkanObjectTypeAccelerationStructureKHR),
create_info(std::in_place_type<vku::safe_VkAccelerationStructureCreateInfo2KHR>, pCreateInfo),
device_address_range(pCreateInfo->addressRange) {}
AccelerationStructureKHR::~AccelerationStructureKHR() {
if (!Destroyed()) {
Destroy();
}
}
void AccelerationStructureKHR::LinkChildNodes() {
if (auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
if (ci_1->buffer_state) {
ci_1->buffer_state->AddParent(this);
}
}
}
void AccelerationStructureKHR::Destroy() {
for (auto& item : sub_states_) {
item.second->Destroy();
}
if (auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
if (ci_1->buffer_state) {
ci_1->buffer_state->RemoveParent(this);
ci_1->buffer_state = nullptr;
}
}
StateObject::Destroy();
}
void AccelerationStructureKHR::NotifyInvalidate(const StateObject::NodeList& invalid_nodes, bool unlink) {
for (auto& item : sub_states_) {
item.second->NotifyInvalidate(invalid_nodes, unlink);
}
StateObject::NotifyInvalidate(invalid_nodes, unlink);
}
void AccelerationStructureKHR::Build(const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, const bool is_host,
const VkAccelerationStructureBuildRangeInfoKHR* build_range_info) {
if (!GetBuildInfo().has_value()) {
build_geometry_info = vku::safe_VkAccelerationStructureBuildGeometryInfoKHR();
}
build_geometry_info->initialize(pInfo, is_host, build_range_info);
};
void AccelerationStructureKHR::UpdateBuildRangeInfos(const VkAccelerationStructureBuildRangeInfoKHR* p_build_range_infos,
uint32_t geometry_count) {
build_range_infos.resize(geometry_count);
for (const auto [i, build_range] : vvl::enumerate(p_build_range_infos, geometry_count)) {
build_range_infos[i] = build_range;
}
}
bool AccelerationStructureKHR::UsesCreateInfo1() const { return std::get_if<CreateInfo1>(&create_info) != nullptr; }
bool AccelerationStructureKHR::UsesCreateInfo2() const {
return std::get_if<vku::safe_VkAccelerationStructureCreateInfo2KHR>(&create_info) != nullptr;
}
BufferAndOffset AccelerationStructureKHR::GetFirstValidBuffer(const vvl::DeviceState& device_state) const {
if (const auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
return {ci_1->buffer_state.get(), ci_1->ci.offset};
}
const auto& ci_2 = std::get<vku::safe_VkAccelerationStructureCreateInfo2KHR>(create_info);
const auto buffer_states = device_state.GetBuffersByAddress(ci_2.addressRange.address);
const vvl::range<VkDeviceAddress> as_addr_range{ci_2.addressRange.address, ci_2.addressRange.address + ci_2.addressRange.size};
for (const auto& as_buffer : buffer_states) {
if ((as_buffer->usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR) &&
as_buffer->DeviceAddressRange().includes(as_addr_range)) {
return {as_buffer, ci_2.addressRange.address - as_buffer->deviceAddress};
}
}
return {nullptr, 0};
}
VkAccelerationStructureCreateFlagsKHR AccelerationStructureKHR::GetCreateFlags() const {
if (const auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
return ci_1->ci.createFlags;
}
return std::get<vku::safe_VkAccelerationStructureCreateInfo2KHR>(create_info).createFlags;
}
VkDeviceSize AccelerationStructureKHR::GetSize() const {
if (const auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
return ci_1->ci.size;
}
return device_address_range.size;
}
VkAccelerationStructureTypeKHR AccelerationStructureKHR::GetType() const {
if (const auto* ci_1 = std::get_if<CreateInfo1>(&create_info)) {
return ci_1->ci.type;
}
return std::get<vku::safe_VkAccelerationStructureCreateInfo2KHR>(create_info).type;
}
VkDeviceAddressRangeKHR AccelerationStructureKHR::GetEffectiveDeviceAddressRange() const { return device_address_range; }
vvl::range<VkDeviceAddress> AccelerationStructureKHR::GetVvlEffectiveDeviceAddressRange() const {
const VkDeviceAddressRangeKHR khr_device_address_range = GetEffectiveDeviceAddressRange();
return {khr_device_address_range.address, khr_device_address_range.address + khr_device_address_range.size};
}
} // namespace vvl