nanovdb-editor 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nanovdb_editor-0.0.3/PKG-INFO +56 -0
- nanovdb_editor-0.0.3/README.md +43 -0
- nanovdb_editor-0.0.3/VERSION.txt +1 -0
- nanovdb_editor-0.0.3/dev_environment.yml +12 -0
- nanovdb_editor-0.0.3/environment.yml +8 -0
- nanovdb_editor-0.0.3/nanovdb_editor/__init__.py +30 -0
- nanovdb_editor-0.0.3/nanovdb_editor/compiler.py +178 -0
- nanovdb_editor-0.0.3/nanovdb_editor/compute.py +275 -0
- nanovdb_editor-0.0.3/nanovdb_editor/device.py +168 -0
- nanovdb_editor-0.0.3/nanovdb_editor/editor.py +340 -0
- nanovdb_editor-0.0.3/nanovdb_editor/raster.py +157 -0
- nanovdb_editor-0.0.3/nanovdb_editor/utils.py +82 -0
- nanovdb_editor-0.0.3/pyproject.toml +45 -0
- nanovdb_editor-0.0.3/test_c/CMakeLists.txt +66 -0
- nanovdb_editor-0.0.3/test_c/build.sh +29 -0
- nanovdb_editor-0.0.3/test_c/main.c +231 -0
- nanovdb_editor-0.0.3/test_c/shaders/test.slang +21 -0
- nanovdb_editor-0.0.3/test_cpp/CMakeLists.txt +31 -0
- nanovdb_editor-0.0.3/test_cpp/build.sh +29 -0
- nanovdb_editor-0.0.3/test_cpp/main.cpp +315 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: nanovdb-editor
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: NanoVDB Editor Python Module
|
|
5
|
+
Keywords: nanovdb,volume,rendering,gaussian,splatting,3d
|
|
6
|
+
Author: The OpenVDB Project contributors
|
|
7
|
+
License: Apache-2.0
|
|
8
|
+
Project-URL: Homepage, https://github.com/openvdb/nanovdb-editor
|
|
9
|
+
Project-URL: Repository, https://github.com/openvdb/nanovdb-editor
|
|
10
|
+
Project-URL: Documentation, https://github.com/openvdb/nanovdb-editor/tree/main/pymodule
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
## NanoVDB Editor
|
|
15
|
+
|
|
16
|
+
WIP
|
|
17
|
+
|
|
18
|
+
### Shader Parameters
|
|
19
|
+
Shaders can have defined struct with shader parameters which are intended to be shown in the editor's UI:
|
|
20
|
+
```hlsl
|
|
21
|
+
struct shader_params_t
|
|
22
|
+
{
|
|
23
|
+
float4 color;
|
|
24
|
+
bool use_color;
|
|
25
|
+
bool3 _pad1;
|
|
26
|
+
int _pad2;
|
|
27
|
+
};
|
|
28
|
+
ConstantBuffer<shader_params_t> shader_params;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Shader parameters can have defined default values in the json file:
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"ShaderParams": {
|
|
35
|
+
"color": {
|
|
36
|
+
"value": [1.0, 0.0, 1.0, 1.0],
|
|
37
|
+
"min": 0.0,
|
|
38
|
+
"max": 1.0,
|
|
39
|
+
"step": 0.01
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
Supported types: `bool`, `int`, `uint`, `int64`, `uint64`, `float` and its vectors and 4x4 matrix.
|
|
45
|
+
Variables with `_pad` in the name are not shown in the UI.
|
|
46
|
+
Those parameters can be interactively changed with generated UI in the editor's Params tab.
|
|
47
|
+
|
|
48
|
+
To display a group of shader parameters from different shaders define a json file with various shader paths:
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"ShaderParams": [
|
|
52
|
+
"editor/editor.slang",
|
|
53
|
+
"test/test.slang"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## NanoVDB Editor
|
|
2
|
+
|
|
3
|
+
WIP
|
|
4
|
+
|
|
5
|
+
### Shader Parameters
|
|
6
|
+
Shaders can have defined struct with shader parameters which are intended to be shown in the editor's UI:
|
|
7
|
+
```hlsl
|
|
8
|
+
struct shader_params_t
|
|
9
|
+
{
|
|
10
|
+
float4 color;
|
|
11
|
+
bool use_color;
|
|
12
|
+
bool3 _pad1;
|
|
13
|
+
int _pad2;
|
|
14
|
+
};
|
|
15
|
+
ConstantBuffer<shader_params_t> shader_params;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Shader parameters can have defined default values in the json file:
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"ShaderParams": {
|
|
22
|
+
"color": {
|
|
23
|
+
"value": [1.0, 0.0, 1.0, 1.0],
|
|
24
|
+
"min": 0.0,
|
|
25
|
+
"max": 1.0,
|
|
26
|
+
"step": 0.01
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
Supported types: `bool`, `int`, `uint`, `int64`, `uint64`, `float` and its vectors and 4x4 matrix.
|
|
32
|
+
Variables with `_pad` in the name are not shown in the UI.
|
|
33
|
+
Those parameters can be interactively changed with generated UI in the editor's Params tab.
|
|
34
|
+
|
|
35
|
+
To display a group of shader parameters from different shaders define a json file with various shader paths:
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"ShaderParams": [
|
|
39
|
+
"editor/editor.slang",
|
|
40
|
+
"test/test.slang"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.0.3
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright Contributors to the OpenVDB Project
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from .compiler import Compiler, pnanovdb_CompileTarget, MemoryBuffer
|
|
8
|
+
from .compute import Compute
|
|
9
|
+
from .device import DeviceInterface
|
|
10
|
+
from .editor import Editor, pnanovdb_EditorConfig
|
|
11
|
+
from .raster import Raster
|
|
12
|
+
|
|
13
|
+
if sys.platform == "win32":
|
|
14
|
+
lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lib")
|
|
15
|
+
if os.path.exists(lib_dir):
|
|
16
|
+
from .utils import add_dll_search_directory
|
|
17
|
+
|
|
18
|
+
add_dll_search_directory(lib_dir)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"Compiler",
|
|
23
|
+
"Compute",
|
|
24
|
+
"DeviceInterface",
|
|
25
|
+
"Editor",
|
|
26
|
+
"Raster",
|
|
27
|
+
"pnanovdb_CompileTarget",
|
|
28
|
+
"MemoryBuffer",
|
|
29
|
+
"pnanovdb_EditorConfig",
|
|
30
|
+
]
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Copyright Contributors to the OpenVDB Project
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
from ctypes import *
|
|
5
|
+
from enum import Enum
|
|
6
|
+
import numpy as np
|
|
7
|
+
from typing import Tuple
|
|
8
|
+
from .utils import load_library
|
|
9
|
+
|
|
10
|
+
COMPILER_LIB = "pnanovdbcompiler"
|
|
11
|
+
|
|
12
|
+
# Match pnanovdb_bool_t (int32_t)
|
|
13
|
+
pnanovdb_bool_t = c_int32
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class pnanovdb_CompileTarget(Enum):
|
|
17
|
+
UNDEFINED = 0
|
|
18
|
+
VULKAN = 1
|
|
19
|
+
CPU = 2
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class pnanovdb_CompilerSettings(Structure):
|
|
23
|
+
"""Definition equivalent to pnanovdb_compiler_settings_t."""
|
|
24
|
+
|
|
25
|
+
_fields_ = [
|
|
26
|
+
("is_row_major", c_int32),
|
|
27
|
+
("use_glslang", c_int32),
|
|
28
|
+
("hlsl_output", c_int32),
|
|
29
|
+
("compile_target", c_uint32),
|
|
30
|
+
("entry_point_name", c_char * 64),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class pnanovdb_CompilerInstance(Structure):
|
|
35
|
+
"""Definition equivalent to pnanovdb_compiler_instance_t."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class pnanovdb_Compiler(Structure):
|
|
39
|
+
"""Definition equivalent to pnanovdb_compiler_t."""
|
|
40
|
+
|
|
41
|
+
_fields_ = [
|
|
42
|
+
("interface_pnanovdb_reflect_data_type", c_void_p), # PNANOVDB_REFLECT_INTERFACE()
|
|
43
|
+
("create_instance", CFUNCTYPE(POINTER(pnanovdb_CompilerInstance))),
|
|
44
|
+
("set_diagnostic_callback", CFUNCTYPE(None, POINTER(pnanovdb_CompilerInstance), CFUNCTYPE(None, c_char_p))),
|
|
45
|
+
(
|
|
46
|
+
"compile_shader_from_file",
|
|
47
|
+
CFUNCTYPE(
|
|
48
|
+
pnanovdb_bool_t,
|
|
49
|
+
POINTER(pnanovdb_CompilerInstance),
|
|
50
|
+
c_char_p,
|
|
51
|
+
POINTER(pnanovdb_CompilerSettings),
|
|
52
|
+
POINTER(pnanovdb_bool_t),
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
(
|
|
56
|
+
"execute_cpu",
|
|
57
|
+
CFUNCTYPE(
|
|
58
|
+
pnanovdb_bool_t,
|
|
59
|
+
POINTER(pnanovdb_CompilerInstance),
|
|
60
|
+
c_char_p,
|
|
61
|
+
c_uint32,
|
|
62
|
+
c_uint32,
|
|
63
|
+
c_uint32,
|
|
64
|
+
c_void_p,
|
|
65
|
+
c_void_p,
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
("destroy_instance", CFUNCTYPE(None, POINTER(pnanovdb_CompilerInstance))),
|
|
69
|
+
("module", c_void_p),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class MemoryBuffer(Structure):
|
|
74
|
+
"""Python wrapper for memory buffer passed to the shader function run on CPU."""
|
|
75
|
+
|
|
76
|
+
_fields_ = [
|
|
77
|
+
("data", c_void_p),
|
|
78
|
+
("size", c_uint64),
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
def __init__(self, data: np.ndarray):
|
|
82
|
+
"""Initialize the MemoryBuffer with a numpy array."""
|
|
83
|
+
self.data = data.ctypes.data_as(c_void_p)
|
|
84
|
+
self.size = data.size
|
|
85
|
+
|
|
86
|
+
def to_ndarray(self, dtype):
|
|
87
|
+
"""Convert memory buffer to numpy array of specified dtype."""
|
|
88
|
+
if not self.data or not self.size:
|
|
89
|
+
return np.array([], dtype=dtype)
|
|
90
|
+
|
|
91
|
+
# Create array from buffer without copying
|
|
92
|
+
return np.frombuffer((c_byte * (self.size * np.dtype(dtype).itemsize)).from_address(self.data), dtype=dtype)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Compiler:
|
|
96
|
+
"""Python wrapper for pnanovdb_compiler_t."""
|
|
97
|
+
|
|
98
|
+
def __init__(self):
|
|
99
|
+
"""Mirrors what is in pnanovdb_compiler_load"""
|
|
100
|
+
self._lib = load_library(COMPILER_LIB)
|
|
101
|
+
|
|
102
|
+
get_compiler = self._lib.pnanovdb_get_compiler
|
|
103
|
+
get_compiler.restype = POINTER(pnanovdb_Compiler)
|
|
104
|
+
get_compiler.argtypes = []
|
|
105
|
+
self._compiler = get_compiler()
|
|
106
|
+
if not self._compiler:
|
|
107
|
+
raise RuntimeError("Failed to get compiler interface")
|
|
108
|
+
|
|
109
|
+
self._instance = None
|
|
110
|
+
self._compiler.contents.module = self._lib._handle
|
|
111
|
+
|
|
112
|
+
def get_compiler(self) -> POINTER(pnanovdb_Compiler):
|
|
113
|
+
return self._compiler
|
|
114
|
+
|
|
115
|
+
def create_instance(self) -> None:
|
|
116
|
+
if self._instance:
|
|
117
|
+
raise RuntimeError("Compiler instance already exists")
|
|
118
|
+
|
|
119
|
+
create_func = self._compiler.contents.create_instance
|
|
120
|
+
self._instance = create_func()
|
|
121
|
+
|
|
122
|
+
if not self._instance:
|
|
123
|
+
raise RuntimeError("Failed to create compiler instance")
|
|
124
|
+
|
|
125
|
+
def compile_shader(
|
|
126
|
+
self, filename: str, entry_point_name="main", is_row_major=False, compile_target=pnanovdb_CompileTarget.VULKAN
|
|
127
|
+
) -> bool:
|
|
128
|
+
if not self._instance:
|
|
129
|
+
raise RuntimeError("No compiler instance exists")
|
|
130
|
+
|
|
131
|
+
settings = pnanovdb_CompilerSettings(
|
|
132
|
+
entry_point_name=entry_point_name.encode("utf-8"),
|
|
133
|
+
is_row_major=is_row_major,
|
|
134
|
+
use_glslang=False,
|
|
135
|
+
hlsl_output=False,
|
|
136
|
+
compile_target=(c_uint32)(compile_target.value),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
compile_func = self._compiler.contents.compile_shader_from_file
|
|
140
|
+
return compile_func(self._instance, filename.encode("utf-8"), byref(settings), None)
|
|
141
|
+
|
|
142
|
+
def execute_cpu(
|
|
143
|
+
self,
|
|
144
|
+
filename: str,
|
|
145
|
+
grid_dims: Tuple[int, int, int],
|
|
146
|
+
uniform_params: POINTER(c_void_p),
|
|
147
|
+
uniform_state: POINTER(c_void_p),
|
|
148
|
+
) -> bool:
|
|
149
|
+
if not self._instance:
|
|
150
|
+
raise RuntimeError("No compiler instance exists")
|
|
151
|
+
|
|
152
|
+
execute_func = self._compiler.contents.execute_cpu
|
|
153
|
+
return execute_func(
|
|
154
|
+
self._instance,
|
|
155
|
+
filename.encode("utf-8"),
|
|
156
|
+
c_uint32(grid_dims[0]),
|
|
157
|
+
c_uint32(grid_dims[1]),
|
|
158
|
+
c_uint32(grid_dims[2]),
|
|
159
|
+
uniform_params,
|
|
160
|
+
uniform_state,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def destroy_instance(self) -> None:
|
|
164
|
+
if not self._instance:
|
|
165
|
+
return
|
|
166
|
+
|
|
167
|
+
destroy_func = self._compiler.contents.destroy_instance
|
|
168
|
+
destroy_func(self._instance)
|
|
169
|
+
|
|
170
|
+
self._instance = None
|
|
171
|
+
|
|
172
|
+
def __del__(self):
|
|
173
|
+
# Do not call into native library from Python finalizer; just drop refs
|
|
174
|
+
try:
|
|
175
|
+
self._instance = None
|
|
176
|
+
self._compiler = None
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Copyright Contributors to the OpenVDB Project
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
from ctypes import *
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from .utils import load_library
|
|
9
|
+
from .device import DeviceInterface, pnanovdb_DeviceInterface, pnanovdb_Device
|
|
10
|
+
from .compiler import Compiler, pnanovdb_Compiler
|
|
11
|
+
|
|
12
|
+
COMPUTE_LIB = "pnanovdbcompute"
|
|
13
|
+
|
|
14
|
+
# Match pnanovdb_bool_t (int32_t)
|
|
15
|
+
pnanovdb_bool_t = c_int32
|
|
16
|
+
|
|
17
|
+
VULKAN_API = 1
|
|
18
|
+
PNANOVDB_TRUE = 1
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class pnanovdb_ComputeShaderSource(Structure):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class pnanovdb_ComputeShaderBuild(Structure):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class pnanovdb_ShaderInterface(Structure):
|
|
30
|
+
"""Definition equivalent to pnanovdb_compute_shader_interface_t."""
|
|
31
|
+
|
|
32
|
+
_fields_ = [
|
|
33
|
+
("interface_pnanovdb_reflect_data_type", c_void_p), # PNANOVDB_REFLECT_INTERFACE()
|
|
34
|
+
("create_shader", CFUNCTYPE(c_void_p, POINTER(pnanovdb_ComputeShaderSource))),
|
|
35
|
+
("map_shader_build", CFUNCTYPE(pnanovdb_bool_t, c_void_p, POINTER(POINTER(pnanovdb_ComputeShaderBuild)))),
|
|
36
|
+
("destroy_shader", CFUNCTYPE(None, c_void_p)),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class pnanovdb_ComputeArray(Structure):
|
|
41
|
+
"""Definition equivalent to pnanovdb_compute_array_t."""
|
|
42
|
+
|
|
43
|
+
_fields_ = [("data", c_void_p), ("element_size", c_uint64), ("element_count", c_uint64), ("filepath", c_char_p)]
|
|
44
|
+
|
|
45
|
+
def __init__(self, data=None, element_size=0, element_count=0, filepath=None):
|
|
46
|
+
super().__init__()
|
|
47
|
+
self.data = data
|
|
48
|
+
self.element_size = element_size
|
|
49
|
+
self.element_count = element_count
|
|
50
|
+
self.filepath = filepath.encode("utf-8") if isinstance(filepath, str) else filepath
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class pnanovdb_Compute(Structure):
|
|
54
|
+
"""Definition equivalent to pnanovdb_compute_t."""
|
|
55
|
+
|
|
56
|
+
_fields_ = [
|
|
57
|
+
("interface_pnanovdb_reflect_data_type", c_void_p), # PNANOVDB_REFLECT_INTERFACE()
|
|
58
|
+
("module", c_void_p),
|
|
59
|
+
("compiler", POINTER(pnanovdb_Compiler)),
|
|
60
|
+
("shader_interface", pnanovdb_ShaderInterface),
|
|
61
|
+
("device_interface", pnanovdb_DeviceInterface),
|
|
62
|
+
("load_nanovdb", CFUNCTYPE(POINTER(pnanovdb_ComputeArray), c_char_p)),
|
|
63
|
+
("save_nanovdb", CFUNCTYPE(pnanovdb_bool_t, POINTER(pnanovdb_ComputeArray), c_char_p)),
|
|
64
|
+
("create_shader_context", CFUNCTYPE(c_void_p, c_char_p)),
|
|
65
|
+
("destroy_shader_context", CFUNCTYPE(None, c_void_p)),
|
|
66
|
+
(
|
|
67
|
+
"init_shader",
|
|
68
|
+
CFUNCTYPE(
|
|
69
|
+
pnanovdb_bool_t,
|
|
70
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
71
|
+
c_void_p, # pnanovdb_compute_queue_t*
|
|
72
|
+
c_void_p, # pnanovdb_shader_context_t*
|
|
73
|
+
c_void_p,
|
|
74
|
+
),
|
|
75
|
+
), # pnanovdb_compiler_settings_t*
|
|
76
|
+
(
|
|
77
|
+
"destroy_shader",
|
|
78
|
+
CFUNCTYPE(
|
|
79
|
+
None,
|
|
80
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
81
|
+
POINTER(pnanovdb_ShaderInterface),
|
|
82
|
+
c_void_p, # pnanovdb_compute_context_t*
|
|
83
|
+
c_void_p,
|
|
84
|
+
),
|
|
85
|
+
), # pnanovdb_shader_context_t*
|
|
86
|
+
(
|
|
87
|
+
"dispatch_shader",
|
|
88
|
+
CFUNCTYPE(
|
|
89
|
+
None,
|
|
90
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
91
|
+
c_void_p, # pnanovdb_compute_context_t*
|
|
92
|
+
c_void_p, # const pnanovdb_shader_context_t*
|
|
93
|
+
c_void_p, # pnanovdb_compute_resource_t*
|
|
94
|
+
c_uint32, # grid_dim_x
|
|
95
|
+
c_uint32, # grid_dim_y
|
|
96
|
+
c_uint32, # grid_dim_z
|
|
97
|
+
c_char_p,
|
|
98
|
+
),
|
|
99
|
+
), # debug_label
|
|
100
|
+
(
|
|
101
|
+
"dispatch_shader_on_array",
|
|
102
|
+
CFUNCTYPE(
|
|
103
|
+
pnanovdb_bool_t,
|
|
104
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
105
|
+
POINTER(pnanovdb_Device),
|
|
106
|
+
c_char_p,
|
|
107
|
+
c_uint32,
|
|
108
|
+
c_uint32,
|
|
109
|
+
c_uint32,
|
|
110
|
+
POINTER(pnanovdb_ComputeArray),
|
|
111
|
+
POINTER(pnanovdb_ComputeArray),
|
|
112
|
+
POINTER(pnanovdb_ComputeArray),
|
|
113
|
+
c_uint32,
|
|
114
|
+
c_uint64,
|
|
115
|
+
c_uint64,
|
|
116
|
+
),
|
|
117
|
+
),
|
|
118
|
+
(
|
|
119
|
+
"dispatch_shader_on_nanovdb_array",
|
|
120
|
+
CFUNCTYPE(
|
|
121
|
+
pnanovdb_bool_t,
|
|
122
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
123
|
+
c_void_p, # const pnanovdb_compute_device_t*
|
|
124
|
+
c_void_p, # const pnanovdb_shader_context_t*
|
|
125
|
+
POINTER(pnanovdb_ComputeArray), # nanovdb_array
|
|
126
|
+
c_int32, # image_width
|
|
127
|
+
c_int32, # image_height
|
|
128
|
+
c_void_p, # background_image
|
|
129
|
+
c_void_p, # upload_buffer
|
|
130
|
+
c_void_p, # user_upload_buffer
|
|
131
|
+
POINTER(c_void_p), # nanovdb_buffer
|
|
132
|
+
POINTER(c_void_p),
|
|
133
|
+
),
|
|
134
|
+
), # readback_buffer
|
|
135
|
+
("create_array", CFUNCTYPE(POINTER(pnanovdb_ComputeArray), c_size_t, c_uint64, c_void_p)),
|
|
136
|
+
("destroy_array", CFUNCTYPE(None, POINTER(pnanovdb_ComputeArray))),
|
|
137
|
+
("map_array", CFUNCTYPE(c_void_p, POINTER(pnanovdb_ComputeArray))),
|
|
138
|
+
("unmap_array", CFUNCTYPE(None, POINTER(pnanovdb_ComputeArray))),
|
|
139
|
+
(
|
|
140
|
+
"compute_array_print_range",
|
|
141
|
+
CFUNCTYPE(
|
|
142
|
+
None,
|
|
143
|
+
c_void_p, # POINTER(pnanovdb_Compute)
|
|
144
|
+
c_void_p, # pnanovdb_compute_log_print_t
|
|
145
|
+
c_char_p, # name
|
|
146
|
+
POINTER(pnanovdb_ComputeArray), # arr
|
|
147
|
+
c_uint32,
|
|
148
|
+
),
|
|
149
|
+
), # channel_count
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class Compute:
|
|
154
|
+
"""Python wrapper for pnanovdb_compute_t."""
|
|
155
|
+
|
|
156
|
+
def __init__(self, compiler: Compiler):
|
|
157
|
+
"""Mirrors what is in pnanovdb_compute_load"""
|
|
158
|
+
self._compiler = compiler
|
|
159
|
+
|
|
160
|
+
self._lib = load_library(COMPUTE_LIB)
|
|
161
|
+
|
|
162
|
+
# only vulkan is supported for now
|
|
163
|
+
self._device_interface = DeviceInterface(VULKAN_API)
|
|
164
|
+
|
|
165
|
+
get_compute = self._lib.pnanovdb_get_compute
|
|
166
|
+
get_compute.restype = POINTER(pnanovdb_Compute)
|
|
167
|
+
get_compute.argtypes = []
|
|
168
|
+
|
|
169
|
+
self._compute = get_compute()
|
|
170
|
+
if not self._compute:
|
|
171
|
+
raise RuntimeError("Failed to get compute interface")
|
|
172
|
+
|
|
173
|
+
compiler_ptr = compiler.get_compiler()
|
|
174
|
+
if not compiler_ptr:
|
|
175
|
+
raise RuntimeError("Failed to get compiler interface")
|
|
176
|
+
|
|
177
|
+
self._compute.contents.compiler = compiler_ptr
|
|
178
|
+
self._compute.contents.device_interface = self._device_interface.get_device_interface().contents
|
|
179
|
+
self._compute.contents.module = self._lib._handle
|
|
180
|
+
|
|
181
|
+
get_shader_interface = self._lib.pnanovdb_get_compute_shader_interface
|
|
182
|
+
get_shader_interface.restype = POINTER(pnanovdb_ShaderInterface)
|
|
183
|
+
get_shader_interface.argtypes = []
|
|
184
|
+
|
|
185
|
+
self._compute.contents.shader_interface = get_shader_interface().contents
|
|
186
|
+
|
|
187
|
+
def get_compute(self) -> POINTER(pnanovdb_Compute):
|
|
188
|
+
return self._compute
|
|
189
|
+
|
|
190
|
+
def compiler(self) -> Compiler:
|
|
191
|
+
return self._compiler
|
|
192
|
+
|
|
193
|
+
def device_interface(self) -> DeviceInterface:
|
|
194
|
+
return self._device_interface
|
|
195
|
+
|
|
196
|
+
def load_nanovdb(self, filepath: str) -> pnanovdb_ComputeArray:
|
|
197
|
+
load_func = self._compute.contents.load_nanovdb
|
|
198
|
+
array = load_func(filepath.encode("utf-8"))
|
|
199
|
+
if not array:
|
|
200
|
+
raise RuntimeError(f"Failed to load NanoVDB file: {filepath}")
|
|
201
|
+
return array.contents
|
|
202
|
+
|
|
203
|
+
def save_nanovdb(self, array: pnanovdb_ComputeArray, filepath: str) -> None:
|
|
204
|
+
save_func = self._compute.contents.save_nanovdb
|
|
205
|
+
save_func(pointer(array), filepath.encode("utf-8"))
|
|
206
|
+
|
|
207
|
+
def create_array(self, data: np.ndarray) -> pnanovdb_ComputeArray:
|
|
208
|
+
create_func = self._compute.contents.create_array
|
|
209
|
+
array = create_func(data.itemsize, data.size, data.ctypes.data_as(c_void_p))
|
|
210
|
+
if not array:
|
|
211
|
+
raise RuntimeError("Failed to create compute array")
|
|
212
|
+
return array.contents
|
|
213
|
+
|
|
214
|
+
def destroy_array(self, array: pnanovdb_ComputeArray) -> None:
|
|
215
|
+
destroy_func = self._compute.contents.destroy_array
|
|
216
|
+
destroy_func(pointer(array))
|
|
217
|
+
|
|
218
|
+
def dispatch_shader_on_array(
|
|
219
|
+
self,
|
|
220
|
+
shader_path: str,
|
|
221
|
+
grid_dims: Tuple[int, int, int],
|
|
222
|
+
data_in: pnanovdb_ComputeArray,
|
|
223
|
+
constants: pnanovdb_ComputeArray,
|
|
224
|
+
data_out: pnanovdb_ComputeArray,
|
|
225
|
+
dispatch_count: int = 1,
|
|
226
|
+
scratch_size: int = 0,
|
|
227
|
+
scratch_clear_size: int = 0,
|
|
228
|
+
) -> bool:
|
|
229
|
+
if not data_in or not constants or not data_out:
|
|
230
|
+
raise ValueError("ComputeArray parameters cannot be None")
|
|
231
|
+
|
|
232
|
+
dispatch_func = self._compute.contents.dispatch_shader_on_array
|
|
233
|
+
result = dispatch_func(
|
|
234
|
+
self._compute,
|
|
235
|
+
self._device_interface.get_device(),
|
|
236
|
+
shader_path.encode("utf-8"),
|
|
237
|
+
c_uint32(grid_dims[0]),
|
|
238
|
+
c_uint32(grid_dims[1]),
|
|
239
|
+
c_uint32(grid_dims[2]),
|
|
240
|
+
pointer(data_in),
|
|
241
|
+
pointer(constants),
|
|
242
|
+
pointer(data_out),
|
|
243
|
+
c_uint32(dispatch_count),
|
|
244
|
+
c_uint64(scratch_size),
|
|
245
|
+
c_uint64(scratch_clear_size),
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
return result == PNANOVDB_TRUE
|
|
249
|
+
|
|
250
|
+
def map_array(self, array: pnanovdb_ComputeArray, np_dtype: np.dtype) -> np.ndarray:
|
|
251
|
+
if array.element_size != np_dtype.itemsize:
|
|
252
|
+
raise ValueError("Array element size mismatches the provided dtype")
|
|
253
|
+
|
|
254
|
+
map_func = self._compute.contents.map_array
|
|
255
|
+
data_ptr = map_func(pointer(array))
|
|
256
|
+
if not data_ptr:
|
|
257
|
+
raise RuntimeError("Failed to map array")
|
|
258
|
+
|
|
259
|
+
buffer = (c_byte * (array.element_size * array.element_count)).from_address(data_ptr)
|
|
260
|
+
return np.frombuffer(buffer, dtype=np_dtype)
|
|
261
|
+
|
|
262
|
+
def unmap_array(self, array: pnanovdb_ComputeArray) -> None:
|
|
263
|
+
unmap_func = self._compute.contents.unmap_array
|
|
264
|
+
unmap_func(pointer(array))
|
|
265
|
+
|
|
266
|
+
def array_exists(self, array: pnanovdb_ComputeArray) -> bool:
|
|
267
|
+
return array and array.data is not None
|
|
268
|
+
|
|
269
|
+
def __del__(self):
|
|
270
|
+
try:
|
|
271
|
+
self._compute = None
|
|
272
|
+
self._compiler = None
|
|
273
|
+
self._device_interface = None
|
|
274
|
+
except Exception:
|
|
275
|
+
pass
|