1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2017-2018 Esteban Tovagliari, The appleseedhq Organization
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28
29 // Interface header.
30 #include "aovaccumulator.h"
31
32 // appleseed.renderer headers.
33 #include "renderer/global/globaltypes.h"
34 #include "renderer/modeling/aov/aov.h"
35 #include "renderer/modeling/frame/frame.h"
36
37 // appleseed.foundation headers.
38 #include "foundation/image/canvasproperties.h"
39 #include "foundation/image/image.h"
40 #include "foundation/image/tile.h"
41
42 // Standard headers.
43 #include <cassert>
44 #include <cstring>
45
46 using namespace foundation;
47 using namespace std;
48
49 namespace renderer
50 {
51
52 //
53 // AOVAccumulator class implementation.
54 //
55
~AOVAccumulator()56 AOVAccumulator::~AOVAccumulator()
57 {
58 }
59
release()60 void AOVAccumulator::release()
61 {
62 delete this;
63 }
64
on_tile_begin(const Frame & frame,const size_t tile_x,const size_t tile_y,const size_t max_spp)65 void AOVAccumulator::on_tile_begin(
66 const Frame& frame,
67 const size_t tile_x,
68 const size_t tile_y,
69 const size_t max_spp)
70 {
71 }
72
on_tile_end(const Frame & frame,const size_t tile_x,const size_t tile_y)73 void AOVAccumulator::on_tile_end(
74 const Frame& frame,
75 const size_t tile_x,
76 const size_t tile_y)
77 {
78 }
79
on_pixel_begin(const Vector2i & pi)80 void AOVAccumulator::on_pixel_begin(
81 const Vector2i& pi)
82 {
83 }
84
on_pixel_end(const Vector2i & pi)85 void AOVAccumulator::on_pixel_end(
86 const Vector2i& pi)
87 {
88 }
89
on_sample_begin(const PixelContext & pixel_context)90 void AOVAccumulator::on_sample_begin(
91 const PixelContext& pixel_context)
92 {
93 }
94
on_sample_end(const PixelContext & pixel_context)95 void AOVAccumulator::on_sample_end(
96 const PixelContext& pixel_context)
97 {
98 }
99
write(const PixelContext & pixel_context,const ShadingPoint & shading_point,const ShadingComponents & shading_components,const AOVComponents & aov_components,ShadingResult & shading_result)100 void AOVAccumulator::write(
101 const PixelContext& pixel_context,
102 const ShadingPoint& shading_point,
103 const ShadingComponents& shading_components,
104 const AOVComponents& aov_components,
105 ShadingResult& shading_result)
106 {
107 }
108
109
110 //
111 // UnfilteredAOVAccumulator class implementation.
112 //
113
UnfilteredAOVAccumulator(Image & image)114 UnfilteredAOVAccumulator::UnfilteredAOVAccumulator(Image& image)
115 : m_image(image)
116 , m_tile(nullptr)
117 {
118 }
119
on_tile_begin(const Frame & frame,const size_t tile_x,const size_t tile_y,const size_t max_spp)120 void UnfilteredAOVAccumulator::on_tile_begin(
121 const Frame& frame,
122 const size_t tile_x,
123 const size_t tile_y,
124 const size_t max_spp)
125 {
126 // Fetch the destination tile.
127 m_tile = &m_image.tile(tile_x, tile_y);
128
129 // Compute the tile's origin and cropped bounding box (inclusive on all sides).
130 const CanvasProperties& props = frame.image().properties();
131 m_tile_origin_x = tile_x * props.m_tile_width;
132 m_tile_origin_y = tile_y * props.m_tile_height;
133 m_cropped_tile_bbox.min.x = static_cast<int>(m_tile_origin_x);
134 m_cropped_tile_bbox.min.y = static_cast<int>(m_tile_origin_y);
135 m_cropped_tile_bbox.max.x = static_cast<int>(m_tile_origin_x + m_tile->get_width() - 1);
136 m_cropped_tile_bbox.max.y = static_cast<int>(m_tile_origin_y + m_tile->get_height() - 1);
137 assert(m_cropped_tile_bbox.is_valid());
138
139 // Clip the tile's bounding box against the crop window.
140 m_cropped_tile_bbox = AABB2i::intersect(m_cropped_tile_bbox, frame.get_crop_window());
141 assert(m_cropped_tile_bbox.is_valid());
142 }
143
on_tile_end(const Frame & frame,const size_t tile_x,const size_t tile_y)144 void UnfilteredAOVAccumulator::on_tile_end(
145 const Frame& frame,
146 const size_t tile_x,
147 const size_t tile_y)
148 {
149 m_tile = nullptr;
150 }
151
152
153 //
154 // AOVAccumulatorContainer class implementation.
155 //
156
AOVAccumulatorContainer()157 AOVAccumulatorContainer::AOVAccumulatorContainer()
158 {
159 init();
160 }
161
AOVAccumulatorContainer(const Frame & frame)162 AOVAccumulatorContainer::AOVAccumulatorContainer(const Frame& frame)
163 {
164 init();
165
166 // Create accumulators for AOVs.
167 for (size_t i = 0, e = frame.aovs().size(); i < e; ++i)
168 {
169 const AOV* aov = frame.aovs().get_by_index(i);
170 insert(aov->create_accumulator());
171 }
172
173 // Create accumulators for internal AOVs.
174 for (size_t i = 0, e = frame.internal_aovs().size(); i < e; ++i)
175 {
176 const AOV* aov = frame.internal_aovs().get_by_index(i);
177 insert(aov->create_accumulator());
178 }
179 }
180
init()181 void AOVAccumulatorContainer::init()
182 {
183 m_size = 0;
184 memset(m_accumulators, 0, MaxAOVAccumulatorCount * sizeof(AOVAccumulator*));
185 }
186
~AOVAccumulatorContainer()187 AOVAccumulatorContainer::~AOVAccumulatorContainer()
188 {
189 for (size_t i = 0, e = m_size; i < e; ++i)
190 delete m_accumulators[i];
191 }
192
on_tile_begin(const Frame & frame,const size_t tile_x,const size_t tile_y,const size_t max_spp)193 void AOVAccumulatorContainer::on_tile_begin(
194 const Frame& frame,
195 const size_t tile_x,
196 const size_t tile_y,
197 const size_t max_spp)
198 {
199 for (size_t i = 0, e = m_size; i < e; ++i)
200 m_accumulators[i]->on_tile_begin(frame, tile_x, tile_y, max_spp);
201 }
202
on_tile_end(const Frame & frame,const size_t tile_x,const size_t tile_y)203 void AOVAccumulatorContainer::on_tile_end(
204 const Frame& frame,
205 const size_t tile_x,
206 const size_t tile_y)
207 {
208 for (size_t i = 0, e = m_size; i < e; ++i)
209 m_accumulators[i]->on_tile_end(frame, tile_x, tile_y);
210 }
211
on_pixel_begin(const Vector2i & pi)212 void AOVAccumulatorContainer::on_pixel_begin(
213 const Vector2i& pi)
214 {
215 for (size_t i = 0, e = m_size; i < e; ++i)
216 m_accumulators[i]->on_pixel_begin(pi);
217 }
218
on_pixel_end(const Vector2i & pi)219 void AOVAccumulatorContainer::on_pixel_end(
220 const Vector2i& pi)
221 {
222 for (size_t i = 0, e = m_size; i < e; ++i)
223 m_accumulators[i]->on_pixel_end(pi);
224 }
225
on_sample_begin(const PixelContext & pixel_context)226 void AOVAccumulatorContainer::on_sample_begin(
227 const PixelContext& pixel_context)
228 {
229 for (size_t i = 0, e = m_size; i < e; ++i)
230 m_accumulators[i]->on_sample_begin(pixel_context);
231 }
232
on_sample_end(const PixelContext & pixel_context)233 void AOVAccumulatorContainer::on_sample_end(
234 const PixelContext& pixel_context)
235 {
236 for (size_t i = 0, e = m_size; i < e; ++i)
237 m_accumulators[i]->on_sample_end(pixel_context);
238 }
239
write(const PixelContext & pixel_context,const ShadingPoint & shading_point,const ShadingComponents & shading_components,const AOVComponents & aov_components,ShadingResult & shading_result)240 void AOVAccumulatorContainer::write(
241 const PixelContext& pixel_context,
242 const ShadingPoint& shading_point,
243 const ShadingComponents& shading_components,
244 const AOVComponents& aov_components,
245 ShadingResult& shading_result)
246 {
247 for (size_t i = 0, e = m_size; i < e; ++i)
248 {
249 m_accumulators[i]->write(
250 pixel_context,
251 shading_point,
252 shading_components,
253 aov_components,
254 shading_result);
255 }
256 }
257
insert(auto_release_ptr<AOVAccumulator> aov_accum)258 bool AOVAccumulatorContainer::insert(auto_release_ptr<AOVAccumulator> aov_accum)
259 {
260 assert(aov_accum.get());
261
262 if (m_size + 1 == MaxAOVAccumulatorCount)
263 return false;
264
265 m_accumulators[m_size++] = aov_accum.release();
266 return true;
267 }
268
269 } // namespace renderer
270