5#include "zeroerr/assert.h"
14 ASSERT(owner !=
nullptr);
17 if (!owner)
throw Exception(
"OffscreenCanvas: null owner");
21 const vk::Format format =
22 hdr ? vk::Format::eR16G16B16A16Sfloat : vk::Format::eR8G8B8A8Unorm;
28 vkb::SamplerBuilder sb;
29 sampleGpu.
sampler = sb.magFilter(vk::Filter::eNearest)
30 .minFilter(vk::Filter::eNearest)
31 .addressModeU(vk::SamplerAddressMode::eClampToEdge)
32 .addressModeV(vk::SamplerAddressMode::eClampToEdge)
35 auto sets = vkb::DescriptorSetBuilder()
42 vkb::UnboundSet unbound{sets[0]};
43 vkb::DescriptorSetUpdater updater;
44 updater.beginDescriptorSet(unbound)
45 .beginImages(0, 0, vk::DescriptorType::eCombinedImageSampler)
46 .image(vkb::SampledImage::forLaterSample(sampleGpu.
sampler, color.imageView()))
47 .beginImages(1, 0, vk::DescriptorType::eCombinedImageSampler)
48 .image(vkb::SampledImage::forLaterSample(sampleGpu.
sampler, color.imageView()))
64 device->destroyFramebuffer(fb);
68 device->destroyFramebuffer(fb3D);
79 bool v = hasPendingClear;
80 hasPendingClear =
false;
90 device, uint32_t(width), uint32_t(height), {color.asAttachment(), depth.asAttachment()});
94 clearColor = colorOpt.value_or(
Color(0.f, 0.f, 0.f, 1.f));
95 hasPendingClear =
true;
98void OffscreenCanvas::readAllPixels(std::vector<uint8_t> &outRgba) {
99 if (hdr)
throw Exception(
"HDR Canvas pixel readback requires an explicit tone-map pass");
103 const vk::DeviceSize byteSize = vk::DeviceSize(width) * vk::DeviceSize(height) * 4;
104 vkb::GenericBuffer staging(
device, vk::BufferUsageFlagBits::eTransferDst, byteSize,
105 vk::MemoryPropertyFlagBits::eHostVisible |
106 vk::MemoryPropertyFlagBits::eHostCoherent);
109 device.getQueue(vkb::QueueType::graphics), [&](vk::CommandBuffer cb) {
110 color.setLayout(cb, vk::ImageLayout::eTransferSrcOptimal);
111 vk::BufferImageCopy region{};
112 region.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0, 0, 1};
113 region.imageExtent = vk::Extent3D{uint32_t(width), uint32_t(height), 1};
114 cb.copyImageToBuffer(color.image(), vk::ImageLayout::eTransferSrcOptimal,
115 staging.buffer, region);
116 color.setLayout(cb, vk::ImageLayout::eShaderReadOnlyOptimal);
119 outRgba.resize(
size_t(byteSize));
120 void *mapped = staging.map();
123 std::memcpy(outRgba.data(), mapped,
size_t(byteSize));
128void OffscreenCanvas::readAllHDRPixels(std::vector<uint8_t> &outRgba16f) {
129 if (!hdr)
throw Exception(
"Canvas is not an HDR render target");
130 auto &
device = owner->getDevice();
133 const vk::DeviceSize byteSize = vk::DeviceSize(
width) * vk::DeviceSize(
height) * 8;
134 vkb::GenericBuffer staging(
device, vk::BufferUsageFlagBits::eTransferDst, byteSize,
135 vk::MemoryPropertyFlagBits::eHostVisible |
136 vk::MemoryPropertyFlagBits::eHostCoherent);
138 vkb::executeImmediately(
device.instance, owner->getUploadPool(),
139 device.getQueue(vkb::QueueType::graphics), [&](vk::CommandBuffer cb) {
140 color.setLayout(cb, vk::ImageLayout::eTransferSrcOptimal);
141 vk::BufferImageCopy region{};
142 region.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0, 0, 1};
143 region.imageExtent = vk::Extent3D{uint32_t(
width), uint32_t(
height), 1};
144 cb.copyImageToBuffer(
color.image(), vk::ImageLayout::eTransferSrcOptimal,
145 staging.buffer, region);
146 color.setLayout(cb, vk::ImageLayout::eShaderReadOnlyOptimal);
149 outRgba16f.resize(
size_t(byteSize));
150 void *mapped = staging.map();
151 std::memcpy(outRgba16f.data(), mapped,
size_t(byteSize));
156Color OffscreenCanvas::getPixel(
int x,
int y) {
162 throw Exception(
"OffscreenCanvas::getPixel: out of bounds (%d,%d)",
x,
y);
163 std::vector<uint8_t>
px;
165 size_t i = (size_t(
y) * size_t(
width) + size_t(
x)) * 4;
166 return Color(
px[i + 0] / 255.f,
px[i + 1] / 255.f,
px[i + 2] / 255.f,
px[i + 3] / 255.f);
170 std::vector<uint8_t>
px;
173 std::memcpy(img->getData(),
px.data(),
px.size());
178 if (!hdr)
return nullptr;
179 std::vector<uint8_t>
px;
180 readAllHDRPixels(
px);
182 std::memcpy(img->getData(),
px.data(),
px.size());
EVENGINE_API_FOUNDATION public API.
EVENGINE_API_BACKENDS public API.
vk::CommandPool getUploadPool() const
Returns the upload pool.
const vkb::BuiltRenderPass & getOffscreenRenderPass(bool hdr=false) const
Returns the offscreen render pass.
vk::DescriptorSetLayout getTexSetLayout() const
Returns the tex set layout.
const vkb::BuiltRenderPass & getOffscreen3DRenderPass(bool hdr=false)
Returns the offscreen 3 d render pass.
vkb::Device & getDevice()
Returns the device.
vk::Format getDepthFormat() const
Returns the depth format.
vk::DescriptorPool getDescriptorPool() const
Returns the descriptor pool.
~OffscreenCanvas() override
Releases OffscreenCanvas resources.
void clear(std::optional< Color > color, std::optional< int > stencil, std::optional< double > depth) override
Clears .
OffscreenCanvas(Graphics *owner, int width, int height, bool hdr=false)
Constructs a OffscreenCanvas.
bool takePendingClear()
Take pending clear.
void ensure3D()
Ensure a D32 depth attachment + 3D (color+depth) framebuffer exist.
Represents raw pixel data.
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
vk::ImageView viewOverride
vkb::BoundSet descriptorSet