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 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 @property MemoryRequirements memoryRequirements() {
93         VkMemoryRequirements vkMr;
94         vk.GetImageMemoryRequirements(vkDev, vkObj, &vkMr);
95         return vkMr.toGfx();
96     }
97 
98     override void bindMemory(DeviceMemory mem, in size_t offset)
99     {
100         assert(!_vdm, "Bind the same buffer twice");
101         _vdm = enforce(cast(VulkanDeviceMemory)mem, "Did not pass a Vulkan memory");
102         vulkanEnforce(
103             vk.BindImageMemory(vkDev, vkObj, _vdm.vkObj, offset),
104             "Could not bind image memory"
105         );
106         _vdm.retain();
107     }
108 
109     VulkanDeviceMemory _vdm;
110 }
111 
112 class VulkanImageView : VulkanDevObj!(VkImageView, "DestroyImageView"), ImageView
113 {
114     mixin(atomicRcCode);
115 
116     this(VkImageView vkObj, VulkanImageBase img, ImageSubresourceRange isr, Swizzle swizzle)
117     {
118         super(vkObj, img.dev);
119         _img = img;
120         _isr = isr;
121         _swizzle = swizzle;
122     }
123 
124     override void dispose()
125     {
126         super.dispose();
127         _img = null;
128     }
129 
130     override @property VulkanImageBase image() {
131         return _img;
132     }
133 
134     override @property ImageSubresourceRange subresourceRange() {
135         return _isr;
136     }
137 
138     override @property Swizzle swizzle() {
139         return _swizzle;
140     }
141 
142     private VulkanImageBase _img;
143     private ImageSubresourceRange _isr;
144     private Swizzle _swizzle;
145 }
146 
147 class VulkanSampler : VulkanDevObj!(VkSampler, "DestroySampler"), Sampler
148 {
149     mixin(atomicRcCode);
150     this(VkSampler sampler, VulkanDevice dev) {
151         super(sampler, dev);
152     }
153 }