Skip to content

cuda.core.texture: API-style follow-up before v1.1.0 (#2292)#2307

Open
Andy-Jost wants to merge 13 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/texture-api-2292
Open

cuda.core.texture: API-style follow-up before v1.1.0 (#2292)#2307
Andy-Jost wants to merge 13 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/texture-api-2292

Conversation

@Andy-Jost

Copy link
Copy Markdown
Contributor

Summary

Addresses all seven API-style items in #2292 to settle the cuda.core.texture public surface before it ships in v1.1.0. These are naming/shape refinements to the texture/surface stack merged in #2095 (design #2188); there are no changes to the underlying CUDA behavior. Because the surface first ships in v1.1.0, the renames need no deprecation shims and the new/renamed entry points carry .. versionadded:: 1.1.0.

Developed as a sequence of reviewable commits (one per item group); the PR is intended to squash-merge.

Changes

  • Allocation shape → Device.create_* + XxxOptions (items 1, 2): replace the per-type classmethod factories with Device.create_opaque_array, Device.create_mipmapped_array, Device.create_texture_object, and Device.create_surface_object, each taking an options dataclass (OpaqueArrayOptions, MipmappedArrayOptions, TextureObjectOptions). This matches the create_stream/create_event + StreamOptions/EventOptions convention. The private _from_handle graphics-interop escape hatch is retained.
  • Rename TextureDescriptorTextureObjectOptions (item 2): CUDA_TEXTURE_DESC is pure creation input, so the type follows the XxxOptions convention rather than the driver's "descriptor" naming.
  • format accepts NumPy dtypes (item 3): array/mipmap creation and ResourceDescriptor.from_linear/from_pitch2d now accept an ArrayFormatType, a plain str, or a NumPy dtype object, mirroring TensorMapDescriptorOptions.data_type.
  • Enums → cuda.core.typing as StrEnum (item 4): ArrayFormat/AddressMode/FilterMode/ReadMode become ArrayFormatType/AddressModeType/FilterModeType/ReadModeType in cuda.core.typing, with semantic string values and the Type suffix, matching every other cuda.core enum. Plain strings are accepted anywhere an enum is expected.
  • ResourceDescriptor.from_arrayfrom_opaque_array (item 5): removes the "array" ambiguity that the ArrayOpaqueArray rename was meant to eliminate.
  • Drop SurfaceObject.from_array sugar (item 6): a surface is now built from an explicit ResourceDescriptor.from_opaque_array(...), consistent with the single-entry-point rule.
  • OpaqueArray.element_sizeelement_bytes (item 7): the accessor returns a byte count, matching size_bytes / pitch_bytes.

Docs (api.rst, api_private.rst), the texture tests, and the four texture examples are updated throughout.

Test Coverage

  • Updated tests/test_texture_surface.py for the new API; negative-path tests reflect that validation now fires at options construction (ValueError) rather than at object creation.
  • Added tests for the NumPy-dtype and str format paths (marked @pytest.mark.agent_authored).

Related Work

Closes #2292. Follow-up to #2095 (design #2188).

Notes

CI will build and run the tests. Local build/run was not possible on the dev machine (no GPU); pre-commit run --all-files passes.

Andy-Jost added 7 commits July 6, 2026 16:42
…ze -> element_bytes (NVIDIA#2292)

Addresses items 5 and 7 of the pre-v1.1.0 texture API-style review.

- ResourceDescriptor.from_array -> ResourceDescriptor.from_opaque_array:
  the Array -> OpaqueArray rename removed "array" ambiguity, so the factory
  name should follow suit.
- OpaqueArray.element_size -> OpaqueArray.element_bytes: the accessor returns
  a byte count, matching the _bytes convention already used by size_bytes and
  pitch_bytes.

Both are renames of APIs not yet released (first ship in v1.1.0), so no
deprecation shim is needed; the new names carry a versionadded:: 1.1.0 note.
Call sites in the texture tests and the four texture examples are updated.
…VIDIA#2292)

Addresses item 4 of the pre-v1.1.0 texture API-style review.

The texture/surface enums were IntEnum subclasses backed by cydriver.CU_*
values, defined in the cuda.core.texture root namespace and lacking the Type
suffix. Every other cuda.core enum unified pre-1.0 lives in cuda.core.typing
as a StrEnum with semantic string values and a Type suffix. Bring the texture
enums in line:

- ArrayFormat  -> cuda.core.typing.ArrayFormatType
- AddressMode  -> cuda.core.typing.AddressModeType
- FilterMode   -> cuda.core.typing.FilterModeType
- ReadMode     -> cuda.core.typing.ReadModeType

Internally the driver integer values are still needed, so _array and _texture
carry private CU<->StrEnum bridge maps; OpaqueArray/MipmappedArray keep storing
the driver int and convert on the .format boundary. Per the enum convention,
plain strings are accepted anywhere an enum is expected (via _normalize_enum /
_normalize_array_format), and invalid values raise ValueError. TextureDescriptor
gains a __post_init__ that normalizes its filter_mode/read_mode/
mipmap_filter_mode fields at construction.

Enums are dropped from the cuda.core.texture __all__ and documented under
cuda.core.typing. Tests, examples, and docs are updated to the new names; the
negative-path tests that previously expected a TypeError at texture creation
now expect a ValueError at descriptor construction.
Addresses item 3 of the pre-v1.1.0 texture API-style review.

TensorMapDescriptorOptions.data_type already accepts NumPy dtype objects and
keeps its enum as a fallback. Apply the same precedent to the texture format
argument: OpaqueArray / MipmappedArray creation and
ResourceDescriptor.from_linear / from_pitch2d now accept an ArrayFormatType,
a plain str, or a NumPy dtype object (anything numpy.dtype() accepts).

Each ArrayFormatType value is already spelled as a NumPy dtype name, so the
eight formats map 1:1 via a new _NUMPY_DTYPE_TO_ARRAYFORMAT table. All four
factories funnel through _validate_format_channels -> _normalize_array_format,
so dtype support is added in one place. ml_dtypes is intentionally not imported:
every current format is a standard NumPy dtype, and the ml_dtypes path only
becomes relevant if/when a bfloat16 format is added.
…VIDIA#2292)

Addresses the rename portion of item 2 of the pre-v1.1.0 texture API-style
review.

CUDA_TEXTURE_DESC is pure creation input (it cannot be queried back from a
texture object), so "descriptor" borrowed the driver naming inappropriately.
TextureObjectOptions matches the XxxOptions convention used throughout
cuda.core (StreamOptions, EventOptions, TensorMapDescriptorOptions, ...).

Pure rename of the dataclass and all references across the implementation,
stubs, __init__ __all__, docs, tests, and examples. The from_descriptor
texture_descriptor= keyword is left untouched here; the whole creation entry
point is replaced by Device.create_texture_object(*, resource, options) in a
later commit.
…array (NVIDIA#2292)

Addresses item 1 (array allocation) and item 2 (Options dataclasses) of the
pre-v1.1.0 texture API-style review.

Every other user-allocatable resource in cuda.core is created via Device.create_*
(create_stream, create_event, ...) with an XxxOptions dataclass. The texture
arrays used per-type classmethod factories (OpaqueArray.from_descriptor,
MipmappedArray.from_descriptor) with loose kwargs instead. Move them in line:

- add OpaqueArrayOptions and MipmappedArrayOptions dataclasses (validated in
  __post_init__, mirroring TensorMapDescriptorOptions);
- add Device.create_opaque_array(options) and Device.create_mipmapped_array(
  options), which gate on _check_context_initialized() and delegate to private
  module factories that bind to the current device (same pattern as
  create_event / create_graph_builder);
- remove the OpaqueArray.from_descriptor / MipmappedArray.from_descriptor
  classmethods; the private _from_handle graphics-interop path is retained.

New entry points carry versionadded:: 1.1.0. Options are exported from
cuda.core.texture and documented in api.rst. Tests and the texture examples are
updated to Device().create_*_array(<Options>(...)).
…object (NVIDIA#2292)

Addresses item 1 (object creation) and item 6 (drop SurfaceObject.from_array
sugar) of the pre-v1.1.0 texture API-style review, completing the move to the
Device.create_* allocation shape.

- add Device.create_texture_object(*, resource, options) and
  Device.create_surface_object(*, resource), gating on
  _check_context_initialized() and delegating to private module factories that
  bind to the current device (same pattern as create_opaque_array);
- remove TextureObject.from_descriptor, SurfaceObject.from_descriptor, and the
  speculative SurfaceObject.from_array sugar (a surface is now built from an
  explicit ResourceDescriptor.from_opaque_array(...) like every other backing);
- rename the sampling-options argument from texture_descriptor to options on the
  new entry point, matching the create_* + XxxOptions convention (the queryable
  TextureObject.texture_descriptor property is unchanged).

New entry points carry versionadded:: 1.1.0. Tests, examples, and api.rst are
updated; a make_surface() helper mirrors make_texture() in the fluid example.
…DIA#2292)

Mechanical pre-commit pass over the NVIDIA#2292 texture API series:

- ruff: drop now-unused imports in the texture example/test files and remove an
  unused _normalize_array_format import from _texture.pyx (cython-lint);
- ruff-format: reflow the rewritten call sites in the tests and examples;
- stubgen-pyx: regenerate the .pyi stubs from the updated .pyx sources.
@Andy-Jost Andy-Jost added this to the cuda.core v1.1.0 milestone Jul 7, 2026
@Andy-Jost Andy-Jost added enhancement Any code-related improvements P0 High priority - Must do! cuda.core Everything related to the cuda.core module labels Jul 7, 2026
@Andy-Jost Andy-Jost self-assigned this Jul 7, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@Andy-Jost

Copy link
Copy Markdown
Contributor Author

/ok to test

Andy-Jost added 5 commits July 7, 2026 10:22
Apply the review findings from the texture API-style follow-up:

- Rename TextureObject.texture_descriptor -> options (and the internal
  _texture_desc slot -> _options) to drop the borrowed "descriptor"
  naming, matching the TextureObjectOptions rename.
- Make options a required argument on create_opaque_array /
  create_mipmapped_array (shape/format/num_channels have no defaults),
  so omitting it raises a clear error instead of a raw dataclass
  TypeError. create_texture_object keeps options=None (all-default
  sampling state).
- Add return and resource/options type annotations to the four
  Device.create_* texture factories via a TYPE_CHECKING texture import
  (mirroring the existing GraphBuilder pattern).
- Clarify in the create_* docstrings that the resource is created in the
  current CUDA context (call set_current first), mirroring
  create_stream / create_event.
- Add versionadded:: 1.1.0 to OpaqueArrayOptions, MipmappedArrayOptions,
  TextureObjectOptions, and the new options property.
- Fix a stale negative-path test whose regex no longer matched the
  shared check_or_create_options message; rename stale from_descriptor
  test names to create_*; realign the gl_interop_fluid API-MAP comment
  table after the enum renames.
- Regenerate .pyi stubs.
…A#2292)

The StrEnum migration (item 4 of NVIDIA#2292) makes a plain str acceptable
anywhere an AddressModeType is expected. A bad tuple entry like "bad" is
therefore a valid *type* but an invalid *value*, so _normalize_enum
rejects it with a ValueError (naming the offending position
address_mode[1]), not a TypeError. Update the test to assert ValueError
and rename it to test_address_mode_rejects_invalid_entry. This is the
second of the two CI failures on PR NVIDIA#2307; the first (the stale
options-type message) was fixed in the previous commit.
…A#2292)

test_enum_coverage.py::test_all_str_enums_in_cases requires every
StrEnum in cuda.core to be declared either in _CASES (bound to a
cuda_binding enum) or in _UNBOUND_STR_ENUMS. The four texture enums
moved into cuda.core.typing (item 4 of NVIDIA#2292) were not registered,
failing that guard.

- AddressModeType / FilterModeType are 1:1 wrappers of CUaddress_mode /
  CUfilter_mode, so add mapping=None _CASES entries (count-check only;
  the texture mapping dicts store cydriver-derived ints, not
  driver.<Enum> members, so the isinstance-based mapping check does not
  apply).
- ArrayFormatType exposes only the 8 NumPy-representable formats out of
  CUarray_format's ~67 members, so it is a curated subset rather than a
  1:1 wrapper -> _UNBOUND_STR_ENUMS.
- ReadModeType maps to the CU_TRSF_READ_AS_INTEGER flag bit, not a
  CUenum -> _UNBOUND_STR_ENUMS.

This is the third local test failure; the other two (stale texture
negative-path tests) were fixed in the two preceding commits.
Comment on lines +1472 to +1475
Allocates an opaque, hardware-laid-out CUDA array for texture/surface
access. The array is created in the current CUDA context, so make this
device current with :meth:`set_current` before calling (mirroring
:meth:`create_stream` / :meth:`create_event`).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #2311. I think this behavior (using the current context rather than the device specified by self) is buggy, but it matches other methods like Device.create_stream and Device.create_event. Fixing it is out of scope for this PR.

@Andy-Jost

Copy link
Copy Markdown
Contributor Author

/ok to test

@Andy-Jost Andy-Jost marked this pull request as ready for review July 7, 2026 18:20
@Andy-Jost Andy-Jost requested review from juenglin, leofang and rparolin and removed request for leofang July 7, 2026 18:20
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.core Everything related to the cuda.core module enhancement Any code-related improvements P0 High priority - Must do!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cuda.core.texture: API-style follow-up before v1.1.0 release

1 participant