// This file is part of the 64k demo project. // It implements the TextureManager. #include "gpu/texture_manager.h" #include #include #if defined(DEMO_CROSS_COMPILE_WIN32) // Old API #define WGPU_TEX_COPY_INFO WGPUImageCopyTexture #define WGPU_TEX_DATA_LAYOUT WGPUTextureDataLayout #else // New API #define WGPU_TEX_COPY_INFO WGPUTexelCopyTextureInfo #define WGPU_TEX_DATA_LAYOUT WGPUTexelCopyBufferLayout #endif void TextureManager::init(WGPUDevice device, WGPUQueue queue) { device_ = device; queue_ = queue; } void TextureManager::shutdown() { for (auto& pair : textures_) { wgpuTextureViewRelease(pair.second.view); wgpuTextureRelease(pair.second.texture); } textures_.clear(); } void TextureManager::create_procedural_texture( const std::string& name, const ProceduralTextureDef& def) { // 1. Generate Data on CPU std::vector pixel_data; pixel_data.resize(def.width * def.height * 4); def.gen_func(pixel_data.data(), def.width, def.height, def.params.data(), (int)def.params.size()); create_texture(name, def.width, def.height, pixel_data.data()); #if !defined(STRIP_ALL) std::cout << "Generated procedural texture: " << name << " (" << def.width << "x" << def.height << ")" << std::endl; #endif } void TextureManager::create_texture(const std::string& name, int width, int height, const uint8_t* data) { WGPUExtent3D tex_size = {(uint32_t)width, (uint32_t)height, 1}; // 2. Create GPU Texture WGPUTextureDescriptor tex_desc = {}; tex_desc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst; tex_desc.dimension = WGPUTextureDimension_2D; tex_desc.size = tex_size; tex_desc.format = WGPUTextureFormat_RGBA8Unorm; tex_desc.mipLevelCount = 1; tex_desc.sampleCount = 1; #if defined(DEMO_CROSS_COMPILE_WIN32) tex_desc.label = nullptr; #else tex_desc.label = {nullptr, 0}; #endif WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc); // 3. Upload Data WGPU_TEX_COPY_INFO destination = {}; destination.texture = texture; destination.mipLevel = 0; destination.origin = {0, 0, 0}; destination.aspect = WGPUTextureAspect_All; WGPU_TEX_DATA_LAYOUT source_layout = {}; source_layout.offset = 0; source_layout.bytesPerRow = width * 4; source_layout.rowsPerImage = height; wgpuQueueWriteTexture(queue_, &destination, data, width * height * 4, &source_layout, &tex_size); // 4. Create View WGPUTextureViewDescriptor view_desc = {}; view_desc.format = WGPUTextureFormat_RGBA8Unorm; view_desc.dimension = WGPUTextureViewDimension_2D; view_desc.baseMipLevel = 0; view_desc.mipLevelCount = 1; view_desc.baseArrayLayer = 0; view_desc.arrayLayerCount = 1; view_desc.aspect = WGPUTextureAspect_All; WGPUTextureView view = wgpuTextureCreateView(texture, &view_desc); // 5. Store GpuTexture gpu_tex; gpu_tex.texture = texture; gpu_tex.view = view; gpu_tex.width = width; gpu_tex.height = height; textures_[name] = gpu_tex; } WGPUTextureView TextureManager::get_texture_view(const std::string& name) { auto it = textures_.find(name); if (it != textures_.end()) { return it->second.view; } return nullptr; }