diff options
Diffstat (limited to 'intern/cycles/hydra/output_driver.cpp')
-rw-r--r-- | intern/cycles/hydra/output_driver.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/intern/cycles/hydra/output_driver.cpp b/intern/cycles/hydra/output_driver.cpp new file mode 100644 index 00000000000..c5f64ac1c18 --- /dev/null +++ b/intern/cycles/hydra/output_driver.cpp @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2022 NVIDIA Corporation + * Copyright 2022 Blender Foundation */ + +#include "hydra/output_driver.h" +#include "hydra/render_buffer.h" +#include "hydra/session.h" + +HDCYCLES_NAMESPACE_OPEN_SCOPE + +HdCyclesOutputDriver::HdCyclesOutputDriver(HdCyclesSession *renderParam) + : _renderParam(renderParam) +{ +} + +void HdCyclesOutputDriver::write_render_tile(const Tile &tile) +{ + update_render_tile(tile); + + // Update convergence state of all render buffers + for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) { + if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) { + renderBuffer->SetConverged(true); + } + } +} + +bool HdCyclesOutputDriver::update_render_tile(const Tile &tile) +{ + std::vector<float> pixels; + + for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) { + if (aovBinding == _renderParam->GetDisplayAovBinding()) { + continue; // Display AOV binding is already updated by Cycles display driver + } + + if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) { + const HdFormat format = renderBuffer->GetFormat(); + if (format == HdFormatInvalid) { + continue; // Skip invalid AOV bindings + } + + const size_t channels = HdGetComponentCount(format); + // Avoid extra copy by mapping render buffer directly when dimensions/format match the tile + if (tile.offset.x == 0 && tile.offset.y == 0 && tile.size.x == renderBuffer->GetWidth() && + tile.size.y == renderBuffer->GetHeight() && + (format >= HdFormatFloat32 && format <= HdFormatFloat32Vec4)) { + float *const data = static_cast<float *>(renderBuffer->Map()); + TF_VERIFY(tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, data)); + renderBuffer->Unmap(); + } + else { + pixels.resize(channels * tile.size.x * tile.size.y); + if (tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, pixels.data())) { + const bool isId = aovBinding.aovName == HdAovTokens->primId || + aovBinding.aovName == HdAovTokens->elementId || + aovBinding.aovName == HdAovTokens->instanceId; + + renderBuffer->WritePixels(pixels.data(), + GfVec2i(tile.offset.x, tile.offset.y), + GfVec2i(tile.size.x, tile.size.y), + channels, + isId); + } + else { + // Do not warn on missing elementId, which is a standard AOV but is not implememted + if (aovBinding.aovName != HdAovTokens->elementId) { + TF_RUNTIME_ERROR("Could not find pass for AOV '%s'", aovBinding.aovName.GetText()); + } + } + } + } + } + + return true; +} + +HDCYCLES_NAMESPACE_CLOSE_SCOPE |