1 /// Vulkan image module
2 module gfx.vulkan.image;
3 
4 package:
5 
6 import gfx.bindings.vulkan;
7 
8 import gfx.core.rc;
9 import gfx.graal.image;
10 import gfx.graal.memory;
11 import gfx.vulkan;
12 import gfx.vulkan.conv;
13 import gfx.vulkan.device;
14 import gfx.vulkan.error;
15 import gfx.vulkan.memory;
16 
17 class VulkanImageBase : ImageBase
18 {
19     this(VkImage vkObj, VulkanDevice dev, ImageInfo info)
20     {
21         _vkObj = vkObj;
22         _dev = dev;
23         _info = info;
24         _vk = dev.vk;
25     }
26 
27     final @property VkImage vkObj()
28     {
29         return _vkObj;
30     }
31 
32     final @property VulkanDevice dev()
33     {
34         return _dev;
35     }
36 
37     final @property VkDevice vkDev()
38     {
39         return _dev.vkObj;
40     }
41 
42     final @property VkDeviceCmds vk() {
43         return _vk;
44     }
45 
46     final override @property ImageInfo info() {
47         return _info;
48     }
49 
50     override VulkanImageView createView(ImageType viewType, ImageSubresourceRange isr, Swizzle swizzle)
51     {
52         const it = _info.type;
53         VkImageViewCreateInfo ivci;
54         ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
55         ivci.image = vkObj;
56         ivci.viewType = viewType.toVkView();
57         ivci.format = _info.format.toVk();
58         ivci.subresourceRange = isr.toVk();
59         ivci.components = swizzle.toVk();
60 
61         VkImageView vkIv;
62         vulkanEnforce(
63             vk.CreateImageView(vkDev, &ivci, null, &vkIv),
64             "Could not create Vulkan View"
65         );
66 
67         return new VulkanImageView(vkIv, this, isr, swizzle);
68     }
69 
70     private VkImage _vkObj;
71     private VulkanDevice _dev;
72     private VkDeviceCmds _vk;
73     private ImageInfo _info;
74 }
75 
76 final class VulkanImage : VulkanImageBase, Image
77 {
78     mixin(atomicRcCode);
79 
80     this(VkImage vkObj, VulkanDevice dev, ImageInfo info)
81     {
82         super(vkObj, dev, info);
83         dev.retain();
84     }
85 
86     override void dispose() {
87         vk.DestroyImage(vkDev, vkObj, null);
88         if (_vdm) _vdm.release();
89         dev.release();
90     }
91 
92     override Device device() {
93         return dev;
94     }
95 
96     override @property MemoryRequirements memoryRequirements() {
97         VkMemoryRequirements vkMr;
98         vk.GetImageMemoryRequirements(vkDev, vkObj, &vkMr);
99         return vkMr.toGfx();
100     }
101 
102     override void bindMemory(DeviceMemory mem, in size_t offset)
103     {
104         assert(!_vdm, "Bind the same buffer twice");
105         _vdm = enforce(cast(VulkanDeviceMemory)mem, "Did not pass a Vulkan memory");
106         vulkanEnforce(
107             vk.BindImageMemory(vkDev, vkObj, _vdm.vkObj, offset),
108             "Could not bind image memory"
109         );
110         _vdm.retain();
111     }
112 
113     override @property DeviceMemory boundMemory() {
114         return _vdm;
115     }
116 
117     VulkanDeviceMemory _vdm;
118 }
119 
120 class VulkanImageView : VulkanDevObj!(VkImageView, "DestroyImageView"), ImageView
121 {
122     mixin(atomicRcCode);
123 
124     this(VkImageView vkObj, VulkanImageBase img, ImageSubresourceRange isr, Swizzle swizzle)
125     {
126         super(vkObj, img.dev);
127         _img = img;
128         _isr = isr;
129         _swizzle = swizzle;
130     }
131 
132     override void dispose()
133     {
134         super.dispose();
135         _img = null;
136     }
137 
138     override @property VulkanImageBase image() {
139         return _img;
140     }
141 
142     override @property ImageSubresourceRange subresourceRange() {
143         return _isr;
144     }
145 
146     override @property Swizzle swizzle() {
147         return _swizzle;
148     }
149 
150     private VulkanImageBase _img;
151     private ImageSubresourceRange _isr;
152     private Swizzle _swizzle;
153 }
154 
155 final class VulkanSampler : VulkanDevObj!(VkSampler, "DestroySampler"), Sampler
156 {
157     mixin(atomicRcCode);
158     this(VkSampler sampler, VulkanDevice dev) {
159         super(sampler, dev);
160     }
161     override @property Device device() {
162         return dev;
163     }
164 }