Q> 마우스로 컬러픽커 기능을 하는 함수 만들기
대략 알고리즘
1) stagingBuffer, stagingBufferMemory 생성
2) 커멘드 버퍼 할당, 레코딩 시작
3) pipelineBarrier로 swapchainImage의 레이아웃 transpose_bit으로 바꾸기
4) 커멘드 버퍼를 그래픽스 큐에 제출
5) 레코딩 시작
6) swapchain에서 stagingBufferMemory로 카피
7) 커멘드 버퍼를 그래픽스 큐에 제출
8) 커멘드 버퍼 할당 해제
9) staging 맵핑
10) memcpy로 이미지 데이터를 void* data에 가져옴
11) 마우스 포지션을 얻어와서 data에서 해당 위치를 검색하면 끝
졸작으로 만드는 중인데 진짜 너무 어렵다 머리 다 빠질 것 같음 ㅅㅂ..
요즘 VULKAN 글 많이 보이던데 진짜 대단한 사람인것 같다
void getImageData(VkImage src, VkDeviceSize imageSize) {
// 스테깅 버퍼, 스테깅 버퍼 메모리 생성
// 커맨드 버퍼 할당
// 커맨드 버퍼 비긴 인포
// Image2Buffer
// memcpy
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
VkBufferCreateInfo bufferCreateInfo{};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.pNext = NULL;
bufferCreateInfo.flags = 0;
bufferCreateInfo.size = imageSize;
// Image에서 값을 받아온다.
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer) != VK_SUCCESS) {
throw std::runtime_error("staging Buffer 생성 오류");
}
VkMemoryRequirements memReq;
vkGetBufferMemoryRequirements(device, stagingBuffer, &memReq);
VkPhysicalDeviceMemoryProperties memProp;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProp);
int memoryTypeIdx = -1;
for (int i = 0; i < memProp.memoryTypeCount; i++) {
if (memReq.memoryTypeBits & (1 << i) && memProp.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
memoryTypeIdx = i;
break;
}
}
if (memoryTypeIdx == -1)
throw std::runtime_error("stagingBuffer가 요구하는 메모리 유형을 찾을 수 없음.");
VkMemoryAllocateInfo memAllocInfo{};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memReq.size;
memAllocInfo.memoryTypeIndex = memoryTypeIdx;
std::cout << memReq.size << std::endl;
if (vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingBufferMemory) != VK_SUCCESS) {
throw std::runtime_error("stagingBufferMemory생성 오류");
}
vkBindBufferMemory(device, stagingBuffer, stagingBufferMemory, 0);
VkCommandBuffer recordBuffer;
VkCommandBufferAllocateInfo cmdbufAllocInfo{};
cmdbufAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdbufAllocInfo.pNext = nullptr;
cmdbufAllocInfo.commandPool = commandPool;
cmdbufAllocInfo.commandBufferCount = 1;
cmdbufAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
if (vkAllocateCommandBuffers(device, &cmdbufAllocInfo, &recordBuffer) != VK_SUCCESS) {
throw std::runtime_error("command buffer 생성 실패.");
}
VkCommandBufferBeginInfo cmdbufBeginInfo{};
cmdbufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdbufBeginInfo.pNext = nullptr;
cmdbufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
cmdbufBeginInfo.pInheritanceInfo = nullptr;
vkBeginCommandBuffer(recordBuffer, &cmdbufBeginInfo);
VkImageMemoryBarrier imageMemBarrier{};
imageMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemBarrier.pNext = nullptr;
imageMemBarrier.image = src;
imageMemBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageMemBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
imageMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageMemBarrier.subresourceRange.baseArrayLayer = 0;
imageMemBarrier.subresourceRange.baseMipLevel = 0;
imageMemBarrier.subresourceRange.layerCount = 1;
imageMemBarrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier( recordBuffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemBarrier);
vkEndCommandBuffer(recordBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &recordBuffer;
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr) != VK_SUCCESS) {
throw std::runtime_error("commandBuffer를 제출하는데 실패.");
}
vkQueueWaitIdle(graphicsQueue);
VkCommandBufferBeginInfo cmdbufBeginInfo{};
cmdbufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdbufBeginInfo.pNext = nullptr;
cmdbufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
cmdbufBeginInfo.pInheritanceInfo = nullptr;
vkBeginCommandBuffer(recordBuffer, &cmdbufBeginInfo);
VkBufferImageCopy bufferImageCopy{};
bufferImageCopy.bufferOffset = 0;
bufferImageCopy.bufferRowLength = 0;
bufferImageCopy.bufferImageHeight = 0;
bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bufferImageCopy.imageSubresource.mipLevel = 0;
bufferImageCopy.imageSubresource.baseArrayLayer = 0;
bufferImageCopy.imageSubresource.layerCount = 1;
bufferImageCopy.imageOffset = { 0,
0,
0};
bufferImageCopy.imageExtent = { static_cast<unsigned int>(swapChainExtent.width),
static_cast<unsigned int>(swapChainExtent.height),
1 };
vkCmdCopyImageToBuffer(recordBuffer, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, &bufferImageCopy);
vkEndCommandBuffer(recordBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &recordBuffer;
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr) != VK_SUCCESS) {
throw std::runtime_error("commandBuffer를 제출하는데 실패.");
}
vkQueueWaitIdle(graphicsQueue);
vkFreeCommandBuffers(device, commandPool, 1, &recordBuffer);
void* data;
vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);
memcpy(data, stagingBufferMemory, imageSize);
vkUnmapMemory(device, stagingBufferMemory);
vkFreeMemory(device, stagingBufferMemory, nullptr);
vkDestroyBuffer(device, stagingBuffer, nullptr);
std::cout << "픽셀 개수: " << sizeof(data) << std::endl;
}
세모 그리는 데 3000줄 필요? 대단하다! Vulkan!
응애시발 - dc App
소스량 개역겹네 여윽시 불칸
솔직히 말하면... DirectX11이나 써라 닝겐
그러기엔 너무 먼길을 왔음 ㅋㅋ
진지하게 토나오노
저거 근데 소스 다 외우는거임?? 아니면 알고리즘만 이해하고 중요한 부분만 기억한다던지 어떻게 공부하는겨
쌩 Vulkan을 짤 일은 거의 없다고 봐도 무방. ARM에서 만든 GPU 가이드라인 레포인데, 얘네도 Vulkan API 절대 쌩으로 안 씀.
https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers/tree/master/framework
NVIDIA에서 배포한 코드인데, 이거도 보면 쌩 Vulkan을 안 씀.
https://github.com/nvpro-samples/shared_sources
아래 대댓은 gpu 회사에 따라서 파이프라인이 전부 다르기에 어떤 부분은 생략 될 수도 있고 어떤 부분은 첨부될 수 도 있고 한데, 근데 그냥 베이스 벌컨 배워두면 둘다 쉽게 짤수 있어.
그리고 의외로 별로 외울만한 것들도 없다 어느정도 이론만 알면 쉽게 코딩이 가능해서 대충 3~4개월 이론 공부하면 충분히 짤만함 ㅋㅋ
공부 방법은 첫번째로 vulkan summary검색하면 나오는 이미지 3개 정도 외우고, 그 다음 디스크립터 인스턴스 프레임버퍼 같은 용어들 정의를 외우고 다른 사람이 만들어 놓은 코드를 집적 3번 이상 집적 카피해본다면 바로 외워짐