Skip to content

Commit 681e046

Browse files
rparolinclaude
andcommitted
cuda.core: address NVIDIA#2188 review feedback — copy parity + cuda.core.textures namespace
Three items from the NVIDIA#2188 design review (Andy-Jost): A+B. CUDAArray.copy_from / copy_to now match the Buffer copy API: - Accept Stream | GraphBuilder (via Stream_accept), so array copies can be captured into a CUDA graph — previously only a concrete Stream was accepted. - copy_to returns the destination object, for parity with Buffer.copy_to. The internal _copy3d helper now takes an already-coerced Stream. C. Group the texture/surface object model under a new cuda.core.textures namespace instead of the flat cuda.core namespace, before v1.1.0 ships (it is hard to move post-release). Adds cuda/core/textures.py re-exporting CUDAArray, ArrayFormat, MipmappedArray, ResourceDescriptor, TextureDescriptor, TextureObject, SurfaceObject, AddressMode, FilterMode, ReadMode; removes the flat exports from cuda.core.__init__ (grouped-only — no deprecation needed pre-release); migrates the texture/surface examples, texture_sample, and the docs api.rst section to the new namespace. Tests: update the stream-rejection match; add copy_to-returns-dst and a GraphBuilder-capture test for CUDAArray copies. Verified: texture/surface suite 65 passed; full cuda_core suite 3449 passed / 230 skipped / 3 xfailed; all examples byte-compile; cuda.core.textures exports the 10 symbols and cuda.core.CUDAArray is gone. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
1 parent e087f0b commit 681e046

23 files changed

Lines changed: 242 additions & 118 deletions

‎cuda_core/cuda/core/__init__.py‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ class _PatchedProperty(metaclass=_PatchedPropMeta):
6969

7070

7171
from cuda.core import checkpoint, system, utils
72-
from cuda.core._array import ArrayFormat, CUDAArray
7372
from cuda.core._context import Context, ContextOptions
7473
from cuda.core._device import Device
7574
from cuda.core._device_resources import (
@@ -100,7 +99,6 @@ class _PatchedProperty(metaclass=_PatchedPropMeta):
10099
VirtualMemoryResource,
101100
VirtualMemoryResourceOptions,
102101
)
103-
from cuda.core._mipmapped_array import MipmappedArray
104102
from cuda.core._module import Kernel, ObjectCode
105103
from cuda.core._program import Program, ProgramOptions
106104
from cuda.core._stream import (
@@ -109,18 +107,14 @@ class _PatchedProperty(metaclass=_PatchedPropMeta):
109107
Stream,
110108
StreamOptions,
111109
)
112-
from cuda.core._surface import SurfaceObject
113110
from cuda.core._tensor_map import TensorMapDescriptor, TensorMapDescriptorOptions
114-
from cuda.core._texture import (
115-
AddressMode,
116-
FilterMode,
117-
ReadMode,
118-
ResourceDescriptor,
119-
TextureDescriptor,
120-
TextureObject,
121-
)
122111

123112
# isort: split
113+
# Texture/surface types live under the cuda.core.textures namespace (not the
114+
# flat cuda.core namespace); import the subpackage so it is available as
115+
# `cuda.core.textures` after `import cuda.core`.
116+
import cuda.core.textures
117+
124118
# Must come after the cuda.core._* extension imports above: loading graph
125119
# earlier interacts badly with the merged-wheel __path__ rewrite and leaves
126120
# Graph/GraphBuilder/GraphCompleteOptions/GraphDebugPrintOptions missing from

‎cuda_core/cuda/core/_array.pyi‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,17 @@ class CUDAArray:
106106
"""Return (width_bytes, height, depth) for cuMemcpy3D, with height/depth
107107
normalized to >=1 for lower-rank arrays."""
108108

109-
def copy_from(self, src, *, stream):
109+
def copy_from(self, src, *, stream) -> None:
110110
"""Copy a full-array's worth of data into this array.
111111
112112
Parameters
113113
----------
114114
src : Buffer or buffer-protocol object
115115
Source data. Must contain at least ``self.size_bytes`` bytes
116116
of contiguous data.
117-
stream : Stream
118-
Stream to issue the copy on.
117+
stream : Stream or GraphBuilder
118+
Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
119+
is accepted so the copy can be captured into a graph.
119120
"""
120121

121122
def copy_to(self, dst, *, stream):
@@ -126,8 +127,13 @@ class CUDAArray:
126127
dst : Buffer or writable buffer-protocol object
127128
Destination. Must have at least ``self.size_bytes`` bytes of
128129
writable, contiguous space.
129-
stream : Stream
130-
Stream to issue the copy on.
130+
stream : Stream or GraphBuilder
131+
Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
132+
is accepted so the copy can be captured into a graph.
133+
134+
Returns
135+
-------
136+
The ``dst`` object, for parity with :meth:`Buffer.copy_to`.
131137
"""
132138

133139
@property

‎cuda_core/cuda/core/_array.pyx‎

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ from cuda.core._resource_handles cimport (
1919
create_array_handle_ref,
2020
get_last_error,
2121
)
22-
from cuda.core._stream cimport Stream
22+
from cuda.core._stream cimport Stream, Stream_accept
2323
from cuda.core._utils.cuda_utils cimport (
2424
HANDLE_RETURN,
2525
_get_current_device_id,
@@ -188,21 +188,19 @@ cdef int _fill_linear_endpoint(
188188
)
189189

190190

191-
cdef _copy3d(CUDAArray arr, object other, object stream, bint to_array):
191+
cdef _copy3d(CUDAArray arr, object other, Stream stream, bint to_array):
192192
"""Issue a full-array async 3D memcpy between ``arr`` and ``other``.
193193
194194
Direction is determined by ``to_array``: True copies *into* arr, False
195-
copies *out of* arr.
195+
copies *out of* arr. ``stream`` must already be a concrete :class:`Stream`
196+
(callers coerce via :func:`Stream_accept`).
196197
"""
197198
cdef cydriver.CUDA_MEMCPY3D params
198199
cdef cpython.Py_buffer pybuf
199200
cdef int got_buffer = 0
200201
cdef intptr_t stream_handle
201202
cdef cydriver.CUstream c_stream
202203

203-
if not isinstance(stream, Stream):
204-
raise TypeError(f"stream must be a Stream, got {type(stream).__name__}")
205-
206204
memset(&params, 0, sizeof(params))
207205
width_bytes, height, depth = arr._extent_bytes()
208206
params.WidthInBytes = <size_t>width_bytes
@@ -369,18 +367,19 @@ cdef class CUDAArray:
369367
cdef size_t d = <size_t>(self._shape[2] if rank >= 3 else 1)
370368
return w, h, d
371369

372-
def copy_from(self, src, *, stream):
370+
def copy_from(self, src, *, stream) -> None:
373371
"""Copy a full-array's worth of data into this array.
374372

375373
Parameters
376374
----------
377375
src : Buffer or buffer-protocol object
378376
Source data. Must contain at least ``self.size_bytes`` bytes
379377
of contiguous data.
380-
stream : Stream
381-
Stream to issue the copy on.
378+
stream : Stream or GraphBuilder
379+
Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
380+
is accepted so the copy can be captured into a graph.
382381
"""
383-
_copy3d(self, src, stream, to_array=True)
382+
_copy3d(self, src, Stream_accept(stream), to_array=True)
384383

385384
def copy_to(self, dst, *, stream):
386385
"""Copy a full-array's worth of data out of this array.
@@ -390,10 +389,16 @@ cdef class CUDAArray:
390389
dst : Buffer or writable buffer-protocol object
391390
Destination. Must have at least ``self.size_bytes`` bytes of
392391
writable, contiguous space.
393-
stream : Stream
394-
Stream to issue the copy on.
392+
stream : Stream or GraphBuilder
393+
Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
394+
is accepted so the copy can be captured into a graph.
395+
396+
Returns
397+
-------
398+
The ``dst`` object, for parity with :meth:`Buffer.copy_to`.
395399
"""
396-
_copy3d(self, dst, stream, to_array=False)
400+
_copy3d(self, dst, Stream_accept(stream), to_array=False)
401+
return dst
397402

398403
@property
399404
def size_bytes(self):

‎cuda_core/cuda/core/textures.py‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
"""Texture and surface APIs for ``cuda.core``.
6+
7+
This subpackage groups the CUDA "Texture and Surface" object model — opaque
8+
array storage and the bindless texture/surface handles built on it — under a
9+
single namespace, mirroring how the CUDA driver documentation organizes them.
10+
11+
Import these types from here, e.g.::
12+
13+
from cuda.core.textures import CUDAArray, TextureObject, TextureDescriptor
14+
"""
15+
16+
from cuda.core._array import ArrayFormat, CUDAArray
17+
from cuda.core._mipmapped_array import MipmappedArray
18+
from cuda.core._surface import SurfaceObject
19+
from cuda.core._texture import (
20+
AddressMode,
21+
FilterMode,
22+
ReadMode,
23+
ResourceDescriptor,
24+
TextureDescriptor,
25+
TextureObject,
26+
)
27+
28+
__all__ = [
29+
"AddressMode",
30+
"ArrayFormat",
31+
"CUDAArray",
32+
"FilterMode",
33+
"MipmappedArray",
34+
"ReadMode",
35+
"ResourceDescriptor",
36+
"SurfaceObject",
37+
"TextureDescriptor",
38+
"TextureObject",
39+
]

‎cuda_core/docs/source/api.rst‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,15 @@ Textures and surfaces
165165
---------------------
166166

167167
CUDA arrays back bindless texture and surface objects for kernel-side sampled
168-
reads and typed load/store. :class:`CUDAArray` is allocated through
168+
reads and typed load/store. These types live in the :mod:`cuda.core.textures`
169+
namespace. :class:`CUDAArray` is allocated through
169170
:meth:`CUDAArray.from_descriptor` and bound through a :class:`ResourceDescriptor`
170171
factory; linear (1D) and row-pitched 2D :class:`Buffer` views as well as
171172
mipmapped allocations (:class:`MipmappedArray`) are also supported as texture
172173
backings.
173174

175+
.. currentmodule:: cuda.core.textures
176+
174177
.. autosummary::
175178
:toctree: generated/
176179

‎cuda_core/examples/gl_interop_bloom.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,21 +91,23 @@
9191
import numpy as np
9292

9393
from cuda.core import (
94-
AddressMode,
95-
ArrayFormat,
9694
Device,
97-
FilterMode,
9895
GraphicsResource,
9996
LaunchConfig,
100-
MipmappedArray,
10197
Program,
10298
ProgramOptions,
99+
launch,
100+
)
101+
from cuda.core.textures import (
102+
AddressMode,
103+
ArrayFormat,
104+
FilterMode,
105+
MipmappedArray,
103106
ReadMode,
104107
ResourceDescriptor,
105108
SurfaceObject,
106109
TextureDescriptor,
107110
TextureObject,
108-
launch,
109111
)
110112

111113
# ---------------------------------------------------------------------------

‎cuda_core/examples/gl_interop_caustics.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,22 @@
9292
import numpy as np
9393

9494
from cuda.core import (
95-
AddressMode,
96-
ArrayFormat,
97-
CUDAArray,
9895
Device,
99-
FilterMode,
10096
GraphicsResource,
10197
LaunchConfig,
10298
Program,
10399
ProgramOptions,
100+
launch,
101+
)
102+
from cuda.core.textures import (
103+
AddressMode,
104+
ArrayFormat,
105+
CUDAArray,
106+
FilterMode,
104107
ReadMode,
105108
ResourceDescriptor,
106109
TextureDescriptor,
107110
TextureObject,
108-
launch,
109111
)
110112

111113
# ---------------------------------------------------------------------------

‎cuda_core/examples/gl_interop_clouds.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,23 @@
9494
import numpy as np
9595

9696
from cuda.core import (
97-
AddressMode,
98-
ArrayFormat,
99-
CUDAArray,
10097
Device,
101-
FilterMode,
10298
GraphicsResource,
10399
LaunchConfig,
104100
Program,
105101
ProgramOptions,
102+
launch,
103+
)
104+
from cuda.core.textures import (
105+
AddressMode,
106+
ArrayFormat,
107+
CUDAArray,
108+
FilterMode,
106109
ReadMode,
107110
ResourceDescriptor,
108111
SurfaceObject,
109112
TextureDescriptor,
110113
TextureObject,
111-
launch,
112114
)
113115

114116
# ---------------------------------------------------------------------------

‎cuda_core/examples/gl_interop_fire.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,23 @@
8888
import numpy as np
8989

9090
from cuda.core import (
91-
AddressMode,
92-
ArrayFormat,
93-
CUDAArray,
9491
Device,
95-
FilterMode,
9692
GraphicsResource,
9793
LaunchConfig,
9894
Program,
9995
ProgramOptions,
96+
launch,
97+
)
98+
from cuda.core.textures import (
99+
AddressMode,
100+
ArrayFormat,
101+
CUDAArray,
102+
FilterMode,
100103
ReadMode,
101104
ResourceDescriptor,
102105
SurfaceObject,
103106
TextureDescriptor,
104107
TextureObject,
105-
launch,
106108
)
107109

108110
# ---------------------------------------------------------------------------

‎cuda_core/examples/gl_interop_fluid.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,23 @@
100100
import numpy as np
101101

102102
from cuda.core import (
103-
AddressMode,
104-
ArrayFormat,
105-
CUDAArray,
106103
Device,
107-
FilterMode,
108104
GraphicsResource,
109105
LaunchConfig,
110106
Program,
111107
ProgramOptions,
108+
launch,
109+
)
110+
from cuda.core.textures import (
111+
AddressMode,
112+
ArrayFormat,
113+
CUDAArray,
114+
FilterMode,
112115
ReadMode,
113116
ResourceDescriptor,
114117
SurfaceObject,
115118
TextureDescriptor,
116119
TextureObject,
117-
launch,
118120
)
119121

120122
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)