summaryrefslogtreecommitdiff
path: root/src/tests/common/offscreen_render_target.cc
blob: 10775a1dad9c2e608f1f9721662e9899fb919f3c (plain)
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
}