FCT
载入中...
搜索中...
未找到
VK_Context.cpp
浏览该文件的文档.
1//
2// Created by Administrator on 2025/3/1.
3//
4
5#include "../FCTAPI.h"
6#include "./VK_Device.h"
7VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
8namespace FCT
9{
10
11
12
13 /*Material *VK_Context::createMaterial(VertexShader *vertexShader, PixelShader *pixelShader) {
14 return nullptr;
15 }*/
16
21
23 {
24 if (m_device) {
25 m_device.freeCommandBuffers(m_commandPool, m_commandBuffers);
26 m_device.destroyCommandPool(m_commandPool);
28 m_device.destroyCommandPool(m_transferCommandPool);
29 }
30 m_device.destroy();
31 }
32 }
33
34 VK_Context::VK_Context(VK_ContextCommon *common) : Context(common->runtime()) {
35 m_resourceDevice = new VK_Device(this);
36 m_common = common;
38 auto queueFamily = m_phyDevice.getQueueFamilyProperties();
39
40 m_transferQueueFamilyIndex = UINT32_MAX;
41 for (size_t i = 0; i < queueFamily.size(); ++i) {
42 if (queueFamily[i].queueFlags & vk::QueueFlagBits::eGraphics) {
44 }
45
46 if (queueFamily[i].queueFlags & vk::QueueFlagBits::eTransfer) {
47 if (!(queueFamily[i].queueFlags & vk::QueueFlagBits::eGraphics) &&
48 !(queueFamily[i].queueFlags & vk::QueueFlagBits::eCompute)) {
50 }
51 else if (m_transferQueueFamilyIndex == UINT32_MAX) {
53 }
54 }
55 }
56
57 if (m_transferQueueFamilyIndex == UINT32_MAX) {
59 }
60
61 std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
62 std::set<uint32_t> uniqueQueueFamilies = {m_graphicsQueueFamilyIndex, m_transferQueueFamilyIndex};
63
64 float queuePriority = 1.0f;
65 for (uint32_t queueFamily : uniqueQueueFamilies) {
66 vk::DeviceQueueCreateInfo queueCreateInfo;
67 queueCreateInfo.setQueueFamilyIndex(queueFamily)
68 .setQueueCount(1)
69 .setPQueuePriorities(&queuePriority);
70 queueCreateInfos.push_back(queueCreateInfo);
71 }
72
73 std::vector<const char*> deviceExtensions = {
74 VK_KHR_SWAPCHAIN_EXTENSION_NAME
75 };
76 vk::PhysicalDeviceFeatures deviceFeatures;
77 deviceFeatures.setSamplerAnisotropy(true);
78
79 vk::DeviceCreateInfo deviceCreateInfo;
80 deviceCreateInfo.setQueueCreateInfos(queueCreateInfos)
81 .setPEnabledExtensionNames(deviceExtensions)
82 .setPEnabledFeatures(&deviceFeatures);
83
84 m_device = m_phyDevice.createDevice(deviceCreateInfo);
85 VULKAN_HPP_DEFAULT_DISPATCHER.init(m_device);
86
89
92 }
97 vk::CommandPoolCreateInfo poolInfo;
98 poolInfo.setQueueFamilyIndex(m_transferQueueFamilyIndex)
99 .setFlags(vk::CommandPoolCreateFlagBits::eTransient |
100 vk::CommandPoolCreateFlagBits::eResetCommandBuffer);
101
102 m_transferCommandPool = m_device.createCommandPool(poolInfo);
103 }
105 vk::CommandBufferAllocateInfo allocInfo;
106 allocInfo.setLevel(vk::CommandBufferLevel::ePrimary);
107 allocInfo.setCommandPool(m_transferCommandPool);
108 allocInfo.setCommandBufferCount(1);
109
110 vk::CommandBuffer commandBuffer = m_device.allocateCommandBuffers(allocInfo)[0];
111
112 vk::CommandBufferBeginInfo beginInfo;
113 beginInfo.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
114 commandBuffer.begin(beginInfo);
115
116 return commandBuffer;
117 }
118
119 void VK_Context::endSingleTimeTransferCommands(vk::CommandBuffer commandBuffer, vk::Fence* outFence) {
120 commandBuffer.end();
121
122 vk::FenceCreateInfo fenceInfo;
123 vk::Fence fence = m_device.createFence(fenceInfo);
124
125 vk::SubmitInfo submitInfo;
126 submitInfo.setCommandBufferCount(1);
127 submitInfo.setPCommandBuffers(&commandBuffer);
128
129 m_transferQueue.submit(1, &submitInfo, fence);
130
131 if (outFence) {
132 *outFence = fence;
133 } else {
134 m_device.waitForFences(1, &fence, VK_TRUE, UINT64_MAX);
135 m_device.destroyFence(fence);
136 m_device.freeCommandBuffers(m_transferCommandPool, 1, &commandBuffer);
137 }
138
139 }
140
142 {
143 vk::CommandBufferAllocateInfo allocInfo;
144 allocInfo.setLevel(vk::CommandBufferLevel::ePrimary);
145 allocInfo.setCommandPool(m_commandPool);
146 allocInfo.setCommandBufferCount(1);
147
148 vk::CommandBuffer commandBuffer = m_device.allocateCommandBuffers(allocInfo)[0];
149
150 vk::CommandBufferBeginInfo beginInfo;
151 beginInfo.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
152 commandBuffer.begin(beginInfo);
153
154 return commandBuffer;
155 }
156
157 void VK_Context::endSingleTimeCommands(vk::CommandBuffer commandBuffer)
158 {
159 commandBuffer.end();
160
161 vk::FenceCreateInfo fenceInfo;
162 vk::Fence fence = m_device.createFence(fenceInfo);
163
164 vk::SubmitInfo submitInfo;
165 submitInfo.setCommandBufferCount(1);
166 submitInfo.setPCommandBuffers(&commandBuffer);
167
168 m_graphicsQueue.submit(1, &submitInfo, fence);
169 m_device.waitForFences(1, &fence, VK_TRUE, UINT64_MAX);
170 m_device.destroyFence(fence);
171
172 m_device.freeCommandBuffers(m_commandPool, 1, &commandBuffer);
173 }
174
175
177 vk::CommandPoolCreateInfo poolInfo;
178 poolInfo.setQueueFamilyIndex(m_graphicsQueueFamilyIndex)
179 .setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer);
180
181 m_commandPool = m_device.createCommandPool(poolInfo);
182/*
183 vk::CommandBufferAllocateInfo allocInfo;
184 allocInfo.setCommandPool(m_commandPool)
185 .setLevel(vk::CommandBufferLevel::ePrimary)
186 .setCommandBufferCount(1);
187
188 m_commandBuffers = m_device.allocateCommandBuffers(allocInfo);*/
189 }
190
191 /* void VK_Context::create(IRenderTarget *target) {
192 //target->bind(this);
193 }*/
194
195 void VK_Context::transferDataToBuffer(vk::Buffer dstBuffer, size_t size, const void* data)
196 {
197 vk::BufferCreateInfo stagingBufferInfo;
198 stagingBufferInfo.setSize(size);
199 stagingBufferInfo.setUsage(vk::BufferUsageFlagBits::eTransferSrc);
200 stagingBufferInfo.setSharingMode(vk::SharingMode::eExclusive);
201
202 vk::Buffer stagingBuffer;
203 vk::DeviceMemory stagingMemory;
204
205 try {
206 stagingBuffer = m_device.createBuffer(stagingBufferInfo);
207
208 vk::MemoryRequirements memRequirements = m_device.getBufferMemoryRequirements(stagingBuffer);
209
210 vk::MemoryAllocateInfo allocInfo;
211 allocInfo.setAllocationSize(memRequirements.size);
212 allocInfo.setMemoryTypeIndex(findMemoryType(
213 memRequirements.memoryTypeBits,
214 vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
215
216 stagingMemory = m_device.allocateMemory(allocInfo);
217 m_device.bindBufferMemory(stagingBuffer, stagingMemory, 0);
218
219 void* mappedData = m_device.mapMemory(stagingMemory, 0, size);
220 memcpy(mappedData, data, size);
221 m_device.unmapMemory(stagingMemory);
222
223 vk::CommandBuffer cmdBuffer = beginSingleTimeCommands();
224
225 vk::BufferCopy copyRegion;
226 copyRegion.setSrcOffset(0);
227 copyRegion.setDstOffset(0);
228 copyRegion.setSize(size);
229 cmdBuffer.copyBuffer(stagingBuffer, dstBuffer, 1, &copyRegion);
230
231 endSingleTimeCommands(cmdBuffer);
232
233 m_device.destroyBuffer(stagingBuffer);
234 m_device.freeMemory(stagingMemory);
235 }
236 catch (const std::exception& e) {
237 ferr << "Failed to transfer data to buffer: " << e.what() << std::endl;
238
239 if (stagingBuffer) {
240 m_device.destroyBuffer(stagingBuffer);
241 }
242
243 if (stagingMemory) {
244 m_device.freeMemory(stagingMemory);
245 }
246
247 throw;
248 }
249 }
250 void VK_Context::transferDataToImage(vk::Image dstImage, uint32_t width, uint32_t height,
251 vk::Format format, const void* data, size_t dataSize, vk::Fence* outFence, std::function<void()>* cleanUpCallback)
252 {
253 transferDataToImage(dstImage, width, height, 1, format, 1, 1,
254 vk::ImageAspectFlagBits::eColor, data, dataSize, outFence, cleanUpCallback);
255 }
256
257 void VK_Context::transferDataToImage(vk::Image dstImage, uint32_t width, uint32_t height, uint32_t depth,
258 vk::Format format, uint32_t mipLevels, uint32_t arrayLayers,
259 vk::ImageAspectFlags aspectMask, const void* data, size_t dataSize,
260 vk::Fence* outFence, std::function<void()>* cleanUpCallback)
261 {
262 size_t pixelSize = FormatSize(FromVkFormat(format));
263 size_t fullImageSize = width * height * depth * pixelSize;
264 vk::BufferCreateInfo stagingBufferInfo;
265 stagingBufferInfo.setSize(fullImageSize);
266 stagingBufferInfo.setUsage(vk::BufferUsageFlagBits::eTransferSrc);
267 stagingBufferInfo.setSharingMode(vk::SharingMode::eExclusive);
268
269 vk::Buffer stagingBuffer;
270 vk::DeviceMemory stagingMemory;
271
272 try {
273 stagingBuffer = m_device.createBuffer(stagingBufferInfo);
274
275 vk::MemoryRequirements memRequirements = m_device.getBufferMemoryRequirements(stagingBuffer);
276
277 vk::MemoryAllocateInfo allocInfo;
278 allocInfo.setAllocationSize(memRequirements.size);
279 allocInfo.setMemoryTypeIndex(findMemoryType(
280 memRequirements.memoryTypeBits,
281 vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
282
283 stagingMemory = m_device.allocateMemory(allocInfo);
284 m_device.bindBufferMemory(stagingBuffer, stagingMemory, 0);
285
286 void* mappedData = m_device.mapMemory(stagingMemory, 0, dataSize);
287 memcpy(mappedData, data, dataSize);
288 m_device.unmapMemory(stagingMemory);
289 vk::CommandBuffer cmdBuffer = beginSingleTimeTransferCommands();
290
291 bool needsQueueTransfer = m_graphicsQueueFamilyIndex != m_transferQueueFamilyIndex;
292
293 vk::ImageLayout finalLayout;
294 vk::AccessFlags finalAccessMask;
295
296 if (aspectMask & vk::ImageAspectFlagBits::eDepth || aspectMask & vk::ImageAspectFlagBits::eStencil) {
297 finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
298 finalAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
299 } else {
300 finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
301 finalAccessMask = vk::AccessFlagBits::eShaderRead;
302 }
303
304 vk::ImageMemoryBarrier barrier;
305 barrier.setOldLayout(vk::ImageLayout::eUndefined);
306 barrier.setNewLayout(vk::ImageLayout::eTransferDstOptimal);
307
308 if (needsQueueTransfer) {
309 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
310 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
311 } else {
312 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
313 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
314 }
315
316 barrier.setImage(dstImage);
317 barrier.setSubresourceRange(vk::ImageSubresourceRange(
318 aspectMask, 0, mipLevels, 0, arrayLayers));
319 barrier.setSrcAccessMask(vk::AccessFlagBits::eNone);
320 barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite);
321
322 cmdBuffer.pipelineBarrier(
323 vk::PipelineStageFlagBits::eTopOfPipe,
324 vk::PipelineStageFlagBits::eTransfer,
325 vk::DependencyFlags(),
326 0, nullptr,
327 0, nullptr,
328 1, &barrier);
329
330 vk::BufferImageCopy region;
331 region.setBufferOffset(0);
332 region.setBufferRowLength(0);
333 region.setBufferImageHeight(0);
334 region.setImageSubresource(vk::ImageSubresourceLayers(
335 aspectMask, 0, 0, arrayLayers));
336 region.setImageOffset(vk::Offset3D(0, 0, 0));
337 region.setImageExtent(vk::Extent3D(width, height, depth));
338
339 cmdBuffer.copyBufferToImage(
340 stagingBuffer,
341 dstImage,
342 vk::ImageLayout::eTransferDstOptimal,
343 1, &region);
344
345 barrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
346
347 if (needsQueueTransfer) {
348 barrier.setNewLayout(vk::ImageLayout::eTransferDstOptimal);
349 barrier.setSrcQueueFamilyIndex(m_transferQueueFamilyIndex);
350 barrier.setDstQueueFamilyIndex(m_graphicsQueueFamilyIndex);
351 barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
352 barrier.setDstAccessMask(vk::AccessFlagBits::eShaderRead);
353 } else {
354 barrier.setNewLayout(finalLayout);
355 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
356 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
357 barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
358 barrier.setDstAccessMask(finalAccessMask);
359 }
360
361 cmdBuffer.pipelineBarrier(
362 vk::PipelineStageFlagBits::eTransfer,
363 vk::PipelineStageFlagBits::eTransfer,
364 vk::DependencyFlags(),
365 0, nullptr,
366 0, nullptr,
367 1, &barrier);
368
369 if (outFence) {
370 vk::Fence fence;
371 endSingleTimeTransferCommands(cmdBuffer, &fence);
372
373 if (cleanUpCallback) {
374 vk::Buffer capturedBuffer = stagingBuffer;
375 vk::DeviceMemory capturedMemory = stagingMemory;
376 vk::Image capturedImage = dstImage;
377 bool capturedNeedsQueueTransfer = needsQueueTransfer;
378 vk::ImageAspectFlags capturedAspectMask = aspectMask;
379 uint32_t capturedMipLevels = mipLevels;
380 uint32_t capturedArrayLayers = arrayLayers;
381 vk::ImageLayout capturedFinalLayout = finalLayout;
382 vk::AccessFlags capturedFinalAccessMask = finalAccessMask;
383 vk::Fence capturedFence = fence;
384 vk::CommandBuffer capturedCmdBuffer = cmdBuffer;
385
386 *cleanUpCallback = [this, capturedBuffer, capturedMemory, capturedImage,
387 capturedNeedsQueueTransfer, capturedAspectMask,
388 capturedMipLevels, capturedArrayLayers,
389 capturedFinalLayout, capturedFinalAccessMask,
390 capturedFence,capturedCmdBuffer]() {
391 m_device.waitForFences(1, &capturedFence, VK_TRUE, UINT64_MAX);
392 m_device.destroyFence(capturedFence);
393 postLogicTask([this,capturedCmdBuffer]()
394 {
395 m_device.freeCommandBuffers(m_transferCommandPool, 1, &capturedCmdBuffer);
396 });
397 if (capturedNeedsQueueTransfer) {
398 vk::CommandBuffer graphicsCmdBuffer = beginSingleTimeCommands();
399
400 vk::ImageMemoryBarrier finalBarrier;
401 finalBarrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
402 finalBarrier.setNewLayout(capturedFinalLayout);
403 finalBarrier.setSrcQueueFamilyIndex(m_transferQueueFamilyIndex);
404 finalBarrier.setDstQueueFamilyIndex(m_graphicsQueueFamilyIndex);
405 finalBarrier.setImage(capturedImage);
406 finalBarrier.setSubresourceRange(vk::ImageSubresourceRange(
407 capturedAspectMask, 0, capturedMipLevels, 0, capturedArrayLayers));
408 finalBarrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
409 finalBarrier.setDstAccessMask(capturedFinalAccessMask);
410
411 vk::PipelineStageFlags finalStage;
412 if (capturedAspectMask & vk::ImageAspectFlagBits::eDepth ||
413 capturedAspectMask & vk::ImageAspectFlagBits::eStencil) {
414 finalStage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
415 } else {
416 finalStage = vk::PipelineStageFlagBits::eAllCommands;
417 }
418
419 graphicsCmdBuffer.pipelineBarrier(
420 vk::PipelineStageFlagBits::eAllCommands,
421 finalStage,
422 vk::DependencyFlags(),
423 0, nullptr,
424 0, nullptr,
425 1, &finalBarrier);
426
427 endSingleTimeCommands(graphicsCmdBuffer);
428 }
429
430 if (capturedBuffer) {
431 m_device.destroyBuffer(capturedBuffer);
432 }
433 if (capturedMemory) {
434 m_device.freeMemory(capturedMemory);
435 }
436 };
437
438 if (outFence) {
439 *outFence = fence;
440 }
441 } else {
442 ferr << "callback is nullptr, resource is leaked in transferDataToImage" << std::endl;
443 }
444 } else {
445 endSingleTimeTransferCommands(cmdBuffer, nullptr);
446
447 if (needsQueueTransfer) {
448 vk::CommandBuffer graphicsCmdBuffer = beginSingleTimeCommands();
449
450 vk::ImageMemoryBarrier finalBarrier;
451 finalBarrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
452 finalBarrier.setNewLayout(finalLayout);
453 finalBarrier.setSrcQueueFamilyIndex(m_transferQueueFamilyIndex);
454 finalBarrier.setDstQueueFamilyIndex(m_graphicsQueueFamilyIndex);
455 finalBarrier.setImage(dstImage);
456 finalBarrier.setSubresourceRange(vk::ImageSubresourceRange(
457 aspectMask, 0, mipLevels, 0, arrayLayers));
458 finalBarrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
459 finalBarrier.setDstAccessMask(finalAccessMask);
460
461 vk::PipelineStageFlags finalStage;
462 if (aspectMask & vk::ImageAspectFlagBits::eDepth ||
463 aspectMask & vk::ImageAspectFlagBits::eStencil) {
464 finalStage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
465 } else {
466 finalStage = vk::PipelineStageFlagBits::eAllCommands;
467 }
468
469 graphicsCmdBuffer.pipelineBarrier(
470 vk::PipelineStageFlagBits::eAllCommands,
471 finalStage,
472 vk::DependencyFlags(),
473 0, nullptr,
474 0, nullptr,
475 1, &finalBarrier);
476
477 endSingleTimeCommands(graphicsCmdBuffer);
478 }
479
480 m_device.destroyBuffer(stagingBuffer);
481 m_device.freeMemory(stagingMemory);
482 }
483 }
484 catch (const std::exception& e) {
485 ferr << "Failed to transfer data to image: " << e.what() << std::endl;
486
487 if (stagingBuffer) {
488 m_device.destroyBuffer(stagingBuffer);
489 }
490
491 if (stagingMemory) {
492 m_device.freeMemory(stagingMemory);
493 }
494
495 throw;
496 }
497 }
498
500 {
501
502 }
503
504 uint32_t VK_Context::findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties)
505 {
506 vk::PhysicalDeviceMemoryProperties memProperties = getPhysicalDevice().getMemoryProperties();
507
508 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
509 if ((typeFilter & (1 << i)) &&
510 (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
511 return i;
512 }
513 }
514 }
515
517 return m_common->getInstance();
518 }
519
521 vk::CommandBufferBeginInfo beginInfo;
522 beginInfo.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
523
524 m_commandBuffers[index].begin(beginInfo);
525 }
526
528 m_commandBuffers[index].end();
529 }
531 vk::SubmitInfo submitInfo;
532 submitInfo.setCommandBuffers(m_commandBuffers[0]);
533
534 m_graphicsQueue.submit(submitInfo);
535 m_graphicsQueue.waitIdle();
536 }
537}
void postLogicTask(const std::function< void()> &task)
Device * m_resourceDevice
Context(Runtime *runtime)
RHI::RasterizationPipeline * createTraditionPipeline() override
void createPlatform() override
vk::PhysicalDevice m_phyDevice
uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties)
vk::Queue m_graphicsQueue
uint32_t getGraphicsQueueFamily() const
VK_Context(VK_ContextCommon *common)
vk::Instance getVkInstance()
void transferDataToBuffer(vk::Buffer dstBuffer, size_t size, const void *data)
void endCommandBuffer(int index)
VK_ContextCommon * m_common
uint32_t m_transferQueueFamilyIndex
void beginCommandBuffer(int index)
void endSingleTimeTransferCommands(vk::CommandBuffer commandBuffer, vk::Fence *outFence)
vk::Queue m_transferQueue
std::vector< vk::CommandBuffer > m_commandBuffers
void transferDataToImage(vk::Image dstImage, uint32_t width, uint32_t height, vk::Format format, const void *data, size_t dataSize, vk::Fence *outFence=nullptr, std::function< void()> *cleanUpCallback=nullptr)
void endSingleTimeCommands(vk::CommandBuffer commandBuffer)
uint32_t m_graphicsQueueFamilyIndex
vk::CommandBuffer beginSingleTimeCommands()
vk::CommandBuffer beginSingleTimeTransferCommands()
vk::CommandPool m_commandPool
auto getPhysicalDevice() const
vk::CommandPool m_transferCommandPool
std::ostream & ferr
Format FromVkFormat(vk::Format format)
constexpr size_t FormatSize(Format format) noexcept