1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
// 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 <cassert>
#include <cstdio>
#include <cstring>
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<uint32_t>(width), static_cast<uint32_t>(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<MapState*>(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<uint8_t> OffscreenRenderTarget::read_pixels() {
#if !defined(STRIP_ALL)
return read_texture_pixels(instance_, device_, texture_, width_, height_);
#else
return std::vector<uint8_t>(); // Should never be called in STRIP_ALL builds
#endif
}
|