12#if defined(TRK_HAS_CUDA_TRACKING)
13#include <cuda_runtime.h>
14#elif defined(TRK_HAS_HIP_TRACKING)
15#include <hip/hip_runtime.h>
26#if defined(TRK_HAS_CUDA_TRACKING)
27void checkGpuError(cudaError_t error,
const char* call)
29 if (error != cudaSuccess) {
30 throw std::runtime_error(std::string(call) +
": " + cudaGetErrorString(error));
33#elif defined(TRK_HAS_HIP_TRACKING)
34void checkGpuError(hipError_t error,
const char* call)
36 if (error != hipSuccess) {
37 throw std::runtime_error(std::string(call) +
": " + hipGetErrorString(error));
53 const auto type =
static_cast<MemoryType
>(
getType());
57 void*
ptr = useHost ? allocateHost(
size) : allocateDevice(
size);
59 std::lock_guard<std::mutex> guard(mMutex);
60 const uint64_t tag = (useStack && !mTagStack.empty()) ? mTagStack.back() : 0;
61 mAllocations.emplace(
ptr, AllocationMeta{useHost ? AllocationSpace::Host : AllocationSpace::Device, tag, useStack});
63 mTaggedAllocations[tag].push_back(
ptr);
77 std::lock_guard<std::mutex> guard(mMutex);
78 const auto found = mAllocations.find(
ptr);
79 if (found == mAllocations.end()) {
83 mAllocations.erase(found);
85 removeFromTagLocked(meta.tag,
ptr);
89 freeAllocation(
ptr, meta.space);
94 std::lock_guard<std::mutex> guard(mMutex);
95 mTagStack.push_back(tag);
100 std::vector<std::pair<void*, AllocationSpace>> toFree;
102 std::lock_guard<std::mutex> guard(mMutex);
103 if (mTagStack.empty() || mTagStack.back() != tag) {
104 throw std::runtime_error(
"GPUExternalAllocator tag stack mismatch");
107 const auto tagged = mTaggedAllocations.find(tag);
108 if (tagged != mTaggedAllocations.end()) {
109 toFree.reserve(tagged->second.size());
110 for (
void*
ptr : tagged->second) {
111 const auto found = mAllocations.find(
ptr);
112 if (found != mAllocations.end()) {
113 toFree.emplace_back(
ptr, found->second.space);
114 mAllocations.erase(found);
117 mTaggedAllocations.erase(tagged);
120 mTagStack.pop_back();
123 for (
const auto& [
ptr, space] : toFree) {
124 freeAllocation(
ptr, space);
130 std::vector<std::pair<void*, AllocationSpace>> toFree;
132 std::lock_guard<std::mutex> guard(mMutex);
133 toFree.reserve(mAllocations.size());
134 for (
const auto& [
ptr, meta] : mAllocations) {
135 toFree.emplace_back(
ptr, meta.space);
137 mAllocations.clear();
138 mTaggedAllocations.clear();
142 for (
const auto& [
ptr, space] : toFree) {
143 freeAllocation(
ptr, space);
147void* GPUExternalAllocator::allocateHost(
size_t size)
150#if defined(TRK_HAS_CUDA_TRACKING)
151 checkGpuError(cudaHostAlloc(&
ptr,
size, cudaHostAllocPortable),
"cudaHostAlloc");
152#elif defined(TRK_HAS_HIP_TRACKING)
153 checkGpuError(hipHostMalloc(&
ptr,
size, hipHostMallocPortable),
"hipHostMalloc");
155 throw std::runtime_error(
"GPUExternalAllocator built without a GPU backend");
160void* GPUExternalAllocator::allocateDevice(
size_t size)
163#if defined(TRK_HAS_CUDA_TRACKING)
164 checkGpuError(cudaMalloc(&
ptr,
size),
"cudaMalloc");
165#elif defined(TRK_HAS_HIP_TRACKING)
166 checkGpuError(hipMalloc(&
ptr,
size),
"hipMalloc");
168 throw std::runtime_error(
"GPUExternalAllocator built without a GPU backend");
173void GPUExternalAllocator::freeAllocation(
void*
ptr, AllocationSpace space)
179#if defined(TRK_HAS_CUDA_TRACKING)
180 if (space == AllocationSpace::Host) {
181 checkGpuError(cudaFreeHost(
ptr),
"cudaFreeHost");
183 checkGpuError(cudaFree(
ptr),
"cudaFree");
185#elif defined(TRK_HAS_HIP_TRACKING)
186 if (space == AllocationSpace::Host) {
187 checkGpuError(hipHostFree(
ptr),
"hipHostFree");
189 checkGpuError(hipFree(
ptr),
"hipFree");
196void GPUExternalAllocator::removeFromTagLocked(uint64_t tag,
void*
ptr)
198 const auto tagged = mTaggedAllocations.find(tag);
199 if (tagged == mTaggedAllocations.end()) {
203 auto& entries = tagged->second;
204 entries.erase(std::remove(entries.begin(), entries.end(),
ptr), entries.end());
205 if (entries.empty()) {
206 mTaggedAllocations.erase(tagged);
Type getType() const noexcept
void * allocate(size_t size) override
void pushTagOnStack(uint64_t tag) override
void deallocate(char *ptr, size_t size) override
void popTagOffStack(uint64_t tag) override
GLint GLint GLsizei GLint GLenum GLenum type
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)