#include <math.h>
#ifndef INFINITY
#define INFINITY __builtin_huge_valf()
#endif
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include "backend/metal/mt_api.h"
#include "core/logger.h"
namespace rhi {
bool create_buffer(Device &device, rhi::BufferDesc &desc, Buffer &buffer) {
MTL::StorageMode storage = MTL::StorageModePrivate;
if (desc.memory == rhi::BufferMemType::Upload || desc.memory == rhi::BufferMemType::Readback) {
storage = MTL::StorageModeShared;
}
MTL::Buffer *handle = device.handle->newBuffer(desc.size, storage);
if (!handle) {
VEL_ERROR("Failed to create Metal buffer ({} bytes)", desc.size);
return false;
}
buffer.desc = desc;
buffer.handle = handle;
if (!desc.name.empty()) {
handle->setLabel(NS::String::string(desc.name.c_str(), NS::UTF8StringEncoding));
}
buffer.address = handle->gpuAddress();
buffer.mapped = (storage == MTL::StorageModeShared) ? handle->contents() : nullptr;
mt::reside(device, handle);
return true;
}
void destroy_buffer(Device &device, Buffer &buffer) {
if (buffer.handle) {
mt::unreside(device, buffer.handle);
buffer.handle->release();
buffer.handle = nullptr;
}
buffer.address = 0;
buffer.mapped = nullptr;
}
u64 buffer_device_address(Device &device, Buffer &buffer, u64 offset) {
(void)device;
if (offset > buffer.desc.size) {
VEL_ERROR("buffer_device_address: offset {} exceeds buffer size {}", offset, buffer.desc.size);
return 0;
}
if (!buffer.handle) {
return 0;
}
return buffer.handle->gpuAddress() + offset;
}
void buffer_flush(Device &device, Buffer &buffer, u64 offset, u64 size) {
// upload/readback buffers are shared (CPU-coherent), private buffers are
// never CPU-mapped nice little no-ops
(void)device;
(void)buffer;
(void)offset;
(void)size;
}
void buffer_invalidate(Device &device, Buffer &buffer, u64 offset, u64 size) {
(void)device;
(void)buffer;
(void)offset;
(void)size;
}
bool create_buffer_view(Device &device, const BufferViewDesc &desc, BufferView &out) {
(void)device;
out.buffer = desc.buffer;
out.desc = desc;
out.handle = desc.buffer ? desc.buffer->handle : nullptr;
// bda. no slot.
out.slot = 0;
if (!out.handle) {
VEL_ERROR("create_buffer_view: null buffer");
return false;
}
return true;
}
u64 handle_id(Device &device, BufferView &view) {
if (!view.buffer) {
VEL_ERROR("handle_id: buffer view has no buffer");
return 0;
}
return buffer_device_address(device, *view.buffer, view.desc.offset);
}
void destroy_buffer_view(Device &device, BufferView &view) {
(void)device;
view.slot = UINT64_MAX;
view.handle = nullptr;
view.buffer = nullptr;
}
bool valid(const BufferView &view) {
return view.handle != nullptr;
}
} // namespace rhi