24 #include <unordered_map> 31 #include <vulkan/spirv.hpp11> 32 #include <vulkan/vulkan.hpp> 37 template <
class ... Args>
38 std::string
format(
const char *fmt, Args... args) {
39 int n = snprintf(
nullptr, 0, fmt, args...);
40 std::string result(n,
'\0');
41 snprintf(&*result.begin(), n+1, fmt, args...);
42 return std::move(result);
46 inline int findMemoryTypeIndex(
const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t memoryTypeBits, vk::MemoryPropertyFlags search) {
47 for (
int i = 0; i != memprops.memoryTypeCount; ++i, memoryTypeBits >>= 1) {
48 if (memoryTypeBits & 1) {
49 if ((memprops.memoryTypes[i].propertyFlags & search) == search) {
58 inline void executeImmediately(vk::Device device, vk::CommandPool commandPool, vk::Queue queue,
const std::function<
void (vk::CommandBuffer cb)> &func) {
59 vk::CommandBufferAllocateInfo cbai{ commandPool, vk::CommandBufferLevel::ePrimary, 1 };
61 auto cbs = device.allocateCommandBuffers(cbai);
62 cbs[0].begin(vk::CommandBufferBeginInfo{});
66 vk::SubmitInfo submit;
67 submit.commandBufferCount = (uint32_t)cbs.size();
68 submit.pCommandBuffers = cbs.data();
69 queue.submit(submit, vk::Fence{});
72 device.freeCommandBuffers(commandPool, cbs);
76 inline uint32_t
mipScale(uint32_t value, uint32_t mipLevel) {
77 return std::max(value >> mipLevel, (uint32_t)1);
82 inline std::vector<uint8_t>
loadFile(
const std::string &filename) {
83 std::ifstream is(filename, std::ios::binary|std::ios::ate);
84 std::vector<uint8_t> bytes;
86 size_t size = is.tellg();
89 is.read((
char*)bytes.data(), size);
91 return std::move(bytes);
98 uint8_t bytesPerBlock;
104 case vk::Format::eR4G4UnormPack8:
return BlockParams{1, 1, 1};
105 case vk::Format::eR4G4B4A4UnormPack16:
return BlockParams{1, 1, 2};
106 case vk::Format::eB4G4R4A4UnormPack16:
return BlockParams{1, 1, 2};
107 case vk::Format::eR5G6B5UnormPack16:
return BlockParams{1, 1, 2};
108 case vk::Format::eB5G6R5UnormPack16:
return BlockParams{1, 1, 2};
109 case vk::Format::eR5G5B5A1UnormPack16:
return BlockParams{1, 1, 2};
110 case vk::Format::eB5G5R5A1UnormPack16:
return BlockParams{1, 1, 2};
111 case vk::Format::eA1R5G5B5UnormPack16:
return BlockParams{1, 1, 2};
112 case vk::Format::eR8Unorm:
return BlockParams{1, 1, 1};
113 case vk::Format::eR8Snorm:
return BlockParams{1, 1, 1};
114 case vk::Format::eR8Uscaled:
return BlockParams{1, 1, 1};
115 case vk::Format::eR8Sscaled:
return BlockParams{1, 1, 1};
116 case vk::Format::eR8Uint:
return BlockParams{1, 1, 1};
117 case vk::Format::eR8Sint:
return BlockParams{1, 1, 1};
118 case vk::Format::eR8Srgb:
return BlockParams{1, 1, 1};
119 case vk::Format::eR8G8Unorm:
return BlockParams{1, 1, 2};
120 case vk::Format::eR8G8Snorm:
return BlockParams{1, 1, 2};
121 case vk::Format::eR8G8Uscaled:
return BlockParams{1, 1, 2};
122 case vk::Format::eR8G8Sscaled:
return BlockParams{1, 1, 2};
123 case vk::Format::eR8G8Uint:
return BlockParams{1, 1, 2};
124 case vk::Format::eR8G8Sint:
return BlockParams{1, 1, 2};
125 case vk::Format::eR8G8Srgb:
return BlockParams{1, 1, 2};
126 case vk::Format::eR8G8B8Unorm:
return BlockParams{1, 1, 3};
127 case vk::Format::eR8G8B8Snorm:
return BlockParams{1, 1, 3};
128 case vk::Format::eR8G8B8Uscaled:
return BlockParams{1, 1, 3};
129 case vk::Format::eR8G8B8Sscaled:
return BlockParams{1, 1, 3};
130 case vk::Format::eR8G8B8Uint:
return BlockParams{1, 1, 3};
131 case vk::Format::eR8G8B8Sint:
return BlockParams{1, 1, 3};
132 case vk::Format::eR8G8B8Srgb:
return BlockParams{1, 1, 3};
133 case vk::Format::eB8G8R8Unorm:
return BlockParams{1, 1, 3};
134 case vk::Format::eB8G8R8Snorm:
return BlockParams{1, 1, 3};
135 case vk::Format::eB8G8R8Uscaled:
return BlockParams{1, 1, 3};
136 case vk::Format::eB8G8R8Sscaled:
return BlockParams{1, 1, 3};
137 case vk::Format::eB8G8R8Uint:
return BlockParams{1, 1, 3};
138 case vk::Format::eB8G8R8Sint:
return BlockParams{1, 1, 3};
139 case vk::Format::eB8G8R8Srgb:
return BlockParams{1, 1, 3};
140 case vk::Format::eR8G8B8A8Unorm:
return BlockParams{1, 1, 4};
141 case vk::Format::eR8G8B8A8Snorm:
return BlockParams{1, 1, 4};
142 case vk::Format::eR8G8B8A8Uscaled:
return BlockParams{1, 1, 4};
143 case vk::Format::eR8G8B8A8Sscaled:
return BlockParams{1, 1, 4};
144 case vk::Format::eR8G8B8A8Uint:
return BlockParams{1, 1, 4};
145 case vk::Format::eR8G8B8A8Sint:
return BlockParams{1, 1, 4};
146 case vk::Format::eR8G8B8A8Srgb:
return BlockParams{1, 1, 4};
147 case vk::Format::eB8G8R8A8Unorm:
return BlockParams{1, 1, 4};
148 case vk::Format::eB8G8R8A8Snorm:
return BlockParams{1, 1, 4};
149 case vk::Format::eB8G8R8A8Uscaled:
return BlockParams{1, 1, 4};
150 case vk::Format::eB8G8R8A8Sscaled:
return BlockParams{1, 1, 4};
151 case vk::Format::eB8G8R8A8Uint:
return BlockParams{1, 1, 4};
152 case vk::Format::eB8G8R8A8Sint:
return BlockParams{1, 1, 4};
153 case vk::Format::eB8G8R8A8Srgb:
return BlockParams{1, 1, 4};
154 case vk::Format::eA8B8G8R8UnormPack32:
return BlockParams{1, 1, 4};
155 case vk::Format::eA8B8G8R8SnormPack32:
return BlockParams{1, 1, 4};
156 case vk::Format::eA8B8G8R8UscaledPack32:
return BlockParams{1, 1, 4};
157 case vk::Format::eA8B8G8R8SscaledPack32:
return BlockParams{1, 1, 4};
158 case vk::Format::eA8B8G8R8UintPack32:
return BlockParams{1, 1, 4};
159 case vk::Format::eA8B8G8R8SintPack32:
return BlockParams{1, 1, 4};
160 case vk::Format::eA8B8G8R8SrgbPack32:
return BlockParams{1, 1, 4};
161 case vk::Format::eA2R10G10B10UnormPack32:
return BlockParams{1, 1, 4};
162 case vk::Format::eA2R10G10B10SnormPack32:
return BlockParams{1, 1, 4};
163 case vk::Format::eA2R10G10B10UscaledPack32:
return BlockParams{1, 1, 4};
164 case vk::Format::eA2R10G10B10SscaledPack32:
return BlockParams{1, 1, 4};
165 case vk::Format::eA2R10G10B10UintPack32:
return BlockParams{1, 1, 4};
166 case vk::Format::eA2R10G10B10SintPack32:
return BlockParams{1, 1, 4};
167 case vk::Format::eA2B10G10R10UnormPack32:
return BlockParams{1, 1, 4};
168 case vk::Format::eA2B10G10R10SnormPack32:
return BlockParams{1, 1, 4};
169 case vk::Format::eA2B10G10R10UscaledPack32:
return BlockParams{1, 1, 4};
170 case vk::Format::eA2B10G10R10SscaledPack32:
return BlockParams{1, 1, 4};
171 case vk::Format::eA2B10G10R10UintPack32:
return BlockParams{1, 1, 4};
172 case vk::Format::eA2B10G10R10SintPack32:
return BlockParams{1, 1, 4};
173 case vk::Format::eR16Unorm:
return BlockParams{1, 1, 2};
174 case vk::Format::eR16Snorm:
return BlockParams{1, 1, 2};
175 case vk::Format::eR16Uscaled:
return BlockParams{1, 1, 2};
176 case vk::Format::eR16Sscaled:
return BlockParams{1, 1, 2};
177 case vk::Format::eR16Uint:
return BlockParams{1, 1, 2};
178 case vk::Format::eR16Sint:
return BlockParams{1, 1, 2};
179 case vk::Format::eR16Sfloat:
return BlockParams{1, 1, 2};
180 case vk::Format::eR16G16Unorm:
return BlockParams{1, 1, 4};
181 case vk::Format::eR16G16Snorm:
return BlockParams{1, 1, 4};
182 case vk::Format::eR16G16Uscaled:
return BlockParams{1, 1, 4};
183 case vk::Format::eR16G16Sscaled:
return BlockParams{1, 1, 4};
184 case vk::Format::eR16G16Uint:
return BlockParams{1, 1, 4};
185 case vk::Format::eR16G16Sint:
return BlockParams{1, 1, 4};
186 case vk::Format::eR16G16Sfloat:
return BlockParams{1, 1, 4};
187 case vk::Format::eR16G16B16Unorm:
return BlockParams{1, 1, 6};
188 case vk::Format::eR16G16B16Snorm:
return BlockParams{1, 1, 6};
189 case vk::Format::eR16G16B16Uscaled:
return BlockParams{1, 1, 6};
190 case vk::Format::eR16G16B16Sscaled:
return BlockParams{1, 1, 6};
191 case vk::Format::eR16G16B16Uint:
return BlockParams{1, 1, 6};
192 case vk::Format::eR16G16B16Sint:
return BlockParams{1, 1, 6};
193 case vk::Format::eR16G16B16Sfloat:
return BlockParams{1, 1, 6};
194 case vk::Format::eR16G16B16A16Unorm:
return BlockParams{1, 1, 8};
195 case vk::Format::eR16G16B16A16Snorm:
return BlockParams{1, 1, 8};
196 case vk::Format::eR16G16B16A16Uscaled:
return BlockParams{1, 1, 8};
197 case vk::Format::eR16G16B16A16Sscaled:
return BlockParams{1, 1, 8};
198 case vk::Format::eR16G16B16A16Uint:
return BlockParams{1, 1, 8};
199 case vk::Format::eR16G16B16A16Sint:
return BlockParams{1, 1, 8};
200 case vk::Format::eR16G16B16A16Sfloat:
return BlockParams{1, 1, 8};
201 case vk::Format::eR32Uint:
return BlockParams{1, 1, 4};
202 case vk::Format::eR32Sint:
return BlockParams{1, 1, 4};
203 case vk::Format::eR32Sfloat:
return BlockParams{1, 1, 4};
204 case vk::Format::eR32G32Uint:
return BlockParams{1, 1, 8};
205 case vk::Format::eR32G32Sint:
return BlockParams{1, 1, 8};
206 case vk::Format::eR32G32Sfloat:
return BlockParams{1, 1, 8};
207 case vk::Format::eR32G32B32Uint:
return BlockParams{1, 1, 12};
208 case vk::Format::eR32G32B32Sint:
return BlockParams{1, 1, 12};
209 case vk::Format::eR32G32B32Sfloat:
return BlockParams{1, 1, 12};
210 case vk::Format::eR32G32B32A32Uint:
return BlockParams{1, 1, 16};
211 case vk::Format::eR32G32B32A32Sint:
return BlockParams{1, 1, 16};
212 case vk::Format::eR32G32B32A32Sfloat:
return BlockParams{1, 1, 16};
213 case vk::Format::eR64Uint:
return BlockParams{1, 1, 8};
214 case vk::Format::eR64Sint:
return BlockParams{1, 1, 8};
215 case vk::Format::eR64Sfloat:
return BlockParams{1, 1, 8};
216 case vk::Format::eR64G64Uint:
return BlockParams{1, 1, 16};
217 case vk::Format::eR64G64Sint:
return BlockParams{1, 1, 16};
218 case vk::Format::eR64G64Sfloat:
return BlockParams{1, 1, 16};
219 case vk::Format::eR64G64B64Uint:
return BlockParams{1, 1, 24};
220 case vk::Format::eR64G64B64Sint:
return BlockParams{1, 1, 24};
221 case vk::Format::eR64G64B64Sfloat:
return BlockParams{1, 1, 24};
222 case vk::Format::eR64G64B64A64Uint:
return BlockParams{1, 1, 32};
223 case vk::Format::eR64G64B64A64Sint:
return BlockParams{1, 1, 32};
224 case vk::Format::eR64G64B64A64Sfloat:
return BlockParams{1, 1, 32};
225 case vk::Format::eB10G11R11UfloatPack32:
return BlockParams{1, 1, 4};
226 case vk::Format::eE5B9G9R9UfloatPack32:
return BlockParams{1, 1, 4};
227 case vk::Format::eD16Unorm:
return BlockParams{1, 1, 4};
228 case vk::Format::eX8D24UnormPack32:
return BlockParams{1, 1, 4};
229 case vk::Format::eD32Sfloat:
return BlockParams{1, 1, 4};
230 case vk::Format::eS8Uint:
return BlockParams{1, 1, 1};
231 case vk::Format::eD16UnormS8Uint:
return BlockParams{1, 1, 3};
232 case vk::Format::eD24UnormS8Uint:
return BlockParams{1, 1, 4};
233 case vk::Format::eD32SfloatS8Uint:
return BlockParams{0, 0, 0};
234 case vk::Format::eBc1RgbUnormBlock:
return BlockParams{4, 4, 8};
235 case vk::Format::eBc1RgbSrgbBlock:
return BlockParams{4, 4, 8};
236 case vk::Format::eBc1RgbaUnormBlock:
return BlockParams{4, 4, 8};
237 case vk::Format::eBc1RgbaSrgbBlock:
return BlockParams{4, 4, 8};
238 case vk::Format::eBc2UnormBlock:
return BlockParams{4, 4, 16};
239 case vk::Format::eBc2SrgbBlock:
return BlockParams{4, 4, 16};
240 case vk::Format::eBc3UnormBlock:
return BlockParams{4, 4, 16};
241 case vk::Format::eBc3SrgbBlock:
return BlockParams{4, 4, 16};
242 case vk::Format::eBc4UnormBlock:
return BlockParams{4, 4, 16};
243 case vk::Format::eBc4SnormBlock:
return BlockParams{4, 4, 16};
244 case vk::Format::eBc5UnormBlock:
return BlockParams{4, 4, 16};
245 case vk::Format::eBc5SnormBlock:
return BlockParams{4, 4, 16};
246 case vk::Format::eBc6HUfloatBlock:
return BlockParams{0, 0, 0};
247 case vk::Format::eBc6HSfloatBlock:
return BlockParams{0, 0, 0};
248 case vk::Format::eBc7UnormBlock:
return BlockParams{0, 0, 0};
249 case vk::Format::eBc7SrgbBlock:
return BlockParams{0, 0, 0};
250 case vk::Format::eEtc2R8G8B8UnormBlock:
return BlockParams{0, 0, 0};
251 case vk::Format::eEtc2R8G8B8SrgbBlock:
return BlockParams{0, 0, 0};
252 case vk::Format::eEtc2R8G8B8A1UnormBlock:
return BlockParams{0, 0, 0};
253 case vk::Format::eEtc2R8G8B8A1SrgbBlock:
return BlockParams{0, 0, 0};
254 case vk::Format::eEtc2R8G8B8A8UnormBlock:
return BlockParams{0, 0, 0};
255 case vk::Format::eEtc2R8G8B8A8SrgbBlock:
return BlockParams{0, 0, 0};
256 case vk::Format::eEacR11UnormBlock:
return BlockParams{0, 0, 0};
257 case vk::Format::eEacR11SnormBlock:
return BlockParams{0, 0, 0};
258 case vk::Format::eEacR11G11UnormBlock:
return BlockParams{0, 0, 0};
259 case vk::Format::eEacR11G11SnormBlock:
return BlockParams{0, 0, 0};
260 case vk::Format::eAstc4x4UnormBlock:
return BlockParams{0, 0, 0};
261 case vk::Format::eAstc4x4SrgbBlock:
return BlockParams{0, 0, 0};
262 case vk::Format::eAstc5x4UnormBlock:
return BlockParams{0, 0, 0};
263 case vk::Format::eAstc5x4SrgbBlock:
return BlockParams{0, 0, 0};
264 case vk::Format::eAstc5x5UnormBlock:
return BlockParams{0, 0, 0};
265 case vk::Format::eAstc5x5SrgbBlock:
return BlockParams{0, 0, 0};
266 case vk::Format::eAstc6x5UnormBlock:
return BlockParams{0, 0, 0};
267 case vk::Format::eAstc6x5SrgbBlock:
return BlockParams{0, 0, 0};
268 case vk::Format::eAstc6x6UnormBlock:
return BlockParams{0, 0, 0};
269 case vk::Format::eAstc6x6SrgbBlock:
return BlockParams{0, 0, 0};
270 case vk::Format::eAstc8x5UnormBlock:
return BlockParams{0, 0, 0};
271 case vk::Format::eAstc8x5SrgbBlock:
return BlockParams{0, 0, 0};
272 case vk::Format::eAstc8x6UnormBlock:
return BlockParams{0, 0, 0};
273 case vk::Format::eAstc8x6SrgbBlock:
return BlockParams{0, 0, 0};
274 case vk::Format::eAstc8x8UnormBlock:
return BlockParams{0, 0, 0};
275 case vk::Format::eAstc8x8SrgbBlock:
return BlockParams{0, 0, 0};
276 case vk::Format::eAstc10x5UnormBlock:
return BlockParams{0, 0, 0};
277 case vk::Format::eAstc10x5SrgbBlock:
return BlockParams{0, 0, 0};
278 case vk::Format::eAstc10x6UnormBlock:
return BlockParams{0, 0, 0};
279 case vk::Format::eAstc10x6SrgbBlock:
return BlockParams{0, 0, 0};
280 case vk::Format::eAstc10x8UnormBlock:
return BlockParams{0, 0, 0};
281 case vk::Format::eAstc10x8SrgbBlock:
return BlockParams{0, 0, 0};
282 case vk::Format::eAstc10x10UnormBlock:
return BlockParams{0, 0, 0};
283 case vk::Format::eAstc10x10SrgbBlock:
return BlockParams{0, 0, 0};
284 case vk::Format::eAstc12x10UnormBlock:
return BlockParams{0, 0, 0};
285 case vk::Format::eAstc12x10SrgbBlock:
return BlockParams{0, 0, 0};
286 case vk::Format::eAstc12x12UnormBlock:
return BlockParams{0, 0, 0};
287 case vk::Format::eAstc12x12SrgbBlock:
return BlockParams{0, 0, 0};
288 case vk::Format::ePvrtc12BppUnormBlockIMG:
return BlockParams{0, 0, 0};
289 case vk::Format::ePvrtc14BppUnormBlockIMG:
return BlockParams{0, 0, 0};
290 case vk::Format::ePvrtc22BppUnormBlockIMG:
return BlockParams{0, 0, 0};
291 case vk::Format::ePvrtc24BppUnormBlockIMG:
return BlockParams{0, 0, 0};
292 case vk::Format::ePvrtc12BppSrgbBlockIMG:
return BlockParams{0, 0, 0};
293 case vk::Format::ePvrtc14BppSrgbBlockIMG:
return BlockParams{0, 0, 0};
294 case vk::Format::ePvrtc22BppSrgbBlockIMG:
return BlockParams{0, 0, 0};
295 case vk::Format::ePvrtc24BppSrgbBlockIMG:
return BlockParams{0, 0, 0};
317 vk::AttachmentDescription desc{{}, format};
318 s.attachmentDescriptions.push_back(desc);
321 void attachmentFlags(vk::AttachmentDescriptionFlags value) { s.attachmentDescriptions.back().flags = value; };
322 void attachmentFormat(vk::Format value) { s.attachmentDescriptions.back().format = value; };
323 void attachmentSamples(vk::SampleCountFlagBits value) { s.attachmentDescriptions.back().samples = value; };
324 void attachmentLoadOp(vk::AttachmentLoadOp value) { s.attachmentDescriptions.back().loadOp = value; };
325 void attachmentStoreOp(vk::AttachmentStoreOp value) { s.attachmentDescriptions.back().storeOp = value; };
326 void attachmentStencilLoadOp(vk::AttachmentLoadOp value) { s.attachmentDescriptions.back().stencilLoadOp = value; };
327 void attachmentStencilStoreOp(vk::AttachmentStoreOp value) { s.attachmentDescriptions.back().stencilStoreOp = value; };
328 void attachmentInitialLayout(vk::ImageLayout value) { s.attachmentDescriptions.back().initialLayout = value; };
329 void attachmentFinalLayout(vk::ImageLayout value) { s.attachmentDescriptions.back().finalLayout = value; };
335 vk::SubpassDescription desc{};
336 desc.pipelineBindPoint = bp;
337 s.subpassDescriptions.push_back(desc);
340 void subpassColorAttachment(vk::ImageLayout layout, uint32_t attachment) {
341 vk::SubpassDescription &subpass = s.subpassDescriptions.back();
342 auto *p = getAttachmentReference();
344 p->attachment = attachment;
345 if (subpass.colorAttachmentCount == 0) {
346 subpass.pColorAttachments = p;
348 subpass.colorAttachmentCount++;
351 void subpassDepthStencilAttachment(vk::ImageLayout layout, uint32_t attachment) {
352 vk::SubpassDescription &subpass = s.subpassDescriptions.back();
353 auto *p = getAttachmentReference();
355 p->attachment = attachment;
356 subpass.pDepthStencilAttachment = p;
359 vk::UniqueRenderPass createUnique(
const vk::Device &device)
const {
360 vk::RenderPassCreateInfo renderPassInfo{};
361 renderPassInfo.attachmentCount = (uint32_t)s.attachmentDescriptions.size();
362 renderPassInfo.pAttachments = s.attachmentDescriptions.data();
363 renderPassInfo.subpassCount = (uint32_t)s.subpassDescriptions.size();
364 renderPassInfo.pSubpasses = s.subpassDescriptions.data();
365 renderPassInfo.dependencyCount = (uint32_t)s.subpassDependencies.size();
366 renderPassInfo.pDependencies = s.subpassDependencies.data();
367 return device.createRenderPassUnique(renderPassInfo);
370 void dependencyBegin(uint32_t srcSubpass, uint32_t dstSubpass) {
371 vk::SubpassDependency desc{};
372 desc.srcSubpass = srcSubpass;
373 desc.dstSubpass = dstSubpass;
374 s.subpassDependencies.push_back(desc);
377 void dependencySrcSubpass(uint32_t value) { s.subpassDependencies.back().srcSubpass = value; };
378 void dependencyDstSubpass(uint32_t value) { s.subpassDependencies.back().dstSubpass = value; };
379 void dependencySrcStageMask(vk::PipelineStageFlags value) { s.subpassDependencies.back().srcStageMask = value; };
380 void dependencyDstStageMask(vk::PipelineStageFlags value) { s.subpassDependencies.back().dstStageMask = value; };
381 void dependencySrcAccessMask(vk::AccessFlags value) { s.subpassDependencies.back().srcAccessMask = value; };
382 void dependencyDstAccessMask(vk::AccessFlags value) { s.subpassDependencies.back().dstAccessMask = value; };
383 void dependencyDependencyFlags(vk::DependencyFlags value) { s.subpassDependencies.back().dependencyFlags = value; };
385 constexpr
static int max_refs = 64;
387 vk::AttachmentReference *getAttachmentReference() {
388 return (s.num_refs < max_refs) ? &s.attachmentReferences[s.num_refs++] :
nullptr;
392 std::vector<vk::AttachmentDescription> attachmentDescriptions;
393 std::vector<vk::SubpassDescription> subpassDescriptions;
394 std::vector<vk::SubpassDependency> subpassDependencies;
395 std::array<vk::AttachmentReference, max_refs> attachmentReferences;
411 auto file = std::ifstream(filename, std::ios::binary);
416 file.seekg(0, std::ios::end);
417 int length = (int)file.tellg();
419 s.opcodes_.resize((
size_t)(length / 4));
420 file.seekg(0, std::ios::beg);
421 file.read((
char *)s.opcodes_.data(), s.opcodes_.size() * 4);
423 vk::ShaderModuleCreateInfo ci;
424 ci.codeSize = s.opcodes_.size() * 4;
425 ci.pCode = s.opcodes_.data();
426 s.module_ = device.createShaderModuleUnique(ci);
432 template<
class InIter>
434 s.opcodes_.assign(begin, end);
435 vk::ShaderModuleCreateInfo ci;
436 ci.codeSize = s.opcodes_.size() * 4;
437 ci.pCode = s.opcodes_.data();
438 s.module_ = device.createShaderModuleUnique(ci);
446 std::string debugName;
462 spv::StorageClass storageClass;
470 auto bound = s.opcodes_[3];
472 std::unordered_map<int, int> bindings;
473 std::unordered_map<int, int> locations;
474 std::unordered_map<int, int> sets;
475 std::unordered_map<int, std::string> debugNames;
477 for (
int i = 5; i != s.opcodes_.size(); i += s.opcodes_[i] >> 16) {
478 spv::Op op = spv::Op(s.opcodes_[i] & 0xffff);
479 if (op == spv::Op::OpDecorate) {
480 int name = s.opcodes_[i + 1];
481 auto decoration = spv::Decoration(s.opcodes_[i + 2]);
482 if (decoration == spv::Decoration::Binding) {
483 bindings[name] = s.opcodes_[i + 3];
484 }
else if (decoration == spv::Decoration::Location) {
485 locations[name] = s.opcodes_[i + 3];
486 }
else if (decoration == spv::Decoration::DescriptorSet) {
487 sets[name] = s.opcodes_[i + 3];
489 }
else if (op == spv::Op::OpName) {
490 int name = s.opcodes_[i + 1];
491 debugNames[name] = (
const char *)&s.opcodes_[i + 2];
495 std::vector<Variable> result;
496 for (
int i = 5; i != s.opcodes_.size(); i += s.opcodes_[i] >> 16) {
497 spv::Op op = spv::Op(s.opcodes_[i] & 0xffff);
498 if (op == spv::Op::OpVariable) {
499 int name = s.opcodes_[i + 1];
500 auto sc = spv::StorageClass(s.opcodes_[i + 3]);
502 b.debugName = debugNames[name];
504 b.location = locations[name];
511 return std::move(result);
514 bool ok()
const {
return s.ok_; }
515 VkShaderModule module() {
return *s.module_; }
519 std::ostream &
write(std::ostream &os) {
520 os <<
"static const uint32_t shader[] = {\n";
522 auto p = s.opcodes_.begin();
524 tmp,
sizeof(tmp),
" 0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,\n", p[0], p[1], p[2], p[3], p[4]);
526 for (
int i = 5; i != s.opcodes_.size(); i += s.opcodes_[i] >> 16) {
527 char *p = tmp + 2, *e = tmp +
sizeof(tmp) - 2;
528 for (
int j = i; j != i + (s.opcodes_[i] >> 16); ++j) {
529 p += snprintf(p, e-p,
"0x%08x,", s.opcodes_[j]);
530 if (p > e-16) { *p++ =
'\n'; *p = 0; os << tmp; p = tmp + 2; }
542 std::vector<uint32_t> opcodes_;
543 vk::UniqueShaderModule module_;
557 vk::UniquePipelineLayout
createUnique(
const vk::Device &device)
const {
558 vk::PipelineLayoutCreateInfo pipelineLayoutInfo{
559 {}, (uint32_t)setLayouts_.size(),
560 setLayouts_.data(), (uint32_t)pushConstantRanges_.size(),
561 pushConstantRanges_.data()};
562 return std::move(device.createPipelineLayoutUnique(pipelineLayoutInfo));
567 setLayouts_.push_back(layout);
573 pushConstantRanges_.emplace_back(stageFlags_, offset_, size_);
577 std::vector<vk::DescriptorSetLayout> setLayouts_;
578 std::vector<vk::PushConstantRange> pushConstantRanges_;
590 inputAssemblyState_.
topology = vk::PrimitiveTopology::eTriangleList;
591 viewport_ = vk::Viewport{0.0f, 0.0f, (float)width, (
float)height, 0.0f, 1.0f};
592 scissor_ = vk::Rect2D{{0, 0}, {width, height}};
593 rasterizationState_.lineWidth = 1.0f;
596 depthStencilState_.depthTestEnable = VK_FALSE;
597 depthStencilState_.depthWriteEnable = VK_TRUE;
598 depthStencilState_.depthCompareOp = vk::CompareOp::eLessOrEqual;
599 depthStencilState_.depthBoundsTestEnable = VK_FALSE;
600 depthStencilState_.back.failOp = vk::StencilOp::eKeep;
601 depthStencilState_.back.passOp = vk::StencilOp::eKeep;
602 depthStencilState_.back.compareOp = vk::CompareOp::eAlways;
603 depthStencilState_.stencilTestEnable = VK_FALSE;
604 depthStencilState_.front = depthStencilState_.back;
607 vk::UniquePipeline createUnique(
const vk::Device &device,
608 const vk::PipelineCache &pipelineCache,
609 const vk::PipelineLayout &pipelineLayout,
610 const vk::RenderPass &renderPass,
bool defaultBlend=
true) {
613 if (colorBlendAttachments_.empty() && defaultBlend) {
614 vk::PipelineColorBlendAttachmentState blend{};
616 blend.srcColorBlendFactor = vk::BlendFactor::eOne;
617 blend.dstColorBlendFactor = vk::BlendFactor::eZero;
618 blend.colorBlendOp = vk::BlendOp::eAdd;
619 blend.srcAlphaBlendFactor = vk::BlendFactor::eOne;
620 blend.dstAlphaBlendFactor = vk::BlendFactor::eZero;
621 blend.alphaBlendOp = vk::BlendOp::eAdd;
622 typedef vk::ColorComponentFlagBits ccbf;
623 blend.colorWriteMask = ccbf::eR|ccbf::eG|ccbf::eB|ccbf::eA;
624 colorBlendAttachments_.push_back(blend);
627 auto count = (uint32_t)colorBlendAttachments_.size();
628 colorBlendState_.attachmentCount = count;
629 colorBlendState_.pAttachments = count ? colorBlendAttachments_.data() :
nullptr;
631 vk::PipelineViewportStateCreateInfo viewportState{
632 {}, 1, &viewport_, 1, &scissor_};
634 vk::PipelineVertexInputStateCreateInfo vertexInputState;
635 vertexInputState.vertexAttributeDescriptionCount = (uint32_t)vertexAttributeDescriptions_.size();
636 vertexInputState.pVertexAttributeDescriptions = vertexAttributeDescriptions_.data();
637 vertexInputState.vertexBindingDescriptionCount = (uint32_t)vertexBindingDescriptions_.size();
638 vertexInputState.pVertexBindingDescriptions = vertexBindingDescriptions_.data();
640 vk::PipelineDynamicStateCreateInfo dynState{{}, (uint32_t)dynamicState_.size(), dynamicState_.data()};
642 vk::GraphicsPipelineCreateInfo pipelineInfo{};
643 pipelineInfo.pVertexInputState = &vertexInputState;
644 pipelineInfo.stageCount = (uint32_t)modules_.size();
645 pipelineInfo.pStages = modules_.data();
646 pipelineInfo.pInputAssemblyState = &inputAssemblyState_;
647 pipelineInfo.pViewportState = &viewportState;
648 pipelineInfo.pRasterizationState = &rasterizationState_;
649 pipelineInfo.pMultisampleState = &multisampleState_;
650 pipelineInfo.pColorBlendState = &colorBlendState_;
651 pipelineInfo.pDepthStencilState = &depthStencilState_;
652 pipelineInfo.layout = pipelineLayout;
653 pipelineInfo.renderPass = renderPass;
654 pipelineInfo.pDynamicState = dynamicState_.empty() ?
nullptr : &dynState;
655 pipelineInfo.subpass = subpass_;
657 return device.createGraphicsPipelineUnique(pipelineCache, pipelineInfo);
662 const char *entryPoint =
"main") {
663 vk::PipelineShaderStageCreateInfo info{};
664 info.module = shader.module();
665 info.pName = entryPoint;
667 modules_.emplace_back(info);
672 void colorBlend(
const vk::PipelineColorBlendAttachmentState &state) {
673 colorBlendAttachments_.push_back(state);
676 void subPass(uint32_t subpass) {
685 colorBlendAttachments_.emplace_back();
686 auto &blend = colorBlendAttachments_.back();
687 blend.blendEnable = enable;
688 blend.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha;
689 blend.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
690 blend.colorBlendOp = vk::BlendOp::eAdd;
691 blend.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha;
692 blend.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
693 blend.alphaBlendOp = vk::BlendOp::eAdd;
694 typedef vk::ColorComponentFlagBits ccbf;
695 blend.colorWriteMask = ccbf::eR|ccbf::eG|ccbf::eB|ccbf::eA;
699 void blendEnable(vk::Bool32 value) { colorBlendAttachments_.back().blendEnable = value; }
708 void blendColorBlendOp(vk::BlendOp value) { colorBlendAttachments_.back().colorBlendOp = value; }
717 void blendAlphaBlendOp(vk::BlendOp value) { colorBlendAttachments_.back().alphaBlendOp = value; }
720 void blendColorWriteMask(vk::ColorComponentFlags value) { colorBlendAttachments_.back().colorWriteMask = value; }
723 void vertexAttribute(uint32_t location_, uint32_t binding_, vk::Format format_, uint32_t offset_) {
724 vertexAttributeDescriptions_.push_back({location_, binding_, format_, offset_});
729 vertexAttributeDescriptions_.push_back(desc);
735 void vertexBinding(uint32_t binding_, uint32_t stride_, vk::VertexInputRate inputRate_ = vk::VertexInputRate::eVertex) {
736 vertexBindingDescriptions_.push_back({binding_, stride_, inputRate_});
743 vertexBindingDescriptions_.push_back(desc);
769 PipelineMaker &depthClampEnable(vk::Bool32 value) { rasterizationState_.depthClampEnable = value;
return *
this; }
770 PipelineMaker &rasterizerDiscardEnable(vk::Bool32 value) { rasterizationState_.rasterizerDiscardEnable = value;
return *
this; }
771 PipelineMaker &polygonMode(vk::PolygonMode value) { rasterizationState_.polygonMode = value;
return *
this; }
772 PipelineMaker &cullMode(vk::CullModeFlags value) { rasterizationState_.cullMode = value;
return *
this; }
773 PipelineMaker &frontFace(vk::FrontFace value) { rasterizationState_.frontFace = value;
return *
this; }
774 PipelineMaker &depthBiasEnable(vk::Bool32 value) { rasterizationState_.depthBiasEnable = value;
return *
this; }
775 PipelineMaker &depthBiasConstantFactor(
float value) { rasterizationState_.depthBiasConstantFactor = value;
return *
this; }
776 PipelineMaker &depthBiasClamp(
float value) { rasterizationState_.depthBiasClamp = value;
return *
this; }
777 PipelineMaker &depthBiasSlopeFactor(
float value) { rasterizationState_.depthBiasSlopeFactor = value;
return *
this; }
778 PipelineMaker &lineWidth(
float value) { rasterizationState_.lineWidth = value;
return *
this; }
784 PipelineMaker &rasterizationSamples(vk::SampleCountFlagBits value) { multisampleState_.rasterizationSamples = value;
return *
this; }
785 PipelineMaker &sampleShadingEnable(vk::Bool32 value) { multisampleState_.sampleShadingEnable = value;
return *
this; }
786 PipelineMaker &minSampleShading(
float value) { multisampleState_.minSampleShading = value;
return *
this; }
787 PipelineMaker &pSampleMask(
const vk::SampleMask* value) { multisampleState_.pSampleMask = value;
return *
this; }
788 PipelineMaker &alphaToCoverageEnable(vk::Bool32 value) { multisampleState_.alphaToCoverageEnable = value;
return *
this; }
789 PipelineMaker &alphaToOneEnable(vk::Bool32 value) { multisampleState_.alphaToOneEnable = value;
return *
this; }
794 PipelineMaker &depthTestEnable(vk::Bool32 value) { depthStencilState_.depthTestEnable = value;
return *
this; }
795 PipelineMaker &depthWriteEnable(vk::Bool32 value) { depthStencilState_.depthWriteEnable = value;
return *
this; }
796 PipelineMaker &depthCompareOp(vk::CompareOp value) { depthStencilState_.depthCompareOp = value;
return *
this; }
797 PipelineMaker &depthBoundsTestEnable(vk::Bool32 value) { depthStencilState_.depthBoundsTestEnable = value;
return *
this; }
798 PipelineMaker &stencilTestEnable(vk::Bool32 value) { depthStencilState_.stencilTestEnable = value;
return *
this; }
799 PipelineMaker &front(vk::StencilOpState value) { depthStencilState_.front = value;
return *
this; }
800 PipelineMaker &back(vk::StencilOpState value) { depthStencilState_.back = value;
return *
this; }
801 PipelineMaker &minDepthBounds(
float value) { depthStencilState_.minDepthBounds = value;
return *
this; }
802 PipelineMaker &maxDepthBounds(
float value) { depthStencilState_.maxDepthBounds = value;
return *
this; }
807 PipelineMaker &logicOpEnable(vk::Bool32 value) { colorBlendState_.logicOpEnable = value;
return *
this; }
808 PipelineMaker &logicOp(vk::LogicOp value) { colorBlendState_.logicOp = value;
return *
this; }
809 PipelineMaker &blendConstants(
float r,
float g,
float b,
float a) {
float *bc = colorBlendState_.blendConstants; bc[0] = r; bc[1] = g; bc[2] = b; bc[3] = a;
return *
this; }
811 PipelineMaker &dynamicState(vk::DynamicState value) { dynamicState_.push_back(value); }
813 vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState_;
814 vk::Viewport viewport_;
816 vk::PipelineRasterizationStateCreateInfo rasterizationState_;
817 vk::PipelineMultisampleStateCreateInfo multisampleState_;
818 vk::PipelineDepthStencilStateCreateInfo depthStencilState_;
819 vk::PipelineColorBlendStateCreateInfo colorBlendState_;
820 std::vector<vk::PipelineColorBlendAttachmentState> colorBlendAttachments_;
821 std::vector<vk::PipelineShaderStageCreateInfo> modules_;
822 std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions_;
823 std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions_;
824 std::vector<vk::DynamicState> dynamicState_;
825 uint32_t subpass_ = 0;
836 const char *entryPoint =
"main") {
837 stage_.module = shader.module();
838 stage_.pName = entryPoint;
839 stage_.stage = stage;
848 vk::UniquePipeline
createUnique(vk::Device device,
const vk::PipelineCache &pipelineCache,
const vk::PipelineLayout &pipelineLayout) {
849 vk::ComputePipelineCreateInfo pipelineInfo{};
851 pipelineInfo.stage = stage_;
852 pipelineInfo.layout = pipelineLayout;
854 return device.createComputePipelineUnique(pipelineCache, pipelineInfo);
857 vk::PipelineShaderStageCreateInfo stage_;
867 GenericBuffer(vk::Device device, vk::PhysicalDeviceMemoryProperties memprops, vk::BufferUsageFlags usage, vk::DeviceSize size, vk::MemoryPropertyFlags memflags = vk::MemoryPropertyFlagBits::eDeviceLocal) {
869 vk::BufferCreateInfo ci{};
870 ci.size = size_ = size;
872 ci.sharingMode = vk::SharingMode::eExclusive;
873 buffer_ = device.createBufferUnique(ci);
876 auto memreq = device.getBufferMemoryRequirements(*buffer_);
879 vk::MemoryAllocateInfo mai{};
880 mai.allocationSize = memreq.size;
882 mem_ = device.allocateMemoryUnique(mai);
884 device.bindBufferMemory(*buffer_, *mem_, 0);
888 void updateLocal(
const vk::Device &device,
const void *value, vk::DeviceSize size)
const {
889 void *ptr = device.mapMemory(*mem_, 0, size_, vk::MemoryMapFlags{});
890 memcpy(ptr, value, (
size_t)size);
892 device.unmapMemory(*mem_);
897 void upload(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, vk::CommandPool commandPool, vk::Queue queue,
const void *value, vk::DeviceSize size)
const {
898 if (size == 0)
return;
899 using buf = vk::BufferUsageFlagBits;
900 using pfb = vk::MemoryPropertyFlagBits;
901 auto tmp =
vku::GenericBuffer(device, memprops, buf::eTransferSrc, size, pfb::eHostVisible);
902 tmp.updateLocal(device, value, size);
905 vk::BufferCopy bc{0, 0, size};
906 cb.copyBuffer(tmp.buffer(), *buffer_, bc);
911 void upload(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, vk::CommandPool commandPool, vk::Queue queue,
const std::vector<T> &value)
const {
912 upload(device, memprops, commandPool, queue, value.data(), value.size() *
sizeof(T));
916 void upload(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, vk::CommandPool commandPool, vk::Queue queue,
const T &value)
const {
917 upload(device, memprops, commandPool, queue, &value,
sizeof(value));
920 void barrier(vk::CommandBuffer cb, vk::PipelineStageFlags srcStageMask, vk::PipelineStageFlags dstStageMask, vk::DependencyFlags dependencyFlags, vk::AccessFlags srcAccessMask, vk::AccessFlags dstAccessMask, uint32_t srcQueueFamilyIndex, uint32_t dstQueueFamilyIndex)
const {
921 vk::BufferMemoryBarrier bmb{srcAccessMask, dstAccessMask, srcQueueFamilyIndex, dstQueueFamilyIndex, *buffer_, 0, size_};
922 cb.pipelineBarrier(srcStageMask, dstStageMask, dependencyFlags,
nullptr, bmb,
nullptr);
925 template<
class Type,
class Allocator>
926 void updateLocal(
const vk::Device &device,
const std::vector<Type, Allocator> &value)
const {
927 updateLocal(device, (
void*)value.data(), vk::DeviceSize(value.size() *
sizeof(Type)));
931 void updateLocal(
const vk::Device &device,
const Type &value)
const {
932 updateLocal(device, (
void*)&value, vk::DeviceSize(
sizeof(Type)));
935 void *map(
const vk::Device &device)
const {
return device.mapMemory(*mem_, 0, size_, vk::MemoryMapFlags{}); };
936 void unmap(
const vk::Device &device)
const {
return device.unmapMemory(*mem_); };
938 void flush(
const vk::Device &device)
const {
939 vk::MappedMemoryRange mr{*mem_, 0, VK_WHOLE_SIZE};
940 return device.flushMappedMemoryRanges(mr);
943 void invalidate(
const vk::Device &device)
const {
944 vk::MappedMemoryRange mr{*mem_, 0, VK_WHOLE_SIZE};
945 return device.invalidateMappedMemoryRanges(mr);
948 vk::Buffer buffer()
const {
return *buffer_; }
949 vk::DeviceMemory mem()
const {
return *mem_; }
950 vk::DeviceSize size()
const {
return size_; }
952 vk::UniqueBuffer buffer_;
953 vk::UniqueDeviceMemory mem_;
954 vk::DeviceSize size_;
964 VertexBuffer(
const vk::Device &device,
const vk::PhysicalDeviceMemoryProperties &memprops,
size_t size) :
GenericBuffer(device, memprops, vk::BufferUsageFlagBits::eVertexBuffer, size, vk::MemoryPropertyFlagBits::eDeviceLocal) {
974 template<
class Type,
class Allocator>
975 HostVertexBuffer(
const vk::Device &device,
const vk::PhysicalDeviceMemoryProperties &memprops,
const std::vector<Type, Allocator> &value) :
GenericBuffer(device, memprops, vk::BufferUsageFlagBits::eVertexBuffer, value.size() *
sizeof(Type), vk::MemoryPropertyFlagBits::eHostVisible) {
976 updateLocal(device, value);
987 IndexBuffer(
const vk::Device &device,
const vk::PhysicalDeviceMemoryProperties &memprops, vk::DeviceSize size) :
GenericBuffer(device, memprops, vk::BufferUsageFlagBits::eIndexBuffer, size, vk::MemoryPropertyFlagBits::eDeviceLocal) {
997 template<
class Type,
class Allocator>
998 HostIndexBuffer(
const vk::Device &device,
const vk::PhysicalDeviceMemoryProperties &memprops,
const std::vector<Type, Allocator> &value) :
GenericBuffer(device, memprops, vk::BufferUsageFlagBits::eIndexBuffer, value.size() *
sizeof(Type), vk::MemoryPropertyFlagBits::eHostVisible) {
999 updateLocal(device, value);
1010 UniformBuffer(
const vk::Device &device,
const vk::PhysicalDeviceMemoryProperties &memprops,
size_t size) :
GenericBuffer(device, memprops, vk::BufferUsageFlagBits::eUniformBuffer|vk::BufferUsageFlagBits::eTransferDst, (vk::DeviceSize)size, vk::MemoryPropertyFlagBits::eDeviceLocal) {
1019 bufferInfo_.resize(maxBuffers);
1020 imageInfo_.resize(maxImages);
1021 bufferViews_.resize(maxBufferViews);
1030 void beginImages(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType) {
1031 vk::WriteDescriptorSet wdesc{};
1032 wdesc.dstSet = dstSet_;
1033 wdesc.dstBinding = dstBinding;
1034 wdesc.dstArrayElement = dstArrayElement;
1035 wdesc.descriptorCount = 0;
1036 wdesc.descriptorType = descriptorType;
1037 wdesc.pImageInfo = imageInfo_.data() + numImages_;
1038 descriptorWrites_.push_back(wdesc);
1042 void image(vk::Sampler sampler, vk::ImageView imageView, vk::ImageLayout imageLayout) {
1043 if (!descriptorWrites_.empty() && numImages_ != imageInfo_.size() && descriptorWrites_.back().pImageInfo) {
1044 descriptorWrites_.back().descriptorCount++;
1045 imageInfo_[numImages_++] = vk::DescriptorImageInfo{sampler, imageView, imageLayout};
1052 void beginBuffers(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType) {
1053 vk::WriteDescriptorSet wdesc{};
1054 wdesc.dstSet = dstSet_;
1055 wdesc.dstBinding = dstBinding;
1056 wdesc.dstArrayElement = dstArrayElement;
1057 wdesc.descriptorCount = 0;
1058 wdesc.descriptorType = descriptorType;
1059 wdesc.pBufferInfo = bufferInfo_.data() + numBuffers_;
1060 descriptorWrites_.push_back(wdesc);
1064 void buffer(vk::Buffer buffer, vk::DeviceSize offset, vk::DeviceSize range) {
1065 if (!descriptorWrites_.empty() && numBuffers_ != bufferInfo_.size() && descriptorWrites_.back().pBufferInfo) {
1066 descriptorWrites_.back().descriptorCount++;
1067 bufferInfo_[numBuffers_++] = vk::DescriptorBufferInfo{buffer, offset, range};
1074 void beginBufferViews(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType) {
1075 vk::WriteDescriptorSet wdesc{};
1076 wdesc.dstSet = dstSet_;
1077 wdesc.dstBinding = dstBinding;
1078 wdesc.dstArrayElement = dstArrayElement;
1079 wdesc.descriptorCount = 0;
1080 wdesc.descriptorType = descriptorType;
1081 wdesc.pTexelBufferView = bufferViews_.data() + numBufferViews_;
1082 descriptorWrites_.push_back(wdesc);
1087 if (!descriptorWrites_.empty() && numBufferViews_ != bufferViews_.size() && descriptorWrites_.back().pImageInfo) {
1088 descriptorWrites_.back().descriptorCount++;
1089 bufferViews_[numBufferViews_++] = view;
1096 void copy(vk::DescriptorSet srcSet, uint32_t srcBinding, uint32_t srcArrayElement, vk::DescriptorSet dstSet, uint32_t dstBinding, uint32_t dstArrayElement, uint32_t descriptorCount) {
1097 descriptorCopies_.emplace_back(srcSet, srcBinding, srcArrayElement, dstSet, dstBinding, dstArrayElement, descriptorCount);
1101 void update(
const vk::Device &device)
const {
1102 device.updateDescriptorSets( descriptorWrites_, descriptorCopies_ );
1106 bool ok()
const {
return ok_; }
1108 std::vector<vk::DescriptorBufferInfo> bufferInfo_;
1109 std::vector<vk::DescriptorImageInfo> imageInfo_;
1110 std::vector<vk::WriteDescriptorSet> descriptorWrites_;
1111 std::vector<vk::CopyDescriptorSet> descriptorCopies_;
1112 std::vector<vk::BufferView> bufferViews_;
1113 vk::DescriptorSet dstSet_;
1114 int numBuffers_ = 0;
1116 int numBufferViews_ = 0;
1126 void buffer(uint32_t binding, vk::DescriptorType descriptorType, vk::ShaderStageFlags stageFlags, uint32_t descriptorCount) {
1127 s.bindings.emplace_back(binding, descriptorType, descriptorCount, stageFlags,
nullptr);
1130 void image(uint32_t binding, vk::DescriptorType descriptorType, vk::ShaderStageFlags stageFlags, uint32_t descriptorCount) {
1131 s.bindings.emplace_back(binding, descriptorType, descriptorCount, stageFlags,
nullptr);
1134 void samplers(uint32_t binding, vk::DescriptorType descriptorType, vk::ShaderStageFlags stageFlags,
const std::vector<vk::Sampler> immutableSamplers) {
1135 s.samplers.push_back(immutableSamplers);
1136 auto pImmutableSamplers = s.samplers.back().data();
1137 s.bindings.emplace_back(binding, descriptorType, (uint32_t)immutableSamplers.size(), stageFlags, pImmutableSamplers);
1140 void bufferView(uint32_t binding, vk::DescriptorType descriptorType, vk::ShaderStageFlags stageFlags, uint32_t descriptorCount) {
1141 s.bindings.emplace_back(binding, descriptorType, descriptorCount, stageFlags,
nullptr);
1146 vk::DescriptorSetLayoutCreateInfo dsci{};
1147 dsci.bindingCount = (uint32_t)s.bindings.size();
1148 dsci.pBindings = s.bindings.data();
1149 return device.createDescriptorSetLayoutUnique(dsci);
1154 std::vector<vk::DescriptorSetLayoutBinding> bindings;
1155 std::vector<std::vector<vk::Sampler> > samplers;
1156 int numSamplers = 0;
1170 void layout(vk::DescriptorSetLayout layout) {
1171 s.layouts.push_back(layout);
1176 std::vector<vk::DescriptorSet>
create(vk::Device device, vk::DescriptorPool descriptorPool)
const {
1177 vk::DescriptorSetAllocateInfo dsai{};
1178 dsai.descriptorPool = descriptorPool;
1179 dsai.descriptorSetCount = (uint32_t)s.layouts.size();
1180 dsai.pSetLayouts = s.layouts.data();
1181 return device.allocateDescriptorSets(dsai);
1185 std::vector<vk::UniqueDescriptorSet>
createUnique(vk::Device device, vk::DescriptorPool descriptorPool)
const {
1186 vk::DescriptorSetAllocateInfo dsai{};
1187 dsai.descriptorPool = descriptorPool;
1188 dsai.descriptorSetCount = (uint32_t)s.layouts.size();
1189 dsai.pSetLayouts = s.layouts.data();
1190 return device.allocateDescriptorSetsUnique(dsai);
1195 std::vector<vk::DescriptorSetLayout> layouts;
1208 GenericImage(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops,
const vk::ImageCreateInfo &info, vk::ImageViewType viewType, vk::ImageAspectFlags aspectMask,
bool makeHostImage) {
1209 create(device, memprops, info, viewType, aspectMask, makeHostImage);
1212 vk::Image image()
const {
return *s.image; }
1213 vk::ImageView imageView()
const {
return *s.imageView; }
1214 vk::DeviceMemory mem()
const {
return *s.mem; }
1217 void clear(vk::CommandBuffer cb,
const std::array<float,4> colour = {1, 1, 1, 1}) {
1218 setLayout(cb, vk::ImageLayout::eTransferDstOptimal);
1219 vk::ClearColorValue ccv(colour);
1220 vk::ImageSubresourceRange range{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1};
1221 cb.clearColorImage(*s.image, vk::ImageLayout::eTransferDstOptimal, ccv, range);
1225 void update(vk::Device device,
const void *data, vk::DeviceSize bytesPerPixel) {
1226 const uint8_t *src = (
const uint8_t *)data;
1227 for (uint32_t mipLevel = 0; mipLevel != info().mipLevels; ++mipLevel) {
1229 for (uint32_t arrayLayer = 0; arrayLayer != info().arrayLayers; ++arrayLayer) {
1230 vk::ImageSubresource subresource{vk::ImageAspectFlagBits::eColor, mipLevel, arrayLayer};
1231 auto srlayout = device.getImageSubresourceLayout(*s.image, subresource);
1232 uint8_t *dest = (uint8_t *)device.mapMemory(*s.mem, 0, s.size, vk::MemoryMapFlags{}) + srlayout.offset;
1233 size_t bytesPerLine = s.info.extent.width * bytesPerPixel;
1234 size_t srcStride = bytesPerLine * info().arrayLayers;
1235 for (
int y = 0; y != s.info.extent.height; ++y) {
1236 memcpy(dest, src + arrayLayer * bytesPerLine, bytesPerLine);
1238 dest += srlayout.rowPitch;
1242 device.unmapMemory(*s.mem);
1247 srcImage.
setLayout(cb, vk::ImageLayout::eTransferSrcOptimal);
1248 setLayout(cb, vk::ImageLayout::eTransferDstOptimal);
1249 for (uint32_t mipLevel = 0; mipLevel != info().mipLevels; ++mipLevel) {
1250 vk::ImageCopy region{};
1251 region.srcSubresource = {vk::ImageAspectFlagBits::eColor, mipLevel, 0, 1};
1252 region.dstSubresource = {vk::ImageAspectFlagBits::eColor, mipLevel, 0, 1};
1253 region.extent = s.info.extent;
1254 cb.copyImage(srcImage.image(), vk::ImageLayout::eTransferSrcOptimal, *s.image, vk::ImageLayout::eTransferDstOptimal, region);
1259 void copy(vk::CommandBuffer cb, vk::Buffer buffer, uint32_t mipLevel, uint32_t arrayLayer, uint32_t width, uint32_t height, uint32_t depth, uint32_t offset) {
1260 setLayout(cb, vk::ImageLayout::eTransferDstOptimal);
1261 vk::BufferImageCopy region{};
1262 region.bufferOffset = offset;
1263 vk::Extent3D extent;
1264 extent.width = width;
1265 extent.height = height;
1266 extent.depth = depth;
1267 region.imageSubresource = {vk::ImageAspectFlagBits::eColor, mipLevel, arrayLayer, 1};
1268 region.imageExtent = extent;
1269 cb.copyBufferToImage(buffer, *s.image, vk::ImageLayout::eTransferDstOptimal, region);
1272 void upload(vk::Device device, std::vector<uint8_t> &bytes, vk::CommandPool commandPool, vk::PhysicalDeviceMemoryProperties memprops, vk::Queue queue) {
1273 vku::GenericBuffer stagingBuffer(device, memprops, (vk::BufferUsageFlags)vk::BufferUsageFlagBits::eTransferSrc, (vk::DeviceSize)bytes.size(), vk::MemoryPropertyFlagBits::eHostVisible);
1274 stagingBuffer.
updateLocal(device, (
const void*)bytes.data(), bytes.size());
1279 vk::Buffer buf = stagingBuffer.buffer();
1280 uint32_t offset = 0;
1281 for (uint32_t mipLevel = 0; mipLevel != s.info.mipLevels; ++mipLevel) {
1282 auto width =
mipScale(s.info.extent.width, mipLevel);
1283 auto height =
mipScale(s.info.extent.height, mipLevel);
1284 auto depth =
mipScale(s.info.extent.depth, mipLevel);
1285 for (uint32_t face = 0; face != s.info.arrayLayers; ++face) {
1286 copy(cb, buf, mipLevel, face, width, height, depth, offset);
1287 offset += ((bp.bytesPerBlock + 3) & ~3) * (width * height);
1290 setLayout(cb, vk::ImageLayout::eShaderReadOnlyOptimal);
1295 void setLayout(vk::CommandBuffer cb, vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask = vk::ImageAspectFlagBits::eColor) {
1296 if (newLayout == s.currentLayout)
return;
1297 vk::ImageLayout oldLayout = s.currentLayout;
1298 s.currentLayout = newLayout;
1300 vk::ImageMemoryBarrier imageMemoryBarriers = {};
1301 imageMemoryBarriers.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1302 imageMemoryBarriers.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1303 imageMemoryBarriers.oldLayout = oldLayout;
1304 imageMemoryBarriers.newLayout = newLayout;
1305 imageMemoryBarriers.image = *s.image;
1306 imageMemoryBarriers.subresourceRange = {aspectMask, 0, s.info.mipLevels, 0, s.info.arrayLayers};
1309 vk::PipelineStageFlags srcStageMask{vk::PipelineStageFlagBits::eTopOfPipe};
1310 vk::PipelineStageFlags dstStageMask{vk::PipelineStageFlagBits::eTopOfPipe};
1311 vk::DependencyFlags dependencyFlags{};
1312 vk::AccessFlags srcMask{};
1313 vk::AccessFlags dstMask{};
1315 typedef vk::ImageLayout il;
1316 typedef vk::AccessFlagBits afb;
1319 switch (oldLayout) {
1320 case il::eUndefined:
break;
1321 case il::eGeneral: srcMask = afb::eTransferWrite;
break;
1322 case il::eColorAttachmentOptimal: srcMask = afb::eColorAttachmentWrite;
break;
1323 case il::eDepthStencilAttachmentOptimal: srcMask = afb::eDepthStencilAttachmentWrite;
break;
1324 case il::eDepthStencilReadOnlyOptimal: srcMask = afb::eDepthStencilAttachmentRead;
break;
1325 case il::eShaderReadOnlyOptimal: srcMask = afb::eShaderRead;
break;
1326 case il::eTransferSrcOptimal: srcMask = afb::eTransferRead;
break;
1327 case il::eTransferDstOptimal: srcMask = afb::eTransferWrite;
break;
1328 case il::ePreinitialized: srcMask = afb::eTransferWrite|afb::eHostWrite;
break;
1329 case il::ePresentSrcKHR: srcMask = afb::eMemoryRead;
break;
1332 switch (newLayout) {
1333 case il::eUndefined:
break;
1334 case il::eGeneral: dstMask = afb::eTransferWrite;
break;
1335 case il::eColorAttachmentOptimal: dstMask = afb::eColorAttachmentWrite;
break;
1336 case il::eDepthStencilAttachmentOptimal: dstMask = afb::eDepthStencilAttachmentWrite;
break;
1337 case il::eDepthStencilReadOnlyOptimal: dstMask = afb::eDepthStencilAttachmentRead;
break;
1338 case il::eShaderReadOnlyOptimal: dstMask = afb::eShaderRead;
break;
1339 case il::eTransferSrcOptimal: dstMask = afb::eTransferRead;
break;
1340 case il::eTransferDstOptimal: dstMask = afb::eTransferWrite;
break;
1341 case il::ePreinitialized: dstMask = afb::eTransferWrite;
break;
1342 case il::ePresentSrcKHR: dstMask = afb::eMemoryRead;
break;
1346 imageMemoryBarriers.srcAccessMask = srcMask;
1347 imageMemoryBarriers.dstAccessMask = dstMask;
1348 auto memoryBarriers =
nullptr;
1349 auto bufferMemoryBarriers =
nullptr;
1350 cb.pipelineBarrier(srcStageMask, dstStageMask, dependencyFlags, memoryBarriers, bufferMemoryBarriers, imageMemoryBarriers);
1355 s.currentLayout = oldLayout;
1358 vk::Format
format()
const {
return s.info.format; }
1359 vk::Extent3D extent()
const {
return s.info.extent; }
1360 const vk::ImageCreateInfo &info()
const {
return s.info; }
1362 void create(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops,
const vk::ImageCreateInfo &info, vk::ImageViewType viewType, vk::ImageAspectFlags aspectMask,
bool hostImage) {
1363 s.currentLayout = info.initialLayout;
1365 s.image = device.createImageUnique(info);
1368 auto memreq = device.getImageMemoryRequirements(*s.image);
1369 vk::MemoryPropertyFlags search{};
1370 if (hostImage) search = vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible;
1374 vk::MemoryAllocateInfo mai{};
1375 mai.allocationSize = s.size = memreq.size;
1377 s.mem = device.allocateMemoryUnique(mai);
1379 device.bindImageMemory(*s.image, *s.mem, 0);
1382 vk::ImageViewCreateInfo viewInfo{};
1383 viewInfo.image = *s.image;
1384 viewInfo.viewType = viewType;
1385 viewInfo.format = info.format;
1386 viewInfo.components = { vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA };
1387 viewInfo.subresourceRange = vk::ImageSubresourceRange{aspectMask, 0, info.mipLevels, 0, info.arrayLayers};
1388 s.imageView = device.createImageViewUnique(viewInfo);
1393 vk::UniqueImage image;
1394 vk::UniqueImageView imageView;
1395 vk::UniqueDeviceMemory mem;
1396 vk::DeviceSize size;
1397 vk::ImageLayout currentLayout;
1398 vk::ImageCreateInfo info;
1412 TextureImage2D(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t width, uint32_t height, uint32_t mipLevels=1, vk::Format
format = vk::Format::eR8G8B8A8Unorm,
bool hostImage =
false) {
1413 vk::ImageCreateInfo info;
1415 info.imageType = vk::ImageType::e2D;
1417 info.extent = vk::Extent3D{ width, height, 1U };
1418 info.mipLevels = mipLevels;
1419 info.arrayLayers = 1;
1420 info.samples = vk::SampleCountFlagBits::e1;
1421 info.tiling = hostImage ? vk::ImageTiling::eLinear : vk::ImageTiling::eOptimal;
1422 info.usage = vk::ImageUsageFlagBits::eSampled|vk::ImageUsageFlagBits::eTransferSrc|vk::ImageUsageFlagBits::eTransferDst;
1423 info.sharingMode = vk::SharingMode::eExclusive;
1424 info.queueFamilyIndexCount = 0;
1425 info.pQueueFamilyIndices =
nullptr;
1426 info.initialLayout = hostImage ? vk::ImageLayout::ePreinitialized : vk::ImageLayout::eUndefined;
1427 create(device, memprops, info, vk::ImageViewType::e2D, vk::ImageAspectFlagBits::eColor, hostImage);
1438 TextureImageCube(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t width, uint32_t height, uint32_t mipLevels=1, vk::Format
format = vk::Format::eR8G8B8A8Unorm,
bool hostImage =
false) {
1439 vk::ImageCreateInfo info;
1440 info.flags = {vk::ImageCreateFlagBits::eCubeCompatible};
1441 info.imageType = vk::ImageType::e2D;
1443 info.extent = vk::Extent3D{ width, height, 1U };
1444 info.mipLevels = mipLevels;
1445 info.arrayLayers = 6;
1446 info.samples = vk::SampleCountFlagBits::e1;
1447 info.tiling = hostImage ? vk::ImageTiling::eLinear : vk::ImageTiling::eOptimal;
1448 info.usage = vk::ImageUsageFlagBits::eSampled|vk::ImageUsageFlagBits::eTransferSrc|vk::ImageUsageFlagBits::eTransferDst;
1449 info.sharingMode = vk::SharingMode::eExclusive;
1450 info.queueFamilyIndexCount = 0;
1451 info.pQueueFamilyIndices =
nullptr;
1453 info.initialLayout = vk::ImageLayout::ePreinitialized;
1454 create(device, memprops, info, vk::ImageViewType::eCube, vk::ImageAspectFlagBits::eColor, hostImage);
1465 DepthStencilImage(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t width, uint32_t height, vk::Format
format = vk::Format::eD24UnormS8Uint) {
1466 vk::ImageCreateInfo info;
1469 info.imageType = vk::ImageType::e2D;
1471 info.extent = vk::Extent3D{ width, height, 1U };
1473 info.arrayLayers = 1;
1474 info.samples = vk::SampleCountFlagBits::e1;
1475 info.tiling = vk::ImageTiling::eOptimal;
1476 info.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment|vk::ImageUsageFlagBits::eTransferSrc|vk::ImageUsageFlagBits::eSampled;
1477 info.sharingMode = vk::SharingMode::eExclusive;
1478 info.queueFamilyIndexCount = 0;
1479 info.pQueueFamilyIndices =
nullptr;
1480 info.initialLayout = vk::ImageLayout::eUndefined;
1481 typedef vk::ImageAspectFlagBits iafb;
1482 create(device, memprops, info, vk::ImageViewType::e2D, iafb::eDepth,
false);
1493 ColorAttachmentImage(vk::Device device,
const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t width, uint32_t height, vk::Format
format = vk::Format::eR8G8B8A8Unorm) {
1494 vk::ImageCreateInfo info;
1497 info.imageType = vk::ImageType::e2D;
1499 info.extent = vk::Extent3D{ width, height, 1U };
1501 info.arrayLayers = 1;
1502 info.samples = vk::SampleCountFlagBits::e1;
1503 info.tiling = vk::ImageTiling::eOptimal;
1504 info.usage = vk::ImageUsageFlagBits::eColorAttachment|vk::ImageUsageFlagBits::eTransferSrc|vk::ImageUsageFlagBits::eSampled;
1505 info.sharingMode = vk::SharingMode::eExclusive;
1506 info.queueFamilyIndexCount = 0;
1507 info.pQueueFamilyIndices =
nullptr;
1508 info.initialLayout = vk::ImageLayout::eUndefined;
1509 typedef vk::ImageAspectFlagBits iafb;
1510 create(device, memprops, info, vk::ImageViewType::e2D, iafb::eColor,
false);
1524 s.info.magFilter = vk::Filter::eNearest;
1525 s.info.minFilter = vk::Filter::eNearest;
1526 s.info.mipmapMode = vk::SamplerMipmapMode::eNearest;
1527 s.info.addressModeU = vk::SamplerAddressMode::eRepeat;
1528 s.info.addressModeV = vk::SamplerAddressMode::eRepeat;
1529 s.info.addressModeW = vk::SamplerAddressMode::eRepeat;
1530 s.info.mipLodBias = 0.0f;
1531 s.info.anisotropyEnable = 0;
1532 s.info.maxAnisotropy = 0.0f;
1533 s.info.compareEnable = 0;
1534 s.info.compareOp = vk::CompareOp::eNever;
1537 s.info.borderColor = vk::BorderColor{};
1538 s.info.unnormalizedCoordinates = 0;
1545 SamplerMaker &flags(vk::SamplerCreateFlags value) { s.info.flags = value;
return *
this; }
1558 SamplerMaker &addressModeU(vk::SamplerAddressMode value) { s.info.addressModeU = value;
return *
this; }
1559 SamplerMaker &addressModeV(vk::SamplerAddressMode value) { s.info.addressModeV = value;
return *
this; }
1560 SamplerMaker &addressModeW(vk::SamplerAddressMode value) { s.info.addressModeW = value;
return *
this; }
1561 SamplerMaker &mipLodBias(
float value) { s.info.mipLodBias = value;
return *
this; }
1562 SamplerMaker &anisotropyEnable(vk::Bool32 value) { s.info.anisotropyEnable = value;
return *
this; }
1563 SamplerMaker &maxAnisotropy(
float value) { s.info.maxAnisotropy = value;
return *
this; }
1564 SamplerMaker &compareEnable(vk::Bool32 value) { s.info.compareEnable = value;
return *
this; }
1565 SamplerMaker &compareOp(vk::CompareOp value) { s.info.compareOp = value;
return *
this; }
1566 SamplerMaker &minLod(
float value) { s.info.minLod = value;
return *
this; }
1567 SamplerMaker &maxLod(
float value) { s.info.maxLod = value;
return *
this; }
1568 SamplerMaker &borderColor(vk::BorderColor value) { s.info.borderColor = value;
return *
this; }
1569 SamplerMaker &unnormalizedCoordinates(vk::Bool32 value) { s.info.unnormalizedCoordinates = value;
return *
this; }
1573 return device.createSamplerUnique(s.info);
1577 vk::Sampler
create(vk::Device device)
const {
1578 return device.createSampler(s.info);
1583 vk::SamplerCreateInfo info;
1592 case 0x1907:
return vk::Format::eR8G8B8Unorm;
1593 case 0x1908:
return vk::Format::eR8G8B8A8Unorm;
1594 case 0x83F0:
return vk::Format::eBc1RgbUnormBlock;
1595 case 0x83F1:
return vk::Format::eBc1RgbaUnormBlock;
1596 case 0x83F2:
return vk::Format::eBc3UnormBlock;
1597 case 0x83F3:
return vk::Format::eBc5UnormBlock;
1599 return vk::Format::eUndefined;
1612 if (p +
sizeof(Header) > end)
return;
1613 header = *(Header*)p;
1614 static const uint8_t magic[] = {
1615 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
1619 if (memcmp(magic, header.identifier,
sizeof(magic))) {
1623 if (header.endianness != 0x04030201) {
1624 swap(header.glType);
1625 swap(header.glTypeSize);
1626 swap(header.glFormat);
1627 swap(header.glInternalFormat);
1628 swap(header.glBaseInternalFormat);
1629 swap(header.pixelWidth);
1630 swap(header.pixelHeight);
1631 swap(header.pixelDepth);
1632 swap(header.numberOfArrayElements);
1633 swap(header.numberOfFaces);
1634 swap(header.numberOfMipmapLevels);
1635 swap(header.bytesOfKeyValueData);
1638 header.numberOfArrayElements = std::max(1U, header.numberOfArrayElements);
1639 header.numberOfFaces = std::max(1U, header.numberOfFaces);
1640 header.numberOfMipmapLevels = std::max(1U, header.numberOfMipmapLevels);
1641 header.pixelDepth = std::max(1U, header.pixelDepth);
1644 if (format_ == vk::Format::eUndefined)
return;
1646 p +=
sizeof(Header);
1647 if (p + header.bytesOfKeyValueData > end)
return;
1649 for (uint32_t i = 0; i < header.bytesOfKeyValueData; ) {
1650 uint32_t keyAndValueByteSize = *(uint32_t*)(p + i);
1651 if (header.endianness != 0x04030201) swap(keyAndValueByteSize);
1652 std::string kv(p + i + 4, p + i + 4 + keyAndValueByteSize);
1653 i += keyAndValueByteSize + 4;
1657 p += header.bytesOfKeyValueData;
1658 for (uint32_t mipLevel = 0; mipLevel != header.numberOfMipmapLevels; ++mipLevel) {
1659 uint32_t imageSize = *(uint32_t*)(p);
1660 imageSize = (imageSize + 3) & ~3;
1661 uint32_t incr = imageSize * header.numberOfFaces * header.numberOfArrayElements;
1662 incr = (incr + 3) & ~3;
1664 if (p + incr > end) {
1667 header.numberOfMipmapLevels = mipLevel;
1671 if (header.endianness != 0x04030201) swap(imageSize);
1674 imageOffsets_.push_back((uint32_t)(p - begin));
1675 imageSizes_.push_back(imageSize);
1682 uint32_t offset(uint32_t mipLevel, uint32_t arrayLayer, uint32_t face) {
1683 return imageOffsets_[mipLevel] + (arrayLayer * header.numberOfFaces + face) * imageSizes_[mipLevel];
1686 uint32_t size(uint32_t mipLevel) {
1687 return imageSizes_[mipLevel];
1690 bool ok()
const {
return ok_; }
1691 vk::Format
format()
const {
return format_; }
1692 uint32_t mipLevels()
const {
return header.numberOfMipmapLevels; }
1693 uint32_t arrayLayers()
const {
return header.numberOfArrayElements; }
1694 uint32_t faces()
const {
return header.numberOfFaces; }
1695 uint32_t width(uint32_t mipLevel)
const {
return mipScale(header.pixelWidth, mipLevel); }
1696 uint32_t height(uint32_t mipLevel)
const {
return mipScale(header.pixelHeight, mipLevel); }
1697 uint32_t depth(uint32_t mipLevel)
const {
return mipScale(header.pixelDepth, mipLevel); }
1699 void upload(vk::Device device,
vku::GenericImage &image, std::vector<uint8_t> &bytes, vk::CommandPool commandPool, vk::PhysicalDeviceMemoryProperties memprops, vk::Queue queue) {
1700 vku::GenericBuffer stagingBuffer(device, memprops, (vk::BufferUsageFlags)vk::BufferUsageFlagBits::eTransferSrc, (vk::DeviceSize)bytes.size(), vk::MemoryPropertyFlagBits::eHostVisible);
1701 stagingBuffer.
updateLocal(device, (
const void*)bytes.data(), bytes.size());
1705 vk::Buffer buf = stagingBuffer.buffer();
1706 for (uint32_t mipLevel = 0; mipLevel != mipLevels(); ++mipLevel) {
1707 auto width = this->width(mipLevel);
1708 auto height = this->height(mipLevel);
1709 auto depth = this->depth(mipLevel);
1710 for (uint32_t face = 0; face != faces(); ++face) {
1711 image.
copy(cb, buf, mipLevel, face, width, height, depth, offset(mipLevel, 0, face));
1714 image.
setLayout(cb, vk::ImageLayout::eShaderReadOnlyOptimal);
1719 static void swap(uint32_t &value) {
1720 value = value >> 24 | (value & 0xff0000) >> 8 | (value & 0xff00) << 8 | value << 24;
1724 uint8_t identifier[12];
1725 uint32_t endianness;
1727 uint32_t glTypeSize;
1729 uint32_t glInternalFormat;
1730 uint32_t glBaseInternalFormat;
1731 uint32_t pixelWidth;
1732 uint32_t pixelHeight;
1733 uint32_t pixelDepth;
1734 uint32_t numberOfArrayElements;
1735 uint32_t numberOfFaces;
1736 uint32_t numberOfMipmapLevels;
1737 uint32_t bytesOfKeyValueData;
1743 std::vector<uint32_t> imageOffsets_;
1744 std::vector<uint32_t> imageSizes_;
std::vector< vk::UniqueDescriptorSet > createUnique(vk::Device device, vk::DescriptorPool descriptorPool) const
Allocate a vector of self-deleting descriptor sets.
Definition: vku.hpp:1185
void vertexBinding(uint32_t binding_, uint32_t stride_, vk::VertexInputRate inputRate_=vk::VertexInputRate::eVertex)
Definition: vku.hpp:735
SamplerMaker()
Default to a very basic sampler.
Definition: vku.hpp:1523
vk::UniquePipeline createUnique(vk::Device device, const vk::PipelineCache &pipelineCache, const vk::PipelineLayout &pipelineLayout)
Create a managed handle to a compute shader.
Definition: vku.hpp:848
std::vector< vk::DescriptorSet > create(vk::Device device, vk::DescriptorPool descriptorPool) const
Definition: vku.hpp:1176
vk::UniqueDescriptorSetLayout createUnique(vk::Device device) const
Create a self-deleting descriptor set object.
Definition: vku.hpp:1145
PipelineMaker & primitiveRestartEnable(vk::Bool32 primitiveRestartEnable)
Definition: vku.hpp:752
void blendSrcColorBlendFactor(vk::BlendFactor value)
Source colour blend factor (called after blendBegin())
Definition: vku.hpp:702
void copy(vk::CommandBuffer cb, vk::Buffer buffer, uint32_t mipLevel, uint32_t arrayLayer, uint32_t width, uint32_t height, uint32_t depth, uint32_t offset)
Copy a subimage in a buffer to this image.
Definition: vku.hpp:1259
ShaderModule(const vk::Device &device, const std::string &filename)
Construct a shader module from a file.
Definition: vku.hpp:410
A factory class for descriptor sets (A set of uniform bindings)
Definition: vku.hpp:1163
void blendDstAlphaBlendFactor(vk::BlendFactor value)
Destination alpha blend factor (called after blendBegin())
Definition: vku.hpp:714
Convenience class for updating descriptor sets (uniforms)
Definition: vku.hpp:1015
void blendAlphaBlendOp(vk::BlendOp value)
Alpha operation (called after blendBegin())
Definition: vku.hpp:717
void descriptorSetLayout(vk::DescriptorSetLayout layout)
Add a descriptor set layout to the pipeline.
Definition: vku.hpp:566
void vertexAttribute(uint32_t location_, uint32_t binding_, vk::Format format_, uint32_t offset_)
Add a vertex attribute to the pipeline.
Definition: vku.hpp:723
void setCurrentLayout(vk::ImageLayout oldLayout)
Set what the image thinks is its current layout (ie. the old layout in an image barrier).
Definition: vku.hpp:1354
std::ostream & write(std::ostream &os)
Definition: vku.hpp:519
void blendEnable(vk::Bool32 value)
Enable or disable blending (called after blendBegin())
Definition: vku.hpp:699
void subpassBegin(vk::PipelineBindPoint bp)
Definition: vku.hpp:334
vk::UniqueSampler createUnique(vk::Device device) const
Allocate a self-deleting image.
Definition: vku.hpp:1572
void executeImmediately(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, const std::function< void(vk::CommandBuffer cb)> &func)
Execute commands immediately and wait for the device to finish.
Definition: vku.hpp:58
void vertexAttribute(const vk::VertexInputAttributeDescription &desc)
Add a vertex attribute to the pipeline.
Definition: vku.hpp:728
PipelineMaker & viewport(const vk::Viewport &value)
Definition: vku.hpp:760
vk::Sampler create(vk::Device device) const
Allocate a non self-deleting Sampler.
Definition: vku.hpp:1577
void beginImages(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType)
Call this to begin a new set of images.
Definition: vku.hpp:1030
SamplerMaker & minFilter(vk::Filter value)
Definition: vku.hpp:1553
void beginBuffers(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType)
Call this to start defining buffers.
Definition: vku.hpp:1052
SamplerMaker & magFilter(vk::Filter value)
Definition: vku.hpp:1549
void update(const vk::Device &device) const
Call this to update the descriptor sets with their pointers (but not data).
Definition: vku.hpp:1101
void shader(vk::ShaderStageFlagBits stage, vku::ShaderModule &shader, const char *entryPoint="main")
Add a shader module to the pipeline.
Definition: vku.hpp:835
A class for building compute pipelines.
Definition: vku.hpp:829
BlockParams getBlockParams(vk::Format format)
Get the details of vulkan texture formats.
Definition: vku.hpp:102
void shader(vk::ShaderStageFlagBits stage, vku::ShaderModule &shader, const char *entryPoint="main")
Add a shader module to the pipeline.
Definition: vku.hpp:661
SamplerMaker & mipmapMode(vk::SamplerMipmapMode value)
Definition: vku.hpp:1557
void blendColorWriteMask(vk::ColorComponentFlags value)
Colour write mask (called after blendBegin())
Definition: vku.hpp:720
void update(vk::Device device, const void *data, vk::DeviceSize bytesPerPixel)
Update the image with an array of pixels. (Currently 2D only)
Definition: vku.hpp:1225
uint32_t mipScale(uint32_t value, uint32_t mipLevel)
Scale a value by mip level, but do not reduce to zero.
Definition: vku.hpp:76
PipelineMaker & inputAssemblyState(const vk::PipelineInputAssemblyStateCreateInfo &value)
Definition: vku.hpp:756
PipelineMaker & colorBlendState(const vk::PipelineColorBlendStateCreateInfo &value)
Definition: vku.hpp:806
void clear(vk::CommandBuffer cb, const std::array< float, 4 > colour={1, 1, 1, 1})
Clear the colour of an image.
Definition: vku.hpp:1217
void beginDescriptorSet(vk::DescriptorSet dstSet)
Call this to begin a new descriptor set.
Definition: vku.hpp:1025
void upload(vk::Device device, const vk::PhysicalDeviceMemoryProperties &memprops, vk::CommandPool commandPool, vk::Queue queue, const void *value, vk::DeviceSize size) const
Definition: vku.hpp:897
void blendDstColorBlendFactor(vk::BlendFactor value)
Destination colour blend factor (called after blendBegin())
Definition: vku.hpp:705
void blendSrcAlphaBlendFactor(vk::BlendFactor value)
Source alpha blend factor (called after blendBegin())
Definition: vku.hpp:711
PipelineMaker & rasterizationState(const vk::PipelineRasterizationStateCreateInfo &value)
Definition: vku.hpp:768
void beginBufferViews(uint32_t dstBinding, uint32_t dstArrayElement, vk::DescriptorType descriptorType)
Call this to start adding buffer views. (for example, writable images).
Definition: vku.hpp:1074
void attachmentBegin(vk::Format format)
Definition: vku.hpp:316
Layout of a KTX file in a buffer.
Definition: vku.hpp:1605
A factory class for descriptor set layouts. (An interface to the shaders)
Definition: vku.hpp:1121
PipelineMaker & multisampleState(const vk::PipelineMultisampleStateCreateInfo &value)
Definition: vku.hpp:783
void blendBegin(vk::Bool32 enable)
Definition: vku.hpp:684
std::string format(const char *fmt, Args...args)
Printf-style formatting function.
Definition: vku.hpp:38
std::vector< uint8_t > loadFile(const std::string &filename)
Definition: vku.hpp:82
void pushConstantRange(vk::ShaderStageFlags stageFlags_, uint32_t offset_, uint32_t size_)
Definition: vku.hpp:572
void colorBlend(const vk::PipelineColorBlendAttachmentState &state)
Definition: vku.hpp:672
void bufferView(vk::BufferView view)
Call this to add a buffer view. (Texel images)
Definition: vku.hpp:1086
int findMemoryTypeIndex(const vk::PhysicalDeviceMemoryProperties &memprops, uint32_t memoryTypeBits, vk::MemoryPropertyFlags search)
Utility function for finding memory types for uniforms and images.
Definition: vku.hpp:46
An image to use as a colour buffer on a renderpass.
Definition: vku.hpp:1488
void layout(vk::DescriptorSetLayout layout)
Add another layout describing a descriptor set.
Definition: vku.hpp:1170
PipelineMaker & topology(vk::PrimitiveTopology topology)
Definition: vku.hpp:748
Description of blocks for compressed formats.
Definition: vku.hpp:95
A variable in a shader.
Definition: vku.hpp:444
PipelineMaker & scissor(const vk::Rect2D &value)
Definition: vku.hpp:764
bool ok() const
Returns true if the updater is error free.
Definition: vku.hpp:1106
This class is a specialisation of GenericBuffer for low performance vertex buffers on the host...
Definition: vku.hpp:969
A 2D texture image living on the GPU or a staging buffer visible to the CPU.
Definition: vku.hpp:1407
void image(vk::Sampler sampler, vk::ImageView imageView, vk::ImageLayout imageLayout)
Call this to add a combined image sampler.
Definition: vku.hpp:1042
void vertexBinding(const vk::VertexInputBindingDescription &desc)
Definition: vku.hpp:742
void updateLocal(const vk::Device &device, const void *value, vk::DeviceSize size) const
For a host buffer, copy memory to the buffer object.
Definition: vku.hpp:888
void copy(vk::CommandBuffer cb, vku::GenericImage &srcImage)
Copy another image to this one. This also changes the layout.
Definition: vku.hpp:1246
void copy(vk::DescriptorSet srcSet, uint32_t srcBinding, uint32_t srcArrayElement, vk::DescriptorSet dstSet, uint32_t dstBinding, uint32_t dstArrayElement, uint32_t descriptorCount)
Copy an existing descriptor.
Definition: vku.hpp:1096
Class for building shader modules and extracting metadata from shaders.
Definition: vku.hpp:404
std::vector< Variable > getVariables() const
Definition: vku.hpp:469
vk::UniquePipelineLayout createUnique(const vk::Device &device) const
Create a self-deleting pipeline layout object.
Definition: vku.hpp:557
void blendColorBlendOp(vk::BlendOp value)
Blend operation (called after blendBegin())
Definition: vku.hpp:708
vk::Format GLtoVKFormat(uint32_t glFormat)
KTX files use OpenGL format values. This converts some common ones to Vulkan equivalents.
Definition: vku.hpp:1590
ShaderModule(const vk::Device &device, InIter begin, InIter end)
Construct a shader module from a memory.
Definition: vku.hpp:433
void setLayout(vk::CommandBuffer cb, vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask=vk::ImageAspectFlagBits::eColor)
Change the layout of this image using a memory barrier.
Definition: vku.hpp:1295
ComputePipelineMaker & module(const vk::PipelineShaderStageCreateInfo &value)
Set the compute shader module.
Definition: vku.hpp:843
void buffer(vk::Buffer buffer, vk::DeviceSize offset, vk::DeviceSize range)
Call this to add a new buffer.
Definition: vku.hpp:1064
PipelineMaker & depthStencilState(const vk::PipelineDepthStencilStateCreateInfo &value)
Definition: vku.hpp:793
An image to use as a depth buffer on a renderpass.
Definition: vku.hpp:1460
This class is a specialisation of GenericBuffer for low performance vertex buffers in CPU memory...
Definition: vku.hpp:992
A cube map texture image living on the GPU or a staging buffer visible to the CPU.
Definition: vku.hpp:1433
Vookoo high level C++ Vulkan interface.
Definition: vku.hpp:34