Welcome to mirror list, hosted at ThFree Co, Russian Federation.

path_trace_display.h « integrator « cycles « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 24aaa0df6b1c38d2a7cecd8f21e6f4b85902d190 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
 * Copyright 2021 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "render/display_driver.h"

#include "util/util_half.h"
#include "util/util_thread.h"
#include "util/util_types.h"
#include "util/util_unique_ptr.h"

CCL_NAMESPACE_BEGIN

class BufferParams;

/* PathTraceDisplay is used for efficient render buffer display.
 *
 * The host applications implements a DisplayDriver, storing a render pass in a GPU-side
 * textures. This texture is continuously updated by the path tracer and drawn by the host
 * application.
 *
 * PathTraceDisplay is a wrapper around the DisplayDriver, adding thread safety, state tracking
 * and error checking. */

class PathTraceDisplay {
 public:
  PathTraceDisplay(unique_ptr<DisplayDriver> driver);
  virtual ~PathTraceDisplay() = default;

  /* Reset the display for the new state of render session. Is called whenever session is reset,
   * which happens on changes like viewport navigation or viewport dimension change.
   *
   * This call will configure parameters for a changed buffer and reset the texture state. */
  void reset(const BufferParams &buffer_params);

  /* --------------------------------------------------------------------
   * Update procedure.
   *
   * These calls indicates a desire of the caller to update content of the displayed texture. */

  /* Returns true when update is ready. Update should be finished with update_end().
   *
   * If false is returned then no update is possible, and no update_end() call is needed.
   *
   * The texture width and height denotes an actual resolution of the underlying render result. */
  bool update_begin(int texture_width, int texture_height);

  void update_end();

  /* Get currently configured texture size of the display (as configured by `update_begin()`. */
  int2 get_texture_size() const;

  /* --------------------------------------------------------------------
   * Texture update from CPU buffer.
   *
   * NOTE: The PathTraceDisplay should be marked for an update being in process with
   * `update_begin()`.
   *
   * Most portable implementation, which must be supported by all platforms. Might not be the most
   * efficient one.
   */

  /* Copy buffer of rendered pixels of a given size into a given position of the texture.
   *
   * This function does not acquire a lock. The reason for this is is to allow use of this function
   * for partial updates from different devices. In this case the caller will acquire the lock
   * once, update all the slices and release
   * the lock once. This will ensure that draw() will never use partially updated texture. */
  void copy_pixels_to_texture(
      const half4 *rgba_pixels, int texture_x, int texture_y, int pixels_width, int pixels_height);

  /* --------------------------------------------------------------------
   * Texture buffer mapping.
   *
   * This functionality is used to update GPU-side texture content without need to maintain CPU
   * side buffer on the caller.
   *
   * NOTE: The PathTraceDisplay should be marked for an update being in process with
   * `update_begin()`.
   *
   * NOTE: Texture buffer can not be mapped while graphics interoperability is active. This means
   * that `map_texture_buffer()` is not allowed between `graphics_interop_begin()` and
   * `graphics_interop_end()` calls.
   */

  /* Map pixels memory form texture to a buffer available for write from CPU. Width and height will
   * define a requested size of the texture to write to.
   * Upon success a non-null pointer is returned and the texture buffer is to be unmapped.
   * If an error happens during mapping, or if mapping is not supported by this GPU display a
   * null pointer is returned and the buffer is NOT to be unmapped.
   *
   * NOTE: Usually the implementation will rely on a GPU context of some sort, and the GPU context
   * is often can not be bound to two threads simultaneously, and can not be released from a
   * different thread. This means that the mapping API should be used from the single thread only,
   */
  half4 *map_texture_buffer();
  void unmap_texture_buffer();

  /* --------------------------------------------------------------------
   * Graphics interoperability.
   *
   * A special code path which allows to update texture content directly from the GPU compute
   * device. Complementary part of DeviceGraphicsInterop.
   *
   * NOTE: Graphics interoperability can not be used while the texture buffer is mapped. This means
   * that `graphics_interop_get()` is not allowed between `map_texture_buffer()` and
   * `unmap_texture_buffer()` calls. */

  /* Get PathTraceDisplay graphics interoperability information which acts as a destination for the
   * device API. */
  DisplayDriver::GraphicsInterop graphics_interop_get();

  /* (De)activate GPU display for graphics interoperability outside of regular display update
   * routines. */
  void graphics_interop_activate();
  void graphics_interop_deactivate();

  /* --------------------------------------------------------------------
   * Drawing.
   */

  /* Clear the texture by filling it with all zeroes.
   *
   * This call might happen in parallel with draw, but can never happen in parallel with the
   * update.
   *
   * The actual zeroing can be deferred to a later moment. What is important is that after clear
   * and before pixels update the drawing texture will be fully empty, and that partial update
   * after clear will write new pixel values for an updating area, leaving everything else zeroed.
   *
   * If the GPU display supports graphics interoperability then the zeroing the display is to be
   * delegated to the device via the `DisplayDriver::GraphicsInterop`. */
  void clear();

  /* Draw the current state of the texture.
   *
   * Returns true if this call did draw an updated state of the texture. */
  bool draw();

 private:
  /* Display driver implemented by the host application. */
  unique_ptr<DisplayDriver> driver_;

  /* Current display parameters */
  thread_mutex mutex_;
  DisplayDriver::Params params_;

  /* Mark texture as its content has been updated.
   * Used from places which knows that the texture content has been brought up-to-date, so that the
   * drawing knows whether it can be performed, and whether drawing happened with an up-to-date
   * texture state. */
  void mark_texture_updated();

  /* State of the update process. */
  struct {
    /* True when update is in process, indicated by `update_begin()` / `update_end()`. */
    bool is_active = false;
  } update_state_;

  /* State of the texture, which is needed for an integration with render session and interactive
   * updates and navigation. */
  struct {
    /* Denotes whether possibly existing state of GPU side texture is still usable.
     * It will not be usable in cases like render border did change (in this case we don't want
     * previous texture to be rendered at all).
     *
     * However, if only navigation or object in scene did change, then the outdated state of the
     * texture is still usable for draw, preventing display viewport flickering on navigation and
     * object modifications. */
    bool is_usable = false;

    /* Texture is considered outdated after `reset()` until the next call of
     * `copy_pixels_to_texture()`. */
    bool is_outdated = true;

    /* Texture size in pixels. */
    int2 size = make_int2(0, 0);
  } texture_state_;

  /* State of the texture buffer. Is tracked to perform sanity checks. */
  struct {
    /* True when the texture buffer is mapped with `map_texture_buffer()`. */
    bool is_mapped = false;
  } texture_buffer_state_;
};

CCL_NAMESPACE_END