// This file is part of the 64k demo project. // It implements offscreen rendering for headless GPU testing. // Provides pixel readback for validation. #include "offscreen_render_target.h" #include "gpu/texture_readback.h" #include #include #include OffscreenRenderTarget::OffscreenRenderTarget(WGPUInstance instance, WGPUDevice device, int width, int height, WGPUTextureFormat format) : instance_(instance), device_(device), width_(width), height_(height), format_(format) { // Create offscreen texture const WGPUTextureDescriptor texture_desc = { .usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc, .dimension = WGPUTextureDimension_2D, .size = {static_cast(width), static_cast(height), 1}, .format = format, .mipLevelCount = 1, .sampleCount = 1, }; texture_ = wgpuDeviceCreateTexture(device_, &texture_desc); assert(texture_ && "Failed to create offscreen texture"); // Create texture view const WGPUTextureViewDescriptor view_desc = { .format = format, .dimension = WGPUTextureViewDimension_2D, .baseMipLevel = 0, .mipLevelCount = 1, .baseArrayLayer = 0, .arrayLayerCount = 1, }; view_ = wgpuTextureCreateView(texture_, &view_desc); assert(view_ && "Failed to create offscreen texture view"); } OffscreenRenderTarget::~OffscreenRenderTarget() { if (view_) { wgpuTextureViewRelease(view_); } if (texture_) { wgpuTextureRelease(texture_); } } void OffscreenRenderTarget::map_callback(WGPUMapAsyncStatus status, void* userdata) { MapState* state = static_cast(userdata); state->status = status; state->done = true; } WGPUBuffer OffscreenRenderTarget::create_staging_buffer() { const size_t buffer_size = width_ * height_ * 4; // BGRA8 = 4 bytes/pixel const WGPUBufferDescriptor buffer_desc = { .usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead, .size = buffer_size, }; return wgpuDeviceCreateBuffer(device_, &buffer_desc); } std::vector OffscreenRenderTarget::read_pixels() { #if !defined(STRIP_ALL) return read_texture_pixels(instance_, device_, texture_, width_, height_); #else return std::vector(); // Should never be called in STRIP_ALL builds #endif }