Coverage for cuda/core/texture/_surface.pyx: 76.32%

38 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-19 01:12 +0000

1# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from __future__ import annotations 

6  

7from libc.string cimport memset 

8  

9from cuda.bindings cimport cydriver 

10from cuda.core.texture._array cimport OpaqueArray 

11from cuda.core._resource_handles cimport ( 

12 SurfObjectHandle, 

13 as_cu, 

14 as_intptr, 

15 create_surf_object_handle, 

16 get_last_error, 

17) 

18from cuda.core.texture._texture import ResourceDescriptor 

19from cuda.core._utils.cuda_utils cimport ( 

20 HANDLE_RETURN, 

21 _get_current_device_id, 

22) 

23  

24  

25cdef class SurfaceObject: 

26 """A bindless surface handle for kernel-side typed load/store. 

27  

28 Wraps ``cuSurfObjectCreate``. Unlike a :class:`TextureObject`, a surface 

29 has no sampling state (no filtering, no addressing modes, no normalization); 

30 kernels read and write through it using integer pixel coordinates. 

31  

32 The backing :class:`OpaqueArray` must have been created with 

33 ``is_surface_load_store=True`` and is kept alive for the lifetime of this 

34 object to prevent dangling handles. 

35  

36 Construct via :meth:`cuda.core.Device.create_surface_object`. Passes to 

37 kernels as a 64-bit handle (via the ``handle`` property). 

38  

39 .. versionadded:: 1.1.0 

40 """ 

41  

42 def __init__(self, *args, **kwargs): 

43 raise RuntimeError( 1h

44 "SurfaceObject cannot be instantiated directly. " 

45 "Use Device.create_surface_object()." 

46 ) 

47  

48 @property 

49 def handle(self): 

50 """The underlying ``CUsurfObject`` as an integer (64-bit kernel arg).""" 

51 return as_intptr(self._handle) 1abc

52  

53 @property 

54 def resource(self): 

55 """The :class:`ResourceDescriptor` this surface was built from.""" 

56 return self._source_ref 1a

57  

58 @property 

59 def device(self): 

60 from cuda.core._device import Device 

61 return Device(self._device_id) 

62  

63 cpdef close(self): 

64 """Release this object's reference to the underlying ``CUsurfObject``. 

65  

66 Destruction (``cuSurfObjectDestroy``) and release of the backing array 

67 happen via the handle's deleter when the last reference is dropped. 

68 Idempotent. 

69 """ 

70 self._handle.reset() 1abc

71 self._source_ref = None 1abc

72  

73 def __enter__(self): 

74 return self 

75  

76 def __exit__(self, exc_type, exc, tb): 

77 self.close() 

78  

79 def __repr__(self): 

80 return f"SurfaceObject(handle=0x{as_intptr(self._handle):x})" 

81  

82  

83def _create_surface_object(resource): 

84 """Create a :class:`SurfaceObject` on the current device. 

85  

86 Backs :meth:`cuda.core.Device.create_surface_object`. ``resource`` must be a 

87 :class:`ResourceDescriptor` wrapping an :class:`OpaqueArray` allocated with 

88 ``is_surface_load_store=True``; linear/pitch2d resources are not valid 

89 surface backings. 

90 """ 

91 if not isinstance(resource, ResourceDescriptor): 1abefgc

92 raise TypeError( 

93 f"resource must be a ResourceDescriptor, got " 

94 f"{type(resource).__name__}" 

95 ) 

96 if resource.kind != "array": 1abefgc

97 raise ValueError( 1ef

98 f"SurfaceObject requires an array-backed ResourceDescriptor, " 1ef

99 f"got kind={resource.kind!r}" 1ef

100 ) 

101  

102 cdef OpaqueArray arr = <OpaqueArray>resource.source 1abgc

103 if not arr.is_surface_load_store: 1abgc

104 raise ValueError( 1g

105 "OpaqueArray must be created with is_surface_load_store=True to be " 

106 "bound as a SurfaceObject" 

107 ) 

108  

109 cdef cydriver.CUDA_RESOURCE_DESC res_desc 

110 memset(&res_desc, 0, sizeof(res_desc)) 1abc

111 res_desc.resType = cydriver.CU_RESOURCE_TYPE_ARRAY 1abc

112 res_desc.res.array.hArray = as_cu(arr._handle) 1abc

113  

114 cdef SurfObjectHandle h = create_surf_object_handle(res_desc, arr._handle) 1abc

115 if not h: 1dabc

116 HANDLE_RETURN(get_last_error()) 

117  

118 cdef SurfaceObject self = SurfaceObject.__new__(SurfaceObject) 1abc

119 self._handle = h 1abc

120 self._source_ref = resource 1abc

121 self._device_id = _get_current_device_id() 1abc

122 return self 1abc