blob: 2ca1003f72de00c4a0da40c09ba70821a948a9ae [file] [edit]
/* Copyright (c) 2026 Valve Corporation
* Copyright (c) 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 "gpu_dump.h"
#include <cstdint>
#include "chassis/layer_object_id.h"
#include "generated/dispatch_functions.h"
#include "generated/vk_extension_helper.h"
#include "state_tracker/buffer_state.h"
#include "state_tracker/device_memory_state.h"
#include "state_tracker/ray_tracing_state.h"
namespace gpudump {
GpuDump::GpuDump(vvl::DispatchDevice* dev, gpudump::Instance* instance_vo)
: vvl::DeviceProxy(dev, instance_vo, LayerObjectTypeGpuDump) {}
GpuDump::~GpuDump() {}
std::vector<uint8_t> GpuDump::CopyDataFromMemory(VkDeviceAddress memory_addresss, VkDeviceSize copy_size) {
std::vector<uint8_t> result;
vvl::span<vvl::Buffer* const> buffer_list = device_state->GetBuffersByAddress(memory_addresss);
if (buffer_list.empty()) {
return result;
}
auto buffer_state = *buffer_list.begin();
const vvl::DeviceMemory& memory_state = *buffer_state->MemoryState();
// Prevent copying OOB of a buffer
if ((memory_addresss + copy_size) > buffer_state->DeviceAddressRange().end) {
return result;
}
VkDeviceSize offset = memory_addresss - buffer_state->DeviceAddressRange().begin;
if (memory_state.mappable) {
uint8_t* data_ptr = static_cast<uint8_t*>(memory_state.p_driver_data);
if (!memory_state.p_driver_data) {
// Just use WHOLE_SIZE to avoid issues with partial mappings
// Example:
// The |memory_address| is 0x1001 and |copy_size| is 4, the driver (or at least TestICD) will return back something
// aligned to a value like 64, so if the buffer is only 64 bytes, you will now be accessing data over it
DispatchMapMemory(device, memory_state.VkHandle(), offset, VK_WHOLE_SIZE, 0, (void**)&data_ptr);
if (memory_state.cache_non_coherent) {
const VkDeviceSize atom_size = phys_dev_props.limits.nonCoherentAtomSize;
uint64_t aligned_offset = offset & ~(atom_size - 1);
if (aligned_offset < offset) {
aligned_offset = offset;
}
VkMappedMemoryRange memory_range = vku::InitStructHelper();
memory_range.memory = memory_state.VkHandle();
memory_range.offset = aligned_offset;
memory_range.size = VK_WHOLE_SIZE;
DispatchInvalidateMappedMemoryRanges(device, 1, &memory_range);
}
}
data_ptr += offset;
result.resize(static_cast<uint32_t>(copy_size));
memcpy(result.data(), data_ptr, static_cast<uint32_t>(copy_size));
if (!memory_state.p_driver_data) {
DispatchUnmapMemory(device, memory_state.VkHandle());
}
} else {
// TODO - Handle non-host visible memory
// When we add, we need to guard against if trying to read non-aligned data
// (which should have a warning already)
}
return result;
}
bool GpuDump::ListBuffers(std::ostringstream& ss, VkDeviceAddress address, uint32_t indents, bool new_line_start) {
if (new_line_start) {
ss << "\n";
}
auto buffer_states = GetBuffersByAddress(address);
for (uint32_t i = 0; i < indents; i++) {
ss << " ";
}
for (uint32_t i = 0; i < buffer_states.size(); i++) {
if (i != 0) {
ss << '\n';
for (uint32_t j = 0; j < indents; j++) {
ss << " ";
}
}
auto& buffer_state = buffer_states[i];
ss << "- " << buffer_state->Describe(*this);
}
if (buffer_states.empty()) {
ss << "- [WARNING] No VkBuffer found at 0x" << std::hex << address;
}
if (!new_line_start) {
ss << "\n";
}
return buffer_states.empty();
}
bool GpuDump::ListAccelerationStructures(std::ostringstream& ss, VkDeviceAddress address, uint32_t indents, bool new_line_start) {
if (new_line_start) {
ss << "\n";
}
auto as_states = GetAccelerationStructuresByAddress(address);
for (uint32_t i = 0; i < indents; i++) {
ss << " ";
}
for (uint32_t i = 0; i < as_states.size(); i++) {
if (i != 0) {
ss << '\n';
for (uint32_t j = 0; j < indents; j++) {
ss << " ";
}
}
auto& as_state = as_states[i];
ss << "- " << as_state->Describe(*this);
}
if (as_states.empty()) {
ss << "- [WARNING] No VkAccelerationStructureKHR found at 0x" << std::hex << address;
}
if (!new_line_start) {
ss << "\n";
}
return as_states.empty();
}
} // namespace gpudump