diff --git a/optix/_version.py b/optix/_version.py index 485f44a..b3f4756 100644 --- a/optix/_version.py +++ b/optix/_version.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.1.2" diff --git a/optix/build.pxd b/optix/build.pxd index 895d613..457c1d7 100644 --- a/optix/build.pxd +++ b/optix/build.pxd @@ -33,11 +33,13 @@ cdef extern from "optix.h" nogil: float timeBegin float timeEnd + cdef struct OptixAccelBuildOptions: unsigned int buildFlags OptixBuildOperation operation OptixMotionOptions motionOptions + cdef enum OptixBuildInputType: OPTIX_BUILD_INPUT_TYPE_TRIANGLES, OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES, @@ -51,6 +53,7 @@ cdef extern from "optix.h" nogil: CUdeviceptr instances unsigned int numInstances + cdef struct OptixAabb: float minX float minY @@ -59,6 +62,7 @@ cdef extern from "optix.h" nogil: float maxY float maxZ + cdef struct OptixBuildInputCustomPrimitiveArray: const CUdeviceptr * aabbBuffers unsigned int numPrimitives @@ -70,7 +74,17 @@ cdef extern from "optix.h" nogil: unsigned int sbtIndexOffsetStrideInBytes unsigned int primitiveIndexOffset - IF _OPTIX_VERSION_MAJOR == 7 and _OPTIX_VERSION_MINOR > 3: # switch to new instance flags + + IF _OPTIX_VERSION_MAJOR == 7 and _OPTIX_VERSION_MINOR > 4: # switch to new instance flags + cdef enum OptixPrimitiveType: + OPTIX_PRIMITIVE_TYPE_CUSTOM, + OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, + OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM, + OPTIX_PRIMITIVE_TYPE_SPHERE, + OPTIX_PRIMITIVE_TYPE_TRIANGLE, + ELIF _OPTIX_VERSION_MAJOR == 7 and _OPTIX_VERSION_MINOR > 3: cdef enum OptixPrimitiveType: OPTIX_PRIMITIVE_TYPE_CUSTOM, OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, @@ -78,11 +92,21 @@ cdef extern from "optix.h" nogil: OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM, OPTIX_PRIMITIVE_TYPE_TRIANGLE, + ELSE: + cdef enum OptixPrimitiveType: + OPTIX_PRIMITIVE_TYPE_CUSTOM, + OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, + OPTIX_PRIMITIVE_TYPE_TRIANGLE, + + IF _OPTIX_VERSION_MAJOR == 7 and _OPTIX_VERSION_MINOR > 3: # switch to new instance flags cdef enum OptixCurveEndcapFlags: OPTIX_CURVE_ENDCAP_DEFAULT, OPTIX_CURVE_ENDCAP_ON + cdef struct OptixBuildInputCurveArray: OptixPrimitiveType curveType unsigned int numPrimitives @@ -99,13 +123,6 @@ cdef extern from "optix.h" nogil: unsigned int primitiveIndexOffset unsigned int endcapFlags ELSE: - cdef enum OptixPrimitiveType: - OPTIX_PRIMITIVE_TYPE_CUSTOM, - OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, - OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, - OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, - OPTIX_PRIMITIVE_TYPE_TRIANGLE, - cdef struct OptixBuildInputCurveArray: OptixPrimitiveType curveType unsigned int numPrimitives @@ -121,11 +138,13 @@ cdef extern from "optix.h" nogil: unsigned int flag unsigned int primitiveIndexOffset + cdef enum OptixIndicesFormat: OPTIX_INDICES_FORMAT_NONE, OPTIX_INDICES_FORMAT_UNSIGNED_SHORT3, OPTIX_INDICES_FORMAT_UNSIGNED_INT3 + cdef enum OptixVertexFormat: OPTIX_VERTEX_FORMAT_NONE, OPTIX_VERTEX_FORMAT_FLOAT3, @@ -135,14 +154,23 @@ cdef extern from "optix.h" nogil: OPTIX_VERTEX_FORMAT_SNORM16_3, OPTIX_VERTEX_FORMAT_SNORM16_2 + cdef enum OptixTransformFormat: OPTIX_TRANSFORM_FORMAT_NONE, OPTIX_TRANSFORM_FORMAT_MATRIX_FLOAT12, - cdef enum OptixGeometryFlags: - OPTIX_GEOMETRY_FLAG_NONE, - OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT, - OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL + + IF _OPTIX_VERSION > 70400: # switch to new geometry flags + cdef enum OptixGeometryFlags: + OPTIX_GEOMETRY_FLAG_NONE, + OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT, + OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL + OPTIX_GEOMETRY_FLAG_DISABLE_TRIANGLE_FACE_CULLING + ELSE: + cdef enum OptixGeometryFlags: + OPTIX_GEOMETRY_FLAG_NONE, + OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT, + OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL cdef struct OptixBuildInputTriangleArray: const CUdeviceptr * vertexBuffers @@ -162,32 +190,63 @@ cdef extern from "optix.h" nogil: unsigned int primitiveIndexOffset OptixTransformFormat transformFormat - cdef struct OptixBuildInput: - OptixBuildInputType type - # union - OptixBuildInputTriangleArray triangleArray - OptixBuildInputCurveArray curveArray - OptixBuildInputCustomPrimitiveArray customPrimitiveArray - OptixBuildInputInstanceArray instanceArray + + IF _OPTIX_VERSION > 70400: # switch to new geometry flags + cdef struct OptixBuildInputSphereArray: + const CUdeviceptr* vertexBuffers + unsigned int vertexStrideInBytes + unsigned int numVertices + const CUdeviceptr *radiusBuffers + unsigned int radiusStrideInBytes + int singleRadius + const unsigned int *flags + unsigned int numSbtRecords + CUdeviceptr sbtIndexOffsetBuffer + unsigned int sbtIndexOffsetSizeInBytes + unsigned int sbtIndexOffsetStrideInBytes + unsigned int primitiveIndexOffset + + cdef struct OptixBuildInput: + OptixBuildInputType type + # union + OptixBuildInputTriangleArray triangleArray + OptixBuildInputCurveArray curveArray + OptixBuildInputSphereArray sphereArray + OptixBuildInputCustomPrimitiveArray customPrimitiveArray + OptixBuildInputInstanceArray instanceArray + ELSE: + cdef struct OptixBuildInput: + OptixBuildInputType type + # union + OptixBuildInputTriangleArray triangleArray + OptixBuildInputCurveArray curveArray + OptixBuildInputCustomPrimitiveArray customPrimitiveArray + OptixBuildInputInstanceArray instanceArray + cdef struct OptixAccelBufferSizes: size_t outputSizeInBytes size_t tempSizeInBytes size_t tempUpdateSizeInBytes + cdef enum OptixAccelPropertyType: OPTIX_PROPERTY_TYPE_COMPACTED_SIZE, OPTIX_PROPERTY_TYPE_AABBS, + cdef struct OptixAccelEmitDesc: CUdeviceptr result OptixAccelPropertyType type + ctypedef uintptr_t OptixTraversableHandle + cdef struct OptixAccelRelocationInfo: unsigned long long info[4] + cdef enum OptixTraversableType: OPTIX_TRAVERSABLE_TYPE_STATIC_TRANSFORM, OPTIX_TRAVERSABLE_TYPE_MATRIX_MOTION_TRANSFORM, @@ -301,6 +360,17 @@ cdef class BuildInputCurveArray(BuildInputArray): cdef object _d_index_buffer +IF _OPTIX_VERSION > 70400: + cdef class BuildInputSphereArray(BuildInputArray): + cdef OptixBuildInputSphereArray build_input + cdef list _d_vertex_buffers + cdef vector[CUdeviceptr] _d_vertex_buffer_ptrs + cdef list _d_radius_buffers + cdef vector[CUdeviceptr] _d_radius_buffer_ptrs + cdef object _d_sbt_offset_buffer + cdef vector[unsigned int] _flags + + cdef class Instance(OptixObject): cdef OptixInstance instance cdef AccelerationStructure _traversable diff --git a/optix/build.pyx b/optix/build.pyx index 4cdb66a..ed2593f 100644 --- a/optix/build.pyx +++ b/optix/build.pyx @@ -23,6 +23,7 @@ __all__ = ['GeometryFlags', 'CurveEndcapFlags' ] + class GeometryFlags(IntEnum): """ Wraps the OptixGeometryFlags enum. @@ -31,6 +32,9 @@ class GeometryFlags(IntEnum): DISABLE_ANYHIT = OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT, REQUIRE_SINGLE_ANYHIT_CALL = OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL + IF _OPTIX_VERSION_MAJOR == 7 and _OPTIX_VERSION_MINOR > 4: + DISABLE_TRIANGLE_FACE_CULLING = OPTIX_GEOMETRY_FLAG_DISABLE_TRIANGLE_FACE_CULLING + class BuildFlags(IntFlag): """ @@ -45,34 +49,29 @@ class BuildFlags(IntFlag): ALLOW_RANDOM_INSTANCE_ACCESS = OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS, -IF _OPTIX_VERSION > 70300: # switch to new instance flags - class PrimitiveType(IntEnum): - """ - Wraps the OptixPrimitiveType enum. - """ - CUSTOM = OPTIX_PRIMITIVE_TYPE_CUSTOM, - ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, - ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, - ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, - ROUND_CATMULLROM = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM, - TRIANGLE = OPTIX_PRIMITIVE_TYPE_TRIANGLE - - class CurveEndcapFlags(IntEnum): +class PrimitiveType(IntEnum): + """ + Wraps the OptixPrimitiveType enum. + """ + CUSTOM = OPTIX_PRIMITIVE_TYPE_CUSTOM, + ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, + ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, + ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR + + IF _OPTIX_VERSION > 70300: # switch to new instance flags + ROUND_CATMULLROM = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM + IF _OPTIX_VERSION > 70400: # switch to new instance flags + SPHERE = OPTIX_PRIMITIVE_TYPE_SPHERE + + TRIANGLE = OPTIX_PRIMITIVE_TYPE_TRIANGLE + + +class CurveEndcapFlags(IntEnum): + IF _OPTIX_VERSION > 70300: # switch to new instance flags DEFAULT = OPTIX_CURVE_ENDCAP_DEFAULT, ON = OPTIX_CURVE_ENDCAP_ON -ELSE: - class CurveEndcapFlags(IntEnum): - DEFAULT = 0 # only for interface. Ignored for Optix versions below 7.4 - - class PrimitiveType(IntEnum): - """ - Wraps the OptixPrimitiveType enum. - """ - CUSTOM = OPTIX_PRIMITIVE_TYPE_CUSTOM, - ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_QUADRATIC_BSPLINE, - ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE, - ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR, - TRIANGLE = OPTIX_PRIMITIVE_TYPE_TRIANGLE + ELSE: + DEFAULT = 0 # only for interface. Ignored for Optix versions below 7.4 class InstanceFlags(IntFlag): @@ -325,7 +324,6 @@ cdef class BuildInputCustomPrimitiveArray(BuildInputArray): return self.build_input.numPrimitives - cdef class BuildInputCurveArray(BuildInputArray): """ BuildInputArray for curve inputs. This class wraps the OptixBuildInputCurveArray struct. @@ -430,6 +428,109 @@ cdef class BuildInputCurveArray(BuildInputArray): return self.build_input.numPrimitives +IF _OPTIX_VERSION > 70400: + cdef class BuildInputSphereArray(BuildInputArray): + """ + BuildInputArray for a sphere. This class wraps the OptixBuildInputSphereArray struct. + In Contrast to the behavior of the Optix C++ API, this Python class will automatically convert all numpy.ndarrays + to cupy.ndarrays and keep track of them. + + Parameters + ---------- + vertex_buffers: + List of vertex buffers (one for each motion step) or a single array. + All arrays will be converted to cupy.ndarrays before any further processing. + index_buffer: ndarray, optional + A single 2d array containing the indices of all triangles or None + num_sbt_records: int + The number of records in the ShaderBindingTable for this geometry + flags: GeometryFlags + Flags to use in this input for each motionstep + sbt_record_offset_buffer: ndarray, optional + Offsets into the ShaderBindingTable record for each primitive (index) or None + pre_transform: ndarray(3,4) or None + A transform to apply prior to processing + primitive_index_offset: int + The offset applied to the primitive index in device code + """ + def __init__(self, + vertex_buffers, + radius_buffers, + num_sbt_records = 1, + flags = None, + sbt_record_offset_buffer = None, + pre_transform = None, + primitive_index_offset = 0 + ): + + self._d_vertex_buffers = [cp.asarray(vb) for vb in ensure_iterable(vertex_buffers)] + self._d_vertex_buffer_ptrs.reserve(len(self._d_vertex_buffers)) + + self._d_radius_buffers = [cp.asarray(vb) for vb in ensure_iterable(radius_buffers)] + self._d_radius_buffer_ptrs.reserve(len(self._d_radius_buffers)) + + if len(self._d_radius_buffers) != len(self._d_vertex_buffers): + raise ValueError("Argument radius_buffers must have the same number of arrays as vertex_buffers.") + + if len(self._d_vertex_buffers) == 0: + raise ValueError("BuildInputSphereArray cannot be empty.") + + dtype = self._d_vertex_buffers[0].dtype + shape = self._d_vertex_buffers[0].shape + strides = self._d_vertex_buffers[0].strides + + radius_dtype = self._d_radius_buffers[0].dtype + radius_shape = self._d_radius_buffers[0].shape + strides = self._d_radius_buffers[0].strides + + for vb, rb in zip(self._d_vertex_buffers, self._d_radius_buffers): + if vb.dtype != dtype or vb.shape != shape or vb.strides != strides: + raise ValueError("All vertex buffers must have the same size and dtype.") + self._d_vertex_buffer_ptrs.push_back(vb.data.ptr) + + if rb.dtype != dtype or rb.shape != shape or rb.strides != strides: + raise ValueError("All radius buffers must have the same size and dtype.") + self._d_radius_buffer_ptrs.push_back(rb.data.ptr) + + self.build_input.vertexBuffers = self._d_vertex_buffer_ptrs.const_data() + self.build_input.radiusBuffers = self._d_radius_buffer_ptrs.const_data() + + self.build_input.vertexStrideInBytes = self._d_vertex_buffers[0].strides[0] + self.build_input.radiusStrideInBytes = self._d_radius_buffers[0].strides[0] + + self.build_input.numVertices = shape[0] + self.build_input.singleRadius = 1 if self._d_radius_buffers[0].shape[0] == 1 else 0 + + self.build_input.numSbtRecords = num_sbt_records + self._flags.resize(num_sbt_records) + + if flags is None: + for i in range(num_sbt_records): + self._flags[i] = OPTIX_GEOMETRY_FLAG_NONE + else: + for i in range(num_sbt_records): + self._flags[i] = flags[i].value + + self.build_input.flags = self._flags.data() + + + if sbt_record_offset_buffer is not None: + self._d_sbt_offset_buffer = cp.asarray(sbt_record_offset_buffer).ravel() + self.build_input.sbtIndexOffsetBuffer = self._d_sbt_offset_buffer.data.ptr + itemsize = self._d_sbt_offset_buffer.itemsize + if itemsize > 4: + raise ValueError("Only 32 bit allowed at max") + self.build_input.sbtIndexOffsetSizeInBytes = itemsize + self.build_input.sbtIndexOffsetStrideInBytes = self._d_sbt_offset_buffer.strides[0] + else: + self.build_input.sbtIndexOffsetBuffer = 0 + self.build_input.sbtIndexOffsetStrideInBytes = 0 + self.build_input.sbtIndexOffsetSizeInBytes = 0 + + self.build_input.primitiveIndexOffset = primitive_index_offset + + __all__.append('BuildInputSphereArray') + cdef class Instance(OptixObject): """ Class representing a single instance (another AccelerationStructure) for use in a Instance level AccelerationStructure. diff --git a/optix/denoiser.pxd b/optix/denoiser.pxd index 5172fce..7e4082f 100644 --- a/optix/denoiser.pxd +++ b/optix/denoiser.pxd @@ -6,7 +6,17 @@ from libc.stdint cimport uintptr_t from libcpp cimport bool cdef extern from "optix_includes.h" nogil: - IF _OPTIX_VERSION > 70300: + IF _OPTIX_VERSION > 70400: + cdef enum OptixDenoiserModelKind: + OPTIX_DENOISER_MODEL_KIND_LDR + OPTIX_DENOISER_MODEL_KIND_HDR + OPTIX_DENOISER_MODEL_KIND_AOV + OPTIX_DENOISER_MODEL_KIND_TEMPORAL + OPTIX_DENOISER_MODEL_KIND_TEMPORAL_AOV + OPTIX_DENOISER_MODEL_KIND_UPSCALE2X + OPTIX_DENOISER_MODEL_KIND_TEMPORAL_UPSCALE2X + + ELIF _OPTIX_VERSION > 70300: cdef enum OptixDenoiserModelKind: OPTIX_DENOISER_MODEL_KIND_LDR OPTIX_DENOISER_MODEL_KIND_HDR @@ -25,17 +35,40 @@ cdef extern from "optix_includes.h" nogil: unsigned int guideAlbedo unsigned int guideNormal - cdef struct OptixDenoiserSizes: - size_t stateSizeInBytes - size_t withOverlapScratchSizeInBytes - size_t withoutOverlapScratchSizeInBytes - unsigned int overlapWindowSizeInPixels + IF _OPTIX_VERSION > 70400: + cdef struct OptixDenoiserSizes: + size_t stateSizeInBytes + size_t withOverlapScratchSizeInBytes + size_t withoutOverlapScratchSizeInBytes + unsigned int overlapWindowSizeInPixels + size_t computeAverageColorSizeInBytes + size_t computeIntensitySizeInBytes + size_t internalGuideLayerPixelSizeInBytes + + cdef enum OptixDenoiserAlphaMode: + OPTIX_DENOISER_ALPHA_MODE_COPY, + OPTIX_DENOISER_ALPHA_MODE_ALPHA_AS_AOV, + OPTIX_DENOISER_ALPHA_MODE_FULL_DENOISE_PASS + + cdef struct OptixDenoiserParams: + OptixDenoiserAlphaMode denoiseAlpha + CUdeviceptr hdrIntensity + float blendFactor + CUdeviceptr hdrAverageColor + unsigned int temporalModeUsePreviousLayers + ELSE: + cdef struct OptixDenoiserSizes: + size_t stateSizeInBytes + size_t withOverlapScratchSizeInBytes + size_t withoutOverlapScratchSizeInBytes + unsigned int overlapWindowSizeInPixels + + cdef struct OptixDenoiserParams: + unsigned int denoiseAlpha + CUdeviceptr hdrIntensity + float blendFactor + CUdeviceptr hdrAverageColor - cdef struct OptixDenoiserParams: - unsigned int denoiseAlpha - CUdeviceptr hdrIntensity - float blendFactor - CUdeviceptr hdrAverageColor cdef enum OptixPixelFormat: OPTIX_PIXEL_FORMAT_HALF2 @@ -60,10 +93,18 @@ cdef extern from "optix_includes.h" nogil: OptixImage2D previousOutput OptixImage2D output - cdef struct OptixDenoiserGuideLayer: - OptixImage2D albedo - OptixImage2D normal - OptixImage2D flow + IF _OPTIX_VERSION > 70400: + cdef struct OptixDenoiserGuideLayer: + OptixImage2D albedo + OptixImage2D normal + OptixImage2D flow + OptixImage2D previousOutputInternalGuideLayer + OptixImage2D outputInternalGuideLayer + ELSE: + cdef struct OptixDenoiserGuideLayer: + OptixImage2D albedo + OptixImage2D normal + OptixImage2D flow ctypedef struct OptixDenoiser: pass diff --git a/optix/denoiser.pyx b/optix/denoiser.pyx index a751dea..d45439f 100644 --- a/optix/denoiser.pyx +++ b/optix/denoiser.pyx @@ -1,4 +1,5 @@ # distutils: language = c++ +import enum from .common cimport optix_check_return, optix_init from .context cimport DeviceContext @@ -14,6 +15,14 @@ __all__ = ['DenoiserModelKind', 'Denoiser' ] +IF _OPTIX_VERSION > 70400: + class DenoiserAlphaMode(enum.IntEnum): + COPY = OPTIX_DENOISER_ALPHA_MODE_COPY + ALPHA_AS_AOV = OPTIX_DENOISER_ALPHA_MODE_ALPHA_AS_AOV + FULL_DENOISE_PASS = OPTIX_DENOISER_ALPHA_MODE_FULL_DENOISE_PASS + + __all__.append('DenoiserAlphaMode') + class DenoiserModelKind(IntEnum): """ Wraps the OptixDenoiserModelKind enum. @@ -25,9 +34,14 @@ class DenoiserModelKind(IntEnum): IF _OPTIX_VERSION > 70300: TEMPORAL_AOV = OPTIX_DENOISER_MODEL_KIND_TEMPORAL_AOV + IF _OPTIX_VERSION > 70400: + UPSCALE2X = OPTIX_DENOISER_MODEL_KIND_UPSCALE2X + TEMPORAL_UPSCALE2X = OPTIX_DENOISER_MODEL_KIND_TEMPORAL_UPSCALE2X def temporal_mode(self): - IF _OPTIX_VERSION > 70300: + IF _OPTIX_VERSION > 70400: + return self == self.TEMPORAL or self==self.TEMPORAL_AOV or self == self.TEMPORAL_UPSCALE2X + ELIF _OPTIX_VERSION > 70300: return self == self.TEMPORAL or self == self.TEMPORAL_AOV ELSE: return self == self.TEMPORAL @@ -144,6 +158,9 @@ cdef class Denoiser(OptixContextObject): self.kp_mode = kp_mode self.tile_size = tile_size self._scratch_size = 0 + + self._guide_layer_scratch_size = 0 + self._average_color_scratch_size = 0 self._state_size = 0 if model_kind is not None: @@ -188,6 +205,13 @@ cdef class Denoiser(OptixContextObject): self._state_size = return_sizes.stateSizeInBytes self._d_state = cp.cuda.alloc(return_sizes.stateSizeInBytes) + IF _OPTIX_VERSION > 70400: + self._intensity_scratch_size = return_sizes.computeIntensitySizeInBytes + self._average_color_scratch_size = return_sizes.computeAverageColorSizeInBytes + ELSE: + self._intensity_scratch_size = self._scratch_size + self._average_color_scratch_size = self._scratch_size + cdef uintptr_t c_stream = 0 if stream is not None: @@ -221,9 +245,10 @@ cdef class Denoiser(OptixContextObject): normals=None, flow=None, outputs=None, - denoise_alpha=False, + denoise_alpha=None, blend_factor=0.0, - stream=None): + stream=None, + temporal_use_previous_layer=False): accepted_input_types = (PixelFormat.FLOAT3, PixelFormat.FLOAT3, PixelFormat.HALF3, PixelFormat.HALF4) inputs = [Image2D(inp, require_type=accepted_input_types) for inp in ensure_iterable(inputs)] @@ -284,11 +309,20 @@ cdef class Denoiser(OptixContextObject): self._init_denoiser(len(inputs), input_size, stream=stream) cdef OptixDenoiserParams params - params.denoiseAlpha = 1 if denoise_alpha else 0 params.hdrIntensity = self._d_intensity.ptr if self._d_intensity is not None else 0 params.hdrAverageColor = self._d_avg_color.ptr if self._d_avg_color is not None else 0 params.blendFactor = blend_factor + IF _OPTIX_VERSION > 70400: + params.temporalModeUsePreviousLayers = 1 if temporal_use_previous_layer and temporal_mode else 0 + if denoise_alpha is None: + denoise_alpha = DenoiserAlphaMode.COPY + + assert isinstance(denoise_alpha, DenoiserAlphaMode), "Optix >7.5 changed this from a boolean variable into an enum" + params.denoiseAlpha = denoise_alpha.value + ELSE: + params.denoiseAlpha = 1 if denoise_alpha else 0 + cdef uintptr_t c_stream = 0 @@ -297,13 +331,14 @@ cdef class Denoiser(OptixContextObject): # determinhe intensity and avg color if needed if self._d_intensity is not None: + optix_check_return(optixDenoiserComputeIntensity( self.denoiser, c_stream, &layers[0].input, self._d_intensity.ptr, self._d_scratch.ptr, - self._scratch_size)) + self._intensity_scratch_size)) if self._d_avg_color is not None: optix_check_return(optixDenoiserComputeAverageColor( @@ -312,7 +347,7 @@ cdef class Denoiser(OptixContextObject): &layers[0].input, self._d_avg_color, self._d_scratch.ptr, - self._scratch_size)) + self._average_color_scratch_size)) if self.tile_size is None: diff --git a/optix/module.pyx b/optix/module.pyx index 9333fbc..c380413 100644 --- a/optix/module.pyx +++ b/optix/module.pyx @@ -217,6 +217,8 @@ cdef class Module(OptixContextObject): """ Class representing a Optix Cuda program that will be called during pipeline execution. Wraps the OptixModule struct. + TODO: support creating modules through nvcc instead of nvrtc as well to support the new optix-ir format in 7.5 + Parameters ---------- context: DeviceContext @@ -406,6 +408,7 @@ cdef class Module(OptixContextObject): flags = list(compile_flags) # get cuda and optix_include_paths cuda_include_path = get_cuda_include_path() + print("cuda path", cuda_include_path) optix_include_path = get_optix_include_path() flags.extend([f'-I{cuda_include_path}', f'-I{optix_include_path}']) diff --git a/optix/path_utility.py b/optix/path_utility.py index 756a756..286c0c4 100644 --- a/optix/path_utility.py +++ b/optix/path_utility.py @@ -38,7 +38,9 @@ def get_path(key): return tuple() -def search_on_path(filenames, keys=('PATH',)): +def search_on_path(filenames, keys=None): + if keys is None: + keys = ('PATH',) for p in chain(*[get_path(key) for key in keys]): for filename in filenames: full = os.path.abspath(os.path.join(p, filename)) @@ -47,7 +49,7 @@ def search_on_path(filenames, keys=('PATH',)): return None -def get_cuda_path(environment_variable='CUDA_ROOT'): +def get_cuda_path(environment_variable=None): global _cuda_path_cache # Use a magic word to represent the cache not filled because None is a @@ -55,7 +57,8 @@ def get_cuda_path(environment_variable='CUDA_ROOT'): if _cuda_path_cache != 'NOT_INITIALIZED': return _cuda_path_cache - nvcc_path = search_on_path(('nvcc', 'nvcc.exe'), keys=(environment_variable, 'PATH')) + nvcc_path = search_on_path(('nvcc', 'nvcc.exe'), keys=(environment_variable, 'PATH') if environment_variable is not + None else ('PATH',)) cuda_path_default = None if nvcc_path is not None: cuda_path_default = os.path.normpath( @@ -70,7 +73,7 @@ def get_cuda_path(environment_variable='CUDA_ROOT'): return _cuda_path_cache -def get_cuda_include_path(environment_variable='CUDA_ROOT'): +def get_cuda_include_path(environment_variable=None): cuda_path = get_cuda_path(environment_variable=environment_variable) if cuda_path is None: return None @@ -81,7 +84,7 @@ def get_cuda_include_path(environment_variable='CUDA_ROOT'): return None -def get_optix_path(environment_variable='OPTIX_PATH'): +def get_optix_path(path_hint=None, environment_variable=None): global _optix_path_cache # Use a magic word to represent the cache not filled because None is a @@ -89,14 +92,20 @@ def get_optix_path(environment_variable='OPTIX_PATH'): if _optix_path_cache != 'NOT_INITIALIZED': return _optix_path_cache - # prefer the dedicated environment variable - optix_header_path = search_on_path(('include/optix.h',), keys=(environment_variable,)) - if optix_header_path is None: - # search on the default path - optix_header_path = search_on_path(('../optix/include/optix.h',), keys=('PATH',)) + if path_hint is None: + # prefer the dedicated environment variable + optix_header_path = search_on_path(('include/optix.h',), keys=(environment_variable,) if environment_variable is not + None else None) + if optix_header_path is None: + # search on the default path + optix_header_path = search_on_path(('../optix/include/optix.h',), keys=('PATH',)) - if optix_header_path is not None: - optix_header_path = os.path.normpath(os.path.join(os.path.dirname(optix_header_path), '..')) + if optix_header_path is not None: + optix_header_path = os.path.normpath(os.path.join(os.path.dirname(optix_header_path), '..')) + else: + optix_header_path = path_hint + if not os.path.exists(os.path.join(optix_header_path, "include/optix.h")): + raise ValueError(f"Path {optix_header_path} does not contain an optix installation.") if optix_header_path is not None: _optix_path_cache = optix_header_path @@ -106,7 +115,7 @@ def get_optix_path(environment_variable='OPTIX_PATH'): return _optix_path_cache -def get_optix_include_path(environment_variable='OPTIX_PATH'): +def get_optix_include_path(environment_variable=None): optix_path = get_optix_path(environment_variable=environment_variable) if optix_path is None: return None diff --git a/optix/pipeline.pxd b/optix/pipeline.pxd index 0806015..47f46fb 100644 --- a/optix/pipeline.pxd +++ b/optix/pipeline.pxd @@ -23,15 +23,16 @@ cdef extern from "optix_includes.h" nogil: OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_GAS, OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING - - IF _OPTIX_VERSION > 70300: # switch to new instance flags - cdef enum OptixCompileDebugLevel: - OPTIX_COMPILE_DEBUG_LEVEL_DEFAULT, - OPTIX_COMPILE_DEBUG_LEVEL_NONE, - OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL, - OPTIX_COMPILE_DEBUG_LEVEL_MODERATE, - OPTIX_COMPILE_DEBUG_LEVEL_FULL - + IF _OPTIX_VERSION > 70400: # switch to new primitive type flags + cdef enum OptixPrimitiveTypeFlags: + OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM, + OPTIX_PRIMITIVE_TYPE_FLAGS_SPHERE, + OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE, + ELIF _OPTIX_VERSION > 70300: cdef enum OptixPrimitiveTypeFlags: OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, @@ -39,6 +40,22 @@ cdef extern from "optix_includes.h" nogil: OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM, OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE, + ELSE: + cdef enum OptixPrimitiveTypeFlags: + OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, + OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, + OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE + + + IF _OPTIX_VERSION > 70300: # switch to new compile debug level + cdef enum OptixCompileDebugLevel: + OPTIX_COMPILE_DEBUG_LEVEL_DEFAULT, + OPTIX_COMPILE_DEBUG_LEVEL_NONE, + OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL, + OPTIX_COMPILE_DEBUG_LEVEL_MODERATE, + OPTIX_COMPILE_DEBUG_LEVEL_FULL ELSE: cdef enum OptixCompileDebugLevel: OPTIX_COMPILE_DEBUG_LEVEL_DEFAULT, @@ -46,12 +63,7 @@ cdef extern from "optix_includes.h" nogil: OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO, OPTIX_COMPILE_DEBUG_LEVEL_FULL - cdef enum OptixPrimitiveTypeFlags: - OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, - OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, - OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, - OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, - OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE, + cdef struct OptixPipelineCompileOptions: diff --git a/optix/pipeline.pyx b/optix/pipeline.pyx index c471b0d..43ce269 100644 --- a/optix/pipeline.pyx +++ b/optix/pipeline.pyx @@ -36,7 +36,25 @@ class TraversableGraphFlags(IntFlag): ALLOW_SINGLE_LEVEL_INSTANCING = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING -IF _OPTIX_VERSION > 70300: # switch to new instance flags +class PrimitiveTypeFlags(IntFlag): + """ + Wraps the OptixPrimitiveTypeFlags enum. + """ + DEFAULT = 0, # corresponds to CUSTOM | TRIANGLE + CUSTOM = OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, + ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, + ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, + ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR + + # switch to new primitive type flags + IF _OPTIX_VERSION > 70300: # switch to new compile debug level flags + ROUND_CATMULLROM = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM + IF _OPTIX_VERSION > 70400: + SPHERE = OPTIX_PRIMITIVE_TYPE_FLAGS_SPHERE + TRIANGLE = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE # fixes negative number error + + +IF _OPTIX_VERSION > 70300: # switch to new compile debug level flags class CompileDebugLevel(IntEnum): """ Wraps the OptixCompileDebugLevel enum. @@ -46,18 +64,6 @@ IF _OPTIX_VERSION > 70300: # switch to new instance flags MINIMAL = OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL, MODERATE = OPTIX_COMPILE_DEBUG_LEVEL_MODERATE, FULL = OPTIX_COMPILE_DEBUG_LEVEL_FULL - - class PrimitiveTypeFlags(IntFlag): - """ - Wraps the OptixPrimitiveTypeFlags enum. - """ - DEFAULT = 0, # corresponds to CUSTOM | TRIANGLE - CUSTOM = OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, - ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, - ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, - ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, - ROUND_CATMULLROM = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM, - TRIANGLE = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE # fixes negative number error ELSE: class CompileDebugLevel(IntEnum): """ @@ -68,17 +74,6 @@ ELSE: LINEINFO = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO, FULL = OPTIX_COMPILE_DEBUG_LEVEL_FULL - class PrimitiveTypeFlags(IntFlag): - """ - Wraps the OptixPrimitiveTypeFlags enum. - """ - DEFAULT = 0, # corresponds to CUSTOM | TRIANGLE - CUSTOM = OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM, - ROUND_QUADRATIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_QUADRATIC_BSPLINE, - ROUND_CUBIC_BSPLINE = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE, - ROUND_LINEAR = OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_LINEAR, - TRIANGLE = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE - cdef class PipelineCompileOptions(OptixObject): """