123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // Copyright (c) 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "gpu/vulkan/vulkan_command_buffer.h"
- #include "base/logging.h"
- #include "gpu/vulkan/vulkan_command_pool.h"
- #include "gpu/vulkan/vulkan_device_queue.h"
- #include "gpu/vulkan/vulkan_function_pointers.h"
- #include "gpu/vulkan/vulkan_util.h"
- namespace gpu {
- namespace {
- VkPipelineStageFlags GetPipelineStageFlags(
- const VulkanDeviceQueue* device_queue,
- const VkImageLayout layout) {
- switch (layout) {
- case VK_IMAGE_LAYOUT_UNDEFINED:
- return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- case VK_IMAGE_LAYOUT_GENERAL:
- return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- return VK_PIPELINE_STAGE_HOST_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_PIPELINE_STAGE_TRANSFER_BIT;
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
- VkPipelineStageFlags flags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
- VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
- if (device_queue->enabled_device_features().tessellationShader) {
- flags |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
- VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
- }
- if (device_queue->enabled_device_features().geometryShader) {
- flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
- }
- return flags;
- }
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- default:
- NOTREACHED() << "layout=" << layout;
- }
- return 0;
- }
- VkAccessFlags GetAccessMask(const VkImageLayout layout) {
- switch (layout) {
- case VK_IMAGE_LAYOUT_UNDEFINED:
- return 0;
- case VK_IMAGE_LAYOUT_GENERAL:
- LOG(WARNING) << "VK_IMAGE_LAYOUT_GENERAL is used.";
- return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT |
- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
- VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
- VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- return VK_ACCESS_HOST_WRITE_BIT;
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
- return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- return VK_ACCESS_TRANSFER_READ_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_ACCESS_TRANSFER_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return 0;
- default:
- NOTREACHED() << "layout=" << layout;
- }
- return 0;
- }
- } // namespace
- VulkanCommandBuffer::VulkanCommandBuffer(VulkanDeviceQueue* device_queue,
- VulkanCommandPool* command_pool,
- bool primary)
- : primary_(primary),
- device_queue_(device_queue),
- command_pool_(command_pool) {
- command_pool_->IncrementCommandBufferCount();
- }
- VulkanCommandBuffer::~VulkanCommandBuffer() {
- DCHECK(!submission_fence_.is_valid());
- DCHECK_EQ(static_cast<VkCommandBuffer>(VK_NULL_HANDLE), command_buffer_);
- DCHECK(!recording_);
- command_pool_->DecrementCommandBufferCount();
- }
- bool VulkanCommandBuffer::Initialize() {
- VkResult result = VK_SUCCESS;
- VkDevice device = device_queue_->GetVulkanDevice();
- VkCommandBufferAllocateInfo command_buffer_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .pNext = nullptr,
- .commandPool = command_pool_->handle(),
- .level = primary_ ? VK_COMMAND_BUFFER_LEVEL_PRIMARY
- : VK_COMMAND_BUFFER_LEVEL_SECONDARY,
- .commandBufferCount = 1,
- };
- DCHECK_EQ(static_cast<VkCommandBuffer>(VK_NULL_HANDLE), command_buffer_);
- result =
- vkAllocateCommandBuffers(device, &command_buffer_info, &command_buffer_);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkAllocateCommandBuffers() failed: " << result;
- return false;
- }
- record_type_ = RECORD_TYPE_EMPTY;
- return true;
- }
- void VulkanCommandBuffer::Destroy() {
- VkDevice device = device_queue_->GetVulkanDevice();
- if (submission_fence_.is_valid()) {
- DCHECK(device_queue_->GetFenceHelper()->HasPassed(submission_fence_));
- submission_fence_ = VulkanFenceHelper::FenceHandle();
- }
- if (VK_NULL_HANDLE != command_buffer_) {
- vkFreeCommandBuffers(device, command_pool_->handle(), 1, &command_buffer_);
- command_buffer_ = VK_NULL_HANDLE;
- }
- }
- bool VulkanCommandBuffer::Submit(uint32_t num_wait_semaphores,
- VkSemaphore* wait_semaphores,
- uint32_t num_signal_semaphores,
- VkSemaphore* signal_semaphores) {
- DCHECK(primary_);
- std::vector<VkPipelineStageFlags> wait_dst_stage_mask(
- num_wait_semaphores, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
- VkSubmitInfo submit_info = {};
- submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submit_info.pNext = nullptr;
- submit_info.waitSemaphoreCount = num_wait_semaphores;
- submit_info.pWaitSemaphores = wait_semaphores;
- submit_info.pWaitDstStageMask = wait_dst_stage_mask.data();
- submit_info.commandBufferCount = 1;
- submit_info.pCommandBuffers = &command_buffer_;
- submit_info.signalSemaphoreCount = num_signal_semaphores;
- submit_info.pSignalSemaphores = signal_semaphores;
- VkResult result = VK_SUCCESS;
- VkFence fence;
- result = device_queue_->GetFenceHelper()->GetFence(&fence);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "Failed to create fence: " << result;
- return false;
- }
- result =
- vkQueueSubmit(device_queue_->GetVulkanQueue(), 1, &submit_info, fence);
- if (VK_SUCCESS != result) {
- vkDestroyFence(device_queue_->GetVulkanDevice(), fence, nullptr);
- submission_fence_ = VulkanFenceHelper::FenceHandle();
- } else {
- submission_fence_ = device_queue_->GetFenceHelper()->EnqueueFence(fence);
- }
- PostExecution();
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkQueueSubmit() failed: " << result;
- return false;
- }
- return true;
- }
- void VulkanCommandBuffer::Enqueue(VkCommandBuffer primary_command_buffer) {
- DCHECK(!primary_);
- vkCmdExecuteCommands(primary_command_buffer, 1, &command_buffer_);
- PostExecution();
- }
- void VulkanCommandBuffer::Clear() {
- // Mark to reset upon next use.
- if (record_type_ != RECORD_TYPE_EMPTY)
- record_type_ = RECORD_TYPE_DIRTY;
- }
- void VulkanCommandBuffer::Wait(uint64_t timeout) {
- if (!submission_fence_.is_valid())
- return;
- device_queue_->GetFenceHelper()->Wait(submission_fence_, timeout);
- }
- bool VulkanCommandBuffer::SubmissionFinished() {
- if (!submission_fence_.is_valid())
- return true;
- return device_queue_->GetFenceHelper()->HasPassed(submission_fence_);
- }
- void VulkanCommandBuffer::TransitionImageLayout(
- VkImage image,
- VkImageLayout old_layout,
- VkImageLayout new_layout,
- uint32_t src_queue_family_index,
- uint32_t dst_queue_family_index) {
- VkImageMemoryBarrier barrier = {};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.srcAccessMask = GetAccessMask(old_layout);
- barrier.dstAccessMask = GetAccessMask(new_layout);
- barrier.oldLayout = old_layout;
- barrier.newLayout = new_layout;
- barrier.srcQueueFamilyIndex = src_queue_family_index;
- barrier.dstQueueFamilyIndex = dst_queue_family_index;
- barrier.image = image;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- barrier.subresourceRange.baseMipLevel = 0;
- barrier.subresourceRange.levelCount = 1;
- barrier.subresourceRange.baseArrayLayer = 0;
- barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer_,
- GetPipelineStageFlags(device_queue_, old_layout),
- GetPipelineStageFlags(device_queue_, new_layout), 0, 0,
- nullptr, 0, nullptr, 1, &barrier);
- }
- void VulkanCommandBuffer::CopyBufferToImage(VkBuffer buffer,
- VkImage image,
- uint32_t buffer_width,
- uint32_t buffer_height,
- uint32_t width,
- uint32_t height) {
- VkBufferImageCopy region = {};
- region.bufferOffset = 0;
- region.bufferRowLength = buffer_width;
- region.bufferImageHeight = buffer_height;
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.mipLevel = 0;
- region.imageSubresource.baseArrayLayer = 0;
- region.imageSubresource.layerCount = 1;
- region.imageOffset = {0, 0, 0};
- region.imageExtent = {width, height, 1};
- vkCmdCopyBufferToImage(command_buffer_, buffer, image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
- }
- void VulkanCommandBuffer::CopyImageToBuffer(VkBuffer buffer,
- VkImage image,
- uint32_t buffer_width,
- uint32_t buffer_height,
- uint32_t width,
- uint32_t height) {
- VkBufferImageCopy region = {};
- region.bufferOffset = 0;
- region.bufferRowLength = buffer_width;
- region.bufferImageHeight = buffer_height;
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.mipLevel = 0;
- region.imageSubresource.baseArrayLayer = 0;
- region.imageSubresource.layerCount = 1;
- region.imageOffset = {0, 0, 0};
- region.imageExtent = {width, height, 1};
- vkCmdCopyImageToBuffer(command_buffer_, image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1,
- ®ion);
- }
- void VulkanCommandBuffer::PostExecution() {
- if (record_type_ == RECORD_TYPE_SINGLE_USE) {
- // Clear upon next use.
- record_type_ = RECORD_TYPE_DIRTY;
- } else if (record_type_ == RECORD_TYPE_MULTI_USE) {
- // Can no longer record new items unless marked as clear.
- record_type_ = RECORD_TYPE_RECORDED;
- }
- }
- void VulkanCommandBuffer::ResetIfDirty() {
- DCHECK(!recording_);
- if (record_type_ == RECORD_TYPE_DIRTY) {
- // Block if command buffer is still in use. This can be externally avoided
- // using the asynchronous SubmissionFinished() function.
- Wait(UINT64_MAX);
- VkResult result = vkResetCommandBuffer(command_buffer_, 0);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkResetCommandBuffer() failed: " << result;
- } else {
- record_type_ = RECORD_TYPE_EMPTY;
- }
- }
- }
- CommandBufferRecorderBase::~CommandBufferRecorderBase() {
- VkResult result = vkEndCommandBuffer(handle_);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkEndCommandBuffer() failed: " << result;
- }
- }
- ScopedMultiUseCommandBufferRecorder::ScopedMultiUseCommandBufferRecorder(
- VulkanCommandBuffer& command_buffer)
- : CommandBufferRecorderBase(command_buffer) {
- ValidateMultiUse(command_buffer);
- VkCommandBufferBeginInfo begin_info = {};
- begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- VkResult result = vkBeginCommandBuffer(handle_, &begin_info);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkBeginCommandBuffer() failed: " << result;
- }
- }
- ScopedSingleUseCommandBufferRecorder::ScopedSingleUseCommandBufferRecorder(
- VulkanCommandBuffer& command_buffer)
- : CommandBufferRecorderBase(command_buffer) {
- ValidateSingleUse(command_buffer);
- VkCommandBufferBeginInfo begin_info = {};
- begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- VkResult result = vkBeginCommandBuffer(handle_, &begin_info);
- if (VK_SUCCESS != result) {
- LOG(ERROR) << "vkBeginCommandBuffer() failed: " << result;
- }
- }
- } // namespace gpu
|