// Sampler cache - deduplicates samplers across effects #pragma once #include // Forward declarations (users must include gpu.h) struct WGPUDeviceImpl; typedef struct WGPUDeviceImpl* WGPUDevice; struct WGPUSamplerImpl; typedef struct WGPUSamplerImpl* WGPUSampler; #include "platform/platform.h" struct SamplerSpec { WGPUAddressMode u, v; WGPUFilterMode mag, min; uint16_t anisotropy; bool operator<(const SamplerSpec& o) const { if (u != o.u) return u < o.u; if (v != o.v) return v < o.v; if (mag != o.mag) return mag < o.mag; if (min != o.min) return min < o.min; return anisotropy < o.anisotropy; } }; class SamplerCache { std::map cache_; SamplerCache() = default; public: static SamplerCache& Get() { static SamplerCache instance; return instance; } WGPUSampler get_or_create(WGPUDevice device, const SamplerSpec& spec) { auto it = cache_.find(spec); if (it != cache_.end()) return it->second; WGPUSamplerDescriptor desc{}; desc.addressModeU = spec.u; desc.addressModeV = spec.v; desc.magFilter = spec.mag; desc.minFilter = spec.min; desc.maxAnisotropy = spec.anisotropy; WGPUSampler sampler = wgpuDeviceCreateSampler(device, &desc); cache_[spec] = sampler; return sampler; } // Common presets static SamplerSpec linear() { return {WGPUAddressMode_Repeat, WGPUAddressMode_Repeat, WGPUFilterMode_Linear, WGPUFilterMode_Linear, 1}; } static SamplerSpec clamp() { return {WGPUAddressMode_ClampToEdge, WGPUAddressMode_ClampToEdge, WGPUFilterMode_Linear, WGPUFilterMode_Linear, 1}; } };