15#include <glm/gtc/packing.hpp>
16#include <glm/vec2.hpp>
17#include <glm/vec4.hpp>
53 if (status != wgpu::MapAsyncStatus::Success)
55 Log::Error(fmt::format(
"Failed to map buffer: {}", std::string_view(message.data, message.length)));
60 auto mapped =
static_cast<uint8_t *
>(buf.getMappedRange(0, buf.getSize()));
62 for (
size_t i = 0; i < size; i++)
72 case wgpu::TextureFormat::RGBA8UnormSrgb:
73 case wgpu::TextureFormat::RGBA8Unorm:
74 pixel.r = mapped[i * 4 + 0];
75 pixel.g = mapped[i * 4 + 1];
76 pixel.b = mapped[i * 4 + 2];
77 pixel.a = mapped[i * 4 + 3];
79 case wgpu::TextureFormat::BGRA8UnormSrgb:
80 case wgpu::TextureFormat::BGRA8Unorm:
81 pixel.b = mapped[i * 4 + 0];
82 pixel.g = mapped[i * 4 + 1];
83 pixel.r = mapped[i * 4 + 2];
84 pixel.a = mapped[i * 4 + 3];
86 case wgpu::TextureFormat::RGBA16Float: {
87 auto r = std::bit_cast<uint16_t>(std::array<uint8_t, 2>{mapped[i * 8 + 0], mapped[i * 8 + 1]});
88 auto g = std::bit_cast<uint16_t>(std::array<uint8_t, 2>{mapped[i * 8 + 2], mapped[i * 8 + 3]});
89 auto b = std::bit_cast<uint16_t>(std::array<uint8_t, 2>{mapped[i * 8 + 4], mapped[i * 8 + 5]});
90 auto a = std::bit_cast<uint16_t>(std::array<uint8_t, 2>{mapped[i * 8 + 6], mapped[i * 8 + 7]});
91 pixel.r =
static_cast<uint8_t
>(std::clamp(glm::unpackHalf1x16(r), 0.0f, 1.0f) * 255.0f);
92 pixel.g =
static_cast<uint8_t
>(std::clamp(glm::unpackHalf1x16(g), 0.0f, 1.0f) * 255.0f);
93 pixel.b =
static_cast<uint8_t
>(std::clamp(glm::unpackHalf1x16(b), 0.0f, 1.0f) * 255.0f);
94 pixel.a =
static_cast<uint8_t
>(std::clamp(glm::unpackHalf1x16(a), 0.0f, 1.0f) * 255.0f);
97 case wgpu::TextureFormat::Depth32Float: {
98 auto depth = std::bit_cast<float>(
99 std::array<uint8_t, 4>{mapped[i * 4 + 0], mapped[i * 4 + 1], mapped[i * 4 + 2], mapped[i * 4 + 3]});
100 auto depthByte =
static_cast<uint8_t
>(std::clamp(depth, 0.0f, 1.0f) * 255.0f);
101 pixel = glm::u8vec4(depthByte, depthByte, depthByte, 255);
106 data->data.pixels.push_back(pixel);
113 Texture(std::string_view name, wgpu::Texture texture,
bool ownsResources =
true)
120 :
Texture(std::string(descriptor.label.data, descriptor.label.length),
121 context.deviceContext.GetDevice()->createTexture(descriptor))
128 Write(context, image);
132 const std::function<glm::u8vec4(glm::uvec2 pos)> &callback)
152 other._webgpuTexture =
nullptr;
154 other._ownsResources =
false;
168 _name = std::move(other._name);
171 other._webgpuTexture =
nullptr;
173 other._ownsResources =
false;
183 if (image.
width != this->_webgpuTexture.getWidth() || image.
height != this->_webgpuTexture.getHeight())
185 Log::Warning(
"Image data size does not match texture size.");
189 wgpu::TexelCopyTextureInfo destination;
191 destination.mipLevel = 0;
192 destination.origin = {0, 0, 0};
193 destination.aspect = wgpu::TextureAspect::All;
195 wgpu::TexelCopyBufferLayout source;
197 source.bytesPerRow = image.
channels * textureSize.width;
198 source.rowsPerImage = textureSize.height;
200 const wgpu::Queue &queue = context.
queue.value();
201 const uint32_t rowBytes = source.bytesPerRow;
202 const uint32_t alignedRowBytes = (rowBytes + 255u) & ~255u;
203 if (alignedRowBytes == rowBytes)
205 queue.writeTexture(destination, image.
pixels.data(), rowBytes * source.rowsPerImage, source, textureSize);
209 std::vector<uint8_t> padded(alignedRowBytes * textureSize.height, 0u);
210 const auto *
const src =
reinterpret_cast<const std::byte *
>(image.
pixels.data());
211 for (uint32_t row = 0; row < textureSize.height; ++row)
213 std::memcpy(padded.data() + row * alignedRowBytes, src + row * rowBytes, rowBytes);
216 source.bytesPerRow = alignedRowBytes;
217 queue.writeTexture(destination, padded.data(), alignedRowBytes * source.rowsPerImage, source, textureSize);
231 const wgpu::Queue &queue = context.
queue.value();
237 const uint32_t bytesPerRow = (copySize.width *
_GetBytesPerPixel() + 255) / 256 * 256;
239 bufDesc.size = copySize.height * bytesPerRow;
240 bufDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
246 srcView.mipLevel = 0;
247 srcView.origin = {0, 0, 0};
248 if (
_webgpuTexture.getFormat() == wgpu::TextureFormat::Depth24Plus ||
249 _webgpuTexture.getFormat() == wgpu::TextureFormat::Depth24PlusStencil8 ||
250 _webgpuTexture.getFormat() == wgpu::TextureFormat::Depth32Float ||
251 _webgpuTexture.getFormat() == wgpu::TextureFormat::Depth32FloatStencil8)
253 srcView.aspect = wgpu::TextureAspect::DepthOnly;
256 srcView.aspect = wgpu::TextureAspect::All;
259 dstView.buffer = readbackBuffer;
260 dstView.layout.offset = 0;
261 dstView.layout.bytesPerRow = bytesPerRow;
262 dstView.layout.rowsPerImage = copySize.height;
264 encoder.copyTextureToBuffer(srcView, dstView, copySize);
265 auto cmd = encoder.finish();
267 auto cmdName = fmt::format(
"{} Readback Command",
_name);
268 queue.submit(1, &cmd);
277 cbInfo.mode = wgpu::CallbackMode::AllowSpontaneous;
279 cbInfo.userdata1 = &cbData;
280 cbInfo.userdata2 =
nullptr;
281 readbackBuffer.mapAsync(wgpu::MapMode::Read, 0, readbackBuffer.getSize(), cbInfo);
285 std::this_thread::sleep_for(std::chrono::milliseconds(100));
287 readbackBuffer.release();
312 textureDesc.dimension = wgpu::TextureDimension::_2D;
313 textureDesc.mipLevelCount = 1;
314 textureDesc.sampleCount = 1;
315 textureDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
316 textureDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment |
317 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
318 textureDesc.viewFormats =
nullptr;
319 textureDesc.viewFormatCount = 0;
Definition UnsupportedTextureFormatError.hpp:7
DeviceContext deviceContext
Definition Context.hpp:43
std::optional< wgpu::Queue > queue
Definition Context.hpp:44
Definition TextureView.hpp:21
Texture(const Context &context, const wgpu::TextureDescriptor &descriptor)
Definition Texture.hpp:119
Texture & operator=(Texture &&other) noexcept
Definition Texture.hpp:157
wgpu::Texture _webgpuTexture
Definition Texture.hpp:325
Texture & operator=(const Texture &)=delete
static wgpu::TextureDescriptor _BuildDescriptor(std::string_view name, const Image &image)
Definition Texture.hpp:307
bool OwnsResources() const
Definition Texture.hpp:302
std::string _name
Definition Texture.hpp:327
void TakeOwnership()
Definition Texture.hpp:300
void Write(const Context &context, const Image &image)
Definition Texture.hpp:181
Texture(std::string_view name, wgpu::Texture texture, bool ownsResources=true)
Definition Texture.hpp:113
Texture(const Texture &)=delete
uint32_t _GetBytesPerPixel() const
Definition Texture.hpp:323
Texture(Texture &&other) noexcept
Definition Texture.hpp:148
bool _ownsResources
Definition Texture.hpp:328
const Resource::TextureView & GetDefaultView() const
Definition Texture.hpp:291
Texture(const Context &context, std::string_view name, const glm::uvec2 &size, const std::function< glm::u8vec4(glm::uvec2 pos)> &callback)
Definition Texture.hpp:131
Resource::TextureView _defaultView
Definition Texture.hpp:326
Image RetrieveImage(const Context &context) const
Reads back the GPU texture and returns it as an Image.
Definition Texture.hpp:229
Texture(const Context &context, std::string_view name, const Image &image)
Definition Texture.hpp:125
glm::uvec2 GetSize() const
Definition Texture.hpp:178
void ReleaseOwnership()
Definition Texture.hpp:298
~Texture()
Definition Texture.hpp:137
Resource::TextureView CreateView(const wgpu::TextureViewDescriptor &descriptor) const
Definition Texture.hpp:293
Definition AGPUBuffer.hpp:6
static void TextureRetrieveCallback(WGPUMapAsyncStatus status, WGPUStringView message, void *userdata1, void *userdata2)
Callback invoked when a readback buffer mapping completes; converts mapped texture data into RGBA8 pi...
Definition Texture.hpp:50
uint32_t GetBytesPerPixel(wgpu::TextureFormat format)
Determines the number of bytes per pixel for a given wgpu texture format.
Definition GetBytesPerPixel.cpp:13
void Error(const T &msg) noexcept(false)
Definition Logger.hpp:34
void Warning(const T &msg) noexcept(false)
Definition Logger.hpp:32
constexpr DefaultFlag Default
Definition webgpu.hpp:78
StringView(const std::string_view &cpp)
Definition webgpu.hpp:618
Extent3D(uint32_t width, uint32_t height, uint32_t depthOrArrayLayers)
Definition webgpu.hpp:643
Definition Texture.hpp:22
bool done
Definition Texture.hpp:27
Image data
Definition Texture.hpp:24
uint32_t bytesPerRow
Definition Texture.hpp:25
wgpu::TextureFormat format
Definition Texture.hpp:26
wgpu::Buffer buffer
Definition Texture.hpp:23
auto & GetDevice()
Definition DeviceContext.hpp:13
uint32_t height
Definition Image.hpp:20
uint32_t width
Definition Image.hpp:19
int channels
Definition Image.hpp:21
std::vector< glm::u8vec4 > pixels
Definition Image.hpp:22