Changeset b794178 in opengl-game for vulkan-utils.cpp
- Timestamp:
- Oct 17, 2019, 9:30:18 PM (5 years ago)
- Branches:
- feature/imgui-sdl, master, points-test
- Children:
- e83b155
- Parents:
- 771b33a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vulkan-utils.cpp
r771b33a rb794178 4 4 #include <set> 5 5 #include <stdexcept> 6 #include <string> 6 7 #define STB_IMAGE_IMPLEMENTATION 8 #include "stb_image.h" // TODO: Probably switch to SDL_image 9 10 // TODO: Remove all instances of auto 7 11 8 12 bool VulkanUtils::checkValidationLayerSupport(const vector<const char*> &validationLayers) { … … 210 214 throw runtime_error("failed to find supported format!"); 211 215 } 216 217 void VulkanUtils::createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, 218 VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) { 219 VkBufferCreateInfo bufferInfo = {}; 220 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 221 bufferInfo.size = size; 222 bufferInfo.usage = usage; 223 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 224 225 if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { 226 throw runtime_error("failed to create buffer!"); 227 } 228 229 VkMemoryRequirements memRequirements; 230 vkGetBufferMemoryRequirements(device, buffer, &memRequirements); 231 232 VkMemoryAllocateInfo allocInfo = {}; 233 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 234 allocInfo.allocationSize = memRequirements.size; 235 allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties); 236 237 if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) { 238 throw runtime_error("failed to allocate buffer memory!"); 239 } 240 241 vkBindBufferMemory(device, buffer, bufferMemory, 0); 242 } 243 244 uint32_t VulkanUtils::findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties) { 245 VkPhysicalDeviceMemoryProperties memProperties; 246 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); 247 248 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { 249 if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { 250 return i; 251 } 252 } 253 254 throw runtime_error("failed to find suitable memory type!"); 255 } 256 257 void VulkanUtils::createVulkanImageFromFile(VkDevice device, VkPhysicalDevice physicalDevice, 258 VkCommandPool commandPool, string filename, VulkanImage& image, VkQueue graphicsQueue) { 259 int texWidth, texHeight, texChannels; 260 261 stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); 262 VkDeviceSize imageSize = texWidth * texHeight * 4; 263 264 if (!pixels) { 265 throw runtime_error("failed to load texture image!"); 266 } 267 268 VkBuffer stagingBuffer; 269 VkDeviceMemory stagingBufferMemory; 270 271 createBuffer(device, physicalDevice, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 272 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 273 stagingBuffer, stagingBufferMemory); 274 275 void* data; 276 277 vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data); 278 memcpy(data, pixels, static_cast<size_t>(imageSize)); 279 vkUnmapMemory(device, stagingBufferMemory); 280 281 stbi_image_free(pixels); 282 283 createImage(device, physicalDevice, texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, 284 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image); 285 286 transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM, 287 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, graphicsQueue); 288 copyBufferToImage(device, commandPool, stagingBuffer, image.image, 289 static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight), graphicsQueue); 290 transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM, 291 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, graphicsQueue); 292 293 vkDestroyBuffer(device, stagingBuffer, nullptr); 294 vkFreeMemory(device, stagingBufferMemory, nullptr); 295 296 image.imageView = createImageView(device, image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); 297 } 298 299 void VulkanUtils::createVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice, 300 SDL_Texture* texture, VulkanImage& image) { 301 int a, w, h; 302 303 // I only need this here for the width and height, which are constants, so just use those instead 304 SDL_QueryTexture(texture, nullptr, &a, &w, &h); 305 306 createImage(device, physicalDevice, w, h, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, 307 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image); 308 309 image.imageView = createImageView(device, image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); 310 } 311 312 void VulkanUtils::createImage(VkDevice device, VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height, 313 VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, 314 VulkanImage& image) { 315 VkImageCreateInfo imageInfo = {}; 316 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 317 imageInfo.imageType = VK_IMAGE_TYPE_2D; 318 imageInfo.extent.width = width; 319 imageInfo.extent.height = height; 320 imageInfo.extent.depth = 1; 321 imageInfo.mipLevels = 1; 322 imageInfo.arrayLayers = 1; 323 imageInfo.format = format; 324 imageInfo.tiling = tiling; 325 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 326 imageInfo.usage = usage; 327 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; 328 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 329 330 if (vkCreateImage(device, &imageInfo, nullptr, &image.image) != VK_SUCCESS) { 331 throw runtime_error("failed to create image!"); 332 } 333 334 VkMemoryRequirements memRequirements; 335 vkGetImageMemoryRequirements(device, image.image, &memRequirements); 336 337 VkMemoryAllocateInfo allocInfo = {}; 338 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 339 allocInfo.allocationSize = memRequirements.size; 340 allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties); 341 342 if (vkAllocateMemory(device, &allocInfo, nullptr, &image.imageMemory) != VK_SUCCESS) { 343 throw runtime_error("failed to allocate image memory!"); 344 } 345 346 vkBindImageMemory(device, image.image, image.imageMemory, 0); 347 } 348 349 void VulkanUtils::transitionImageLayout(VkDevice device, VkCommandPool commandPool, VkImage image, 350 VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkQueue graphicsQueue) { 351 VkCommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool); 352 353 VkImageMemoryBarrier barrier = {}; 354 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 355 barrier.oldLayout = oldLayout; 356 barrier.newLayout = newLayout; 357 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 358 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 359 barrier.image = image; 360 361 if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { 362 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 363 364 if (hasStencilComponent(format)) { 365 barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; 366 } 367 } else { 368 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 369 } 370 371 barrier.subresourceRange.baseMipLevel = 0; 372 barrier.subresourceRange.levelCount = 1; 373 barrier.subresourceRange.baseArrayLayer = 0; 374 barrier.subresourceRange.layerCount = 1; 375 376 VkPipelineStageFlags sourceStage; 377 VkPipelineStageFlags destinationStage; 378 379 if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { 380 barrier.srcAccessMask = 0; 381 barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 382 383 sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 384 destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 385 } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { 386 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 387 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 388 389 sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 390 destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 391 } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { 392 barrier.srcAccessMask = 0; 393 barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 394 395 sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 396 destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; 397 } else { 398 throw invalid_argument("unsupported layout transition!"); 399 } 400 401 vkCmdPipelineBarrier( 402 commandBuffer, 403 sourceStage, destinationStage, 404 0, 405 0, nullptr, 406 0, nullptr, 407 1, &barrier 408 ); 409 410 endSingleTimeCommands(device, commandPool, commandBuffer, graphicsQueue); 411 } 412 413 VkCommandBuffer VulkanUtils::beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool) { 414 VkCommandBufferAllocateInfo allocInfo = {}; 415 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 416 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 417 allocInfo.commandPool = commandPool; 418 allocInfo.commandBufferCount = 1; 419 420 VkCommandBuffer commandBuffer; 421 vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer); 422 423 VkCommandBufferBeginInfo beginInfo = {}; 424 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 425 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 426 427 vkBeginCommandBuffer(commandBuffer, &beginInfo); 428 429 return commandBuffer; 430 } 431 432 void VulkanUtils::endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, 433 VkCommandBuffer commandBuffer, VkQueue graphicsQueue) { 434 vkEndCommandBuffer(commandBuffer); 435 436 VkSubmitInfo submitInfo = {}; 437 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 438 submitInfo.commandBufferCount = 1; 439 submitInfo.pCommandBuffers = &commandBuffer; 440 441 vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); 442 vkQueueWaitIdle(graphicsQueue); 443 444 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 445 } 446 447 void VulkanUtils::copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkBuffer buffer, 448 VkImage image, uint32_t width, uint32_t height, VkQueue graphicsQueue) { 449 VkCommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool); 450 451 VkBufferImageCopy region = {}; 452 region.bufferOffset = 0; 453 region.bufferRowLength = 0; 454 region.bufferImageHeight = 0; 455 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 456 region.imageSubresource.mipLevel = 0; 457 region.imageSubresource.baseArrayLayer = 0; 458 region.imageSubresource.layerCount = 1; 459 region.imageOffset = { 0, 0, 0 }; 460 region.imageExtent = { width, height, 1 }; 461 462 vkCmdCopyBufferToImage( 463 commandBuffer, 464 buffer, 465 image, 466 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 467 1, 468 ®ion 469 ); 470 471 endSingleTimeCommands(device, commandPool, commandBuffer, graphicsQueue); 472 } 473 474 bool VulkanUtils::hasStencilComponent(VkFormat format) { 475 return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; 476 }
Note:
See TracChangeset
for help on using the changeset viewer.