#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 {
static MTL::SamplerMinMagFilter to_filter(rhi::SamplerFilter filter) {
switch (filter) {
case rhi::SamplerFilter::POINT:
return MTL::SamplerMinMagFilterNearest;
case rhi::SamplerFilter::LINEAR:
case rhi::SamplerFilter::ANISOTROPIC:
default:
return MTL::SamplerMinMagFilterLinear;
}
}
static MTL::SamplerAddressMode to_address(rhi::SamplerAddressMode mode) {
switch (mode) {
case rhi::SamplerAddressMode::WRAP:
return MTL::SamplerAddressModeRepeat;
case rhi::SamplerAddressMode::MIRROR:
return MTL::SamplerAddressModeMirrorRepeat;
case rhi::SamplerAddressMode::CLAMP:
return MTL::SamplerAddressModeClampToEdge;
case rhi::SamplerAddressMode::BORDER:
default:
return MTL::SamplerAddressModeClampToEdge;
}
}
bool create_sampler(Device &device, SamplerDesc &desc, Sampler &sampler) {
MTL::SamplerDescriptor *sd = MTL::SamplerDescriptor::alloc()->init();
sd->setMinFilter(to_filter(desc.filter));
sd->setMagFilter(to_filter(desc.filter));
sd->setSAddressMode(to_address(desc.address));
sd->setTAddressMode(to_address(desc.address));
if (desc.use_mips) {
sd->setMipFilter(MTL::SamplerMipFilterLinear);
}
MTL::SamplerState *state = device.handle->newSamplerState(sd);
sd->release();
if (!state) {
VEL_ERROR("Failed to create Metal sampler state");
return false;
}
sampler.handle = state;
if (!desc.name.empty()) {
state->setLabel(NS::String::string(desc.name.c_str(), NS::UTF8StringEncoding));
}
sampler.slot = mt::write_sampler(device, sampler);
return true;
}
u64 handle_id(Device &device, Sampler &sampler) {
if (sampler.slot == UINT64_MAX) {
VEL_ERROR("handle_id: sampler carries no heap slot");
return 0;
}
return mt::heap_sampler_id(device, sampler.slot);
}
void destroy_sampler(Device &device, Sampler &sampler) {
mt::free_sampler(device, sampler.slot);
sampler.slot = UINT64_MAX;
if (sampler.handle) {
sampler.handle->release();
sampler.handle = nullptr;
}
}
bool valid(const Sampler &sampler) {
return sampler.handle != nullptr;
}
} // namespace rhi