Upload document frame faces through renderer API
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "paint_renderer/compositor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
@@ -105,6 +106,24 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] std::byte rgba8_channel(float value) noexcept
|
||||
{
|
||||
const auto clamped = std::clamp(value, 0.0F, 1.0F);
|
||||
return static_cast<std::byte>(static_cast<std::uint8_t>(clamped * 255.0F + 0.5F));
|
||||
}
|
||||
|
||||
void append_rgba8_bytes(std::vector<std::byte>& bytes, std::span<const pp::paint::Rgba> pixels)
|
||||
{
|
||||
bytes.clear();
|
||||
bytes.reserve(pixels.size() * pp::document::rgba8_components);
|
||||
for (const auto& pixel : pixels) {
|
||||
bytes.push_back(rgba8_channel(pixel.r));
|
||||
bytes.push_back(rgba8_channel(pixel.g));
|
||||
bytes.push_back(rgba8_channel(pixel.b));
|
||||
bytes.push_back(rgba8_channel(pixel.a));
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status composite_face_payload(
|
||||
std::span<pp::paint::Rgba> destination,
|
||||
pp::renderer::Extent2D extent,
|
||||
@@ -327,6 +346,72 @@ pp::foundation::Result<DocumentFrameCompositeResult> composite_document_frame(
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentFrameUploadResult> upload_document_frame_faces(
|
||||
pp::renderer::IRenderDevice& device,
|
||||
DocumentFrameUploadRequest request)
|
||||
{
|
||||
auto composite = composite_document_frame(DocumentFrameCompositeRequest {
|
||||
.document = request.document,
|
||||
.frame_index = request.frame_index,
|
||||
.clear_color = request.clear_color,
|
||||
});
|
||||
if (!composite) {
|
||||
return pp::foundation::Result<DocumentFrameUploadResult>::failure(composite.status());
|
||||
}
|
||||
|
||||
DocumentFrameUploadResult result;
|
||||
result.composite = std::move(composite.value());
|
||||
std::vector<std::byte> upload_bytes;
|
||||
|
||||
for (std::size_t face_index = 0; face_index < result.composite.faces.size(); ++face_index) {
|
||||
const pp::renderer::TextureDesc desc {
|
||||
.extent = result.composite.extent,
|
||||
.format = pp::renderer::TextureFormat::rgba8,
|
||||
.usage = pp::renderer::TextureUsage::sampled
|
||||
| pp::renderer::TextureUsage::upload_destination
|
||||
| pp::renderer::TextureUsage::readback_source
|
||||
| pp::renderer::TextureUsage::copy_source,
|
||||
.debug_name = "document-frame-face",
|
||||
};
|
||||
auto texture = device.create_texture(desc);
|
||||
if (!texture) {
|
||||
return pp::foundation::Result<DocumentFrameUploadResult>::failure(texture.status());
|
||||
}
|
||||
|
||||
append_rgba8_bytes(upload_bytes, result.composite.faces[face_index].pixels);
|
||||
auto& context = device.immediate_context();
|
||||
const auto upload_status = context.upload_texture(
|
||||
*texture.value(),
|
||||
pp::renderer::ReadbackRegion {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = result.composite.extent.width,
|
||||
.height = result.composite.extent.height,
|
||||
},
|
||||
upload_bytes);
|
||||
if (!upload_status.ok()) {
|
||||
return pp::foundation::Result<DocumentFrameUploadResult>::failure(upload_status);
|
||||
}
|
||||
|
||||
result.uploaded_bytes += static_cast<std::uint64_t>(upload_bytes.size());
|
||||
if (request.transition_to_shader_read && device.features().explicit_texture_transitions) {
|
||||
const auto transition_status = context.transition_texture(
|
||||
*texture.value(),
|
||||
pp::renderer::TextureState::upload_destination,
|
||||
pp::renderer::TextureState::shader_read);
|
||||
if (!transition_status.ok()) {
|
||||
return pp::foundation::Result<DocumentFrameUploadResult>::failure(transition_status);
|
||||
}
|
||||
++result.transition_count;
|
||||
}
|
||||
|
||||
result.face_textures[face_index] = std::move(texture.value());
|
||||
++result.texture_count;
|
||||
}
|
||||
|
||||
return pp::foundation::Result<DocumentFrameUploadResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
bool stroke_composite_requires_feedback(
|
||||
pp::paint::BlendMode layer_blend_mode,
|
||||
pp::paint::StrokeBlendMode stroke_blend_mode,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
@@ -116,6 +117,21 @@ struct DocumentFrameCompositeResult {
|
||||
std::size_t face_payload_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentFrameUploadRequest {
|
||||
const pp::document::CanvasDocument* document = nullptr;
|
||||
std::size_t frame_index = 0;
|
||||
pp::paint::Rgba clear_color {};
|
||||
bool transition_to_shader_read = true;
|
||||
};
|
||||
|
||||
struct DocumentFrameUploadResult {
|
||||
DocumentFrameCompositeResult composite {};
|
||||
std::array<std::unique_ptr<pp::renderer::ITexture2D>, pp::document::cube_face_count> face_textures {};
|
||||
std::size_t texture_count = 0;
|
||||
std::size_t transition_count = 0;
|
||||
std::uint64_t uploaded_bytes = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] pp::foundation::Status composite_layer(
|
||||
std::span<pp::paint::Rgba> destination,
|
||||
pp::renderer::Extent2D extent,
|
||||
@@ -127,6 +143,10 @@ struct DocumentFrameCompositeResult {
|
||||
[[nodiscard]] pp::foundation::Result<DocumentFrameCompositeResult> composite_document_frame(
|
||||
DocumentFrameCompositeRequest request);
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<DocumentFrameUploadResult> upload_document_frame_faces(
|
||||
pp::renderer::IRenderDevice& device,
|
||||
DocumentFrameUploadRequest request);
|
||||
|
||||
[[nodiscard]] bool stroke_composite_requires_feedback(
|
||||
pp::paint::BlendMode layer_blend_mode,
|
||||
pp::paint::StrokeBlendMode stroke_blend_mode,
|
||||
|
||||
Reference in New Issue
Block a user