NDEVR
API Documentation
VulkanPatchMatch.h
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2026, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: VulkanCompute
28File: VulkanPatchMatch
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include "VulkanComputeDevice.h"
35#include "VulkanComputeBuffer.h"
36#include "VulkanComputePipeline.h"
37#include <NDEVR/Buffer.h>
38#include <NDEVR/Pointer.h>
39#include <NDEVR/String.h>
40#include <NDEVR/File.h>
41
42#if !defined(__EMSCRIPTEN__) && NDEVR_SUPPORTS_THREADING
43
44namespace NDEVR
45{
57
68 {
69 float K[12];
70 float R[12];
71 float C[3];
72 int32_t camWidth;
73 int32_t camHeight;
74 uint32_t pixelOffset;
75 uint32_t _pad0;
76 uint32_t _pad1;
77 };
78 static_assert(sizeof(PatchMatchCamera) == 128, "PatchMatchCamera must be 128 bytes for std430 array stride");
79
82 {
83 int32_t width;
84 int32_t height;
85 int32_t nNumViews;
86 int32_t nInitTopK;
87 float fDepthMin;
88 float fDepthMax;
90 int32_t iteration;
91 int32_t isRedPass;
94 int32_t yOffset;
96 int32_t _pcPad0;
97 int32_t _pcPad1;
98 int32_t _pcPad2;
99 };
100
103 {
107 int width = 0;
108 int height = 0;
109 void clear()
110 {
111 width = 0;
112 height = 0;
113 depth_map.clear();
114 normal_map.clear();
115 confidence_map.clear();
116 }
117
118 };
119
132
135 {
136 int32_t width;
137 int32_t height;
139 int32_t _pad0;
141 float _pad1;
142 float _pad2;
143 float _pad3;
144 int32_t yOffset;
145 int32_t _pad4;
146 int32_t _pad5;
147 int32_t _pad6;
148 };
149
152 {
153 int32_t width;
154 int32_t height;
155 int32_t _pad0;
156 int32_t _pad1;
157 float _pad2;
158 float _pad3;
159 float _pad4;
160 float _pad5;
161 int32_t yOffset;
162 int32_t _pad6;
163 int32_t _pad7;
164 int32_t _pad8;
165 };
166
169 {
170 int32_t width;
171 int32_t height;
172 int32_t maxRange;
173 int32_t _pad0;
174 float _pad1;
175 float _pad2;
176 float P1;
177 float P2;
178 float decay;
179 float sgmWeight;
181 int32_t yOffset;
182 };
183
187 {
188 DynamicPointer<VulkanComputeBuffer> planes_buf, costs_buf, views_buf, rand_buf;
189 DynamicPointer<VulkanComputeBuffer> camera_buf, image_buf, low_depth_buf;
190 uint04 pixel_count = 0;
191 uint04 n_views = 0;
192 bool allocated = false;
193 };
194
195 class VULKAN_COMPUTE_API VulkanPatchMatch
196 {
197 public:
199 static bool IsAvailable(LogPtr log);
200
201 VulkanPatchMatch();
202 ~VulkanPatchMatch();
203
205 bool isInitialized() const { return m_initialized; }
206
224 bool estimateDepthMap(
225 uint04 ref_index,
226 const Buffer<uint04>& neighbor_indices,
227 const Buffer<PatchMatchCamera>& cameras,
228 const Buffer<Buffer<float>>& images,
229 const Buffer<int>& image_widths,
230 const Buffer<int>& image_heights,
231 float depth_min,
232 float depth_max,
233 uint04 n_estimation_iters,
234 uint04 n_init_top_k,
235 float threshold_keep_cost,
236 const Buffer<float>& initial_planes,
237 DepthEstimateResult& result,
238 const Buffer<float>& geometric_prior = Buffer<float>(),
239 PatchMatchGpuCache* cache = nullptr,
240 float confidence_skip = 0.0f);
241
253 static void FilterDepthMap(DepthEstimateResult& result,
254 uint04 min_component_size = 16u,
255 float depth_rel_tolerance = 0.02f);
256
271 static bool WriteDmap(File file_path,
272 const String& image_file_name,
273 const Buffer<uint32_t>& view_ids,
274 uint32_t image_width, uint32_t image_height,
275 const double K[9], const double R[9], const double C[3],
276 float depth_min, float depth_max,
277 float threshold_keep_cost,
278 const DepthEstimateResult& result);
279
290 bool filterGeometricConsistency(
291 const PatchMatchCamera& ref_camera,
292 const Buffer<PatchMatchCamera>& neighbor_cameras,
293 DepthEstimateResult& ref_result,
294 const Buffer<DepthEstimateResult>& neighbor_results,
295 float depth_diff_threshold,
296 float normal_diff_threshold,
297 uint04 min_consistent_views);
298
304 void filterDepthMapGpu(DepthEstimateResult& result,
305 uint04 min_consistent = 2u,
306 float depth_rel_tolerance = 0.02f);
307
321 bool refineDepthsInPlace(
322 const Buffer<PatchMatchCamera>& cameras,
323 const Buffer<Buffer<float>>& images,
324 const Buffer<int>& image_widths,
325 const Buffer<int>& image_heights,
326 float depth_min, float depth_max,
327 uint04 n_refinement_iters,
328 float threshold_keep_cost,
329 DepthEstimateResult& result,
330 PatchMatchGpuCache* cache = nullptr);
331
335 bool refineGeometric(
336 uint04 ref_index,
337 const Buffer<uint04>& neighbor_indices,
338 const Buffer<PatchMatchCamera>& cameras,
339 const Buffer<Buffer<float>>& images,
340 const Buffer<int>& image_widths,
341 const Buffer<int>& image_heights,
342 float depth_min, float depth_max,
343 uint04 n_refinement_iters,
344 uint04 n_init_top_k,
345 float threshold_keep_cost,
346 DepthEstimateResult& result,
347 const Buffer<PatchMatchCamera>& neighbor_cameras_for_geo,
348 const Buffer<DepthEstimateResult>& neighbor_depth_maps,
349 float depth_diff_threshold,
350 float normal_diff_threshold,
351 uint04 min_consistent_views,
352 PatchMatchGpuCache* cache = nullptr);
353
354 private:
357 bool loadShaders();
359 void createPipelines();
360
361 private:
362 ConstPointer<VulkanComputeDevice> m_compute_device;
363
364 // Compute pipelines (one per shader)
365 DynamicPointer<VulkanComputePipeline> m_initialize_pipeline;
366 DynamicPointer<VulkanComputePipeline> m_propagate_pipeline;
367 DynamicPointer<VulkanComputePipeline> m_filter_pipeline;
368 DynamicPointer<VulkanComputePipeline> m_refine_pipeline;
369 DynamicPointer<VulkanComputePipeline> m_geo_consistency_pipeline;
370 DynamicPointer<VulkanComputePipeline> m_depth_consistency_pipeline;
371 DynamicPointer<VulkanComputePipeline> m_median_pipeline;
372 DynamicPointer<VulkanComputePipeline> m_sgm_pipeline;
373
374 // SPIR-V shaders
375 DynamicPointer<VulkanShader> m_initialize_shader;
376 DynamicPointer<VulkanShader> m_propagate_shader;
377 DynamicPointer<VulkanShader> m_filter_shader;
378 DynamicPointer<VulkanShader> m_refine_shader;
379 DynamicPointer<VulkanShader> m_geo_consistency_shader;
380 DynamicPointer<VulkanShader> m_depth_consistency_shader;
381 DynamicPointer<VulkanShader> m_median_shader;
382 DynamicPointer<VulkanShader> m_sgm_shader;
383
384 bool m_initialized = false;
385 LogPtr m_log;
386 public:
389 void setLog(LogPtr log) { m_log = log; }
390 };
391}
392
393#else // __EMSCRIPTEN__ or no threading
394
395namespace NDEVR
396{
397 // Stub for platforms without Vulkan support
398 class VULKAN_COMPUTE_API VulkanPatchMatch
399 {
400 public:
401 static bool IsAvailable() { return false; }
402 };
403}
404
405#endif // !__EMSCRIPTEN__ && NDEVR_SUPPORTS_THREADING
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
Provides a modifiable pointer that has shared ownership of a dynamically allocated object.
Definition Pointer.hpp:356
A light-weight wrapper that will be a no-op if there is not a valid log reference,...
The primary namespace for the NDEVR SDK.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Push constants for depth consistency shader.
float _pad3
Padding for std430 alignment.
int32_t width
Image width in pixels.
int32_t height
Image height in pixels.
float _pad1
Padding for std430 alignment.
int32_t _pad0
Padding for std430 alignment.
int32_t _pad6
Padding for std430 alignment.
float fDepthRelTolerance
Relative depth tolerance for neighbor consistency.
int32_t nMinConsistent
Minimum consistent 8-neighbors to keep a pixel.
float _pad2
Padding for std430 alignment.
int32_t _pad4
Padding for std430 alignment.
int32_t _pad5
Padding for std430 alignment.
int32_t yOffset
Row offset for tiled dispatches.
Result from a single depth estimation pass.
Buffer< float > depth_map
W*H depth values.
int width
Image width in pixels.
Buffer< float > normal_map
W*H*3 normal components.
int height
Image height in pixels.
Buffer< float > confidence_map
W*H confidence values.
Push constants for geometric consistency shader.
int32_t nMinConsistent
Minimum consistent neighbors required to keep a pixel.
float fNormalDiffThreshold
Cosine angle threshold for normal consistency.
int32_t height
Image height in pixels.
float fDepthDiffThreshold
Relative depth tolerance for consistency.
int32_t yOffset
Row offset for tiled dispatches.
int32_t _pad0
Padding for std430 alignment.
int32_t width
Image width in pixels.
int32_t nNumNeighbors
Number of neighbor depth maps to check.
Push constants for median filter shader.
int32_t height
Image height in pixels.
int32_t width
Image width in pixels.
GPU-accelerated PatchMatch depth estimation using Vulkan compute shaders.
float R[12]
3x3 rotation (column-major, 3 columns × [3 floats + 1 pad])
int32_t camHeight
Image height.
uint32_t _pad0
Padding to match GLSL std430 array stride (128 bytes).
uint32_t pixelOffset
Offset into packed image SSBO.
float K[12]
3x3 intrinsic (column-major, 3 columns × [3 floats + 1 pad])
float C[3]
Camera center (vec3).
int32_t camWidth
Image width (packs into vec3 C's trailing 4 bytes).
uint32_t _pad1
(std430 rounds struct size to 16-byte alignment for arrays)
GPU buffer cache for reuse across multiple estimateDepthMap calls.
Push constant layout (must match GLSL layout exactly).
int32_t yOffset
Row offset for tiled dispatches.
int32_t nInitTopK
Number of top views to select during initialization.
float fThresholdKeepCost
Cost threshold for filtering bad matches.
int32_t nNumViews
Number of neighbor views used for matching.
int32_t iteration
Current PatchMatch iteration index.
float fConfidenceSkipThreshold
Skip pixels with cost below this (0 = disabled).
int32_t width
Image width in pixels.
int32_t _pcPad1
Padding for std430 alignment.
int32_t isRedPass
Whether this is the red (1) or black (0) checkerboard pass.
int32_t nEstimationIters
Total number of PatchMatch iterations to perform.
int32_t bLowResProcessed
Whether a low-resolution prior has been applied.
float fDepthMin
Minimum depth bound.
float fDepthMax
Maximum depth bound.
int32_t _pcPad0
Padding for std430 alignment.
int32_t _pcPad2
Padding for std430 alignment.
int32_t height
Image height in pixels.
Push constants for SGM directional cost aggregation shader.
int32_t maxRange
Max scanline walk distance (default 64).
float threshSmall
Relative depth diff threshold for small step (default 0.01).
float P2
Large depth step penalty (default 0.08).
float sgmWeight
Blend weight for aggregated cost (default 0.3).
float decay
Per-step penalty decay (default 0.92).
float P1
Small depth step penalty (default 0.02).