mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
224 lines
7.8 KiB
C++
224 lines
7.8 KiB
C++
#include "stdafx.h"
|
|
#include "image_helpers.h"
|
|
#include "image.h"
|
|
#include "util/logs.hpp"
|
|
#include "../VKRenderPass.h"
|
|
#include "../../gcm_enums.h"
|
|
|
|
namespace vk
|
|
{
|
|
VkComponentMapping default_component_map =
|
|
{
|
|
VK_COMPONENT_SWIZZLE_R,
|
|
VK_COMPONENT_SWIZZLE_G,
|
|
VK_COMPONENT_SWIZZLE_B,
|
|
VK_COMPONENT_SWIZZLE_A
|
|
};
|
|
|
|
VkImageAspectFlags get_aspect_flags(VkFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
default:
|
|
return VK_IMAGE_ASPECT_COLOR_BIT;
|
|
case VK_FORMAT_D16_UNORM:
|
|
case VK_FORMAT_D32_SFLOAT:
|
|
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
}
|
|
}
|
|
|
|
VkComponentMapping apply_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector)
|
|
{
|
|
VkComponentSwizzle final_mapping[4] = {};
|
|
|
|
for (u8 channel = 0; channel < 4; ++channel)
|
|
{
|
|
switch (remap_vector.second[channel])
|
|
{
|
|
case CELL_GCM_TEXTURE_REMAP_ONE:
|
|
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE;
|
|
break;
|
|
case CELL_GCM_TEXTURE_REMAP_ZERO:
|
|
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO;
|
|
break;
|
|
case CELL_GCM_TEXTURE_REMAP_REMAP:
|
|
final_mapping[channel] = base_remap[remap_vector.first[channel]];
|
|
break;
|
|
default:
|
|
rsx_log.error("Unknown remap lookup value %d", remap_vector.second[channel]);
|
|
}
|
|
}
|
|
|
|
return{ final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] };
|
|
}
|
|
|
|
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, const VkImageSubresourceRange& range,
|
|
u32 src_queue_family, u32 dst_queue_family, u32 src_access_mask_bits, u32 dst_access_mask_bits)
|
|
{
|
|
if (vk::is_renderpass_open(cmd))
|
|
{
|
|
vk::end_renderpass(cmd);
|
|
}
|
|
|
|
//Prepare an image to match the new layout..
|
|
VkImageMemoryBarrier barrier = {};
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
barrier.newLayout = new_layout;
|
|
barrier.oldLayout = current_layout;
|
|
barrier.image = image;
|
|
barrier.srcAccessMask = 0;
|
|
barrier.dstAccessMask = 0;
|
|
barrier.srcQueueFamilyIndex = src_queue_family;
|
|
barrier.dstQueueFamilyIndex = dst_queue_family;
|
|
barrier.subresourceRange = range;
|
|
|
|
VkPipelineStageFlags src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
VkPipelineStageFlags dst_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
|
switch (new_layout)
|
|
{
|
|
case VK_IMAGE_LAYOUT_GENERAL:
|
|
// Avoid this layout as it is unoptimized
|
|
barrier.dstAccessMask =
|
|
{
|
|
VK_ACCESS_TRANSFER_READ_BIT |
|
|
VK_ACCESS_TRANSFER_WRITE_BIT |
|
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
|
VK_ACCESS_SHADER_READ_BIT |
|
|
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
|
|
};
|
|
dst_stage =
|
|
{
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT |
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
};
|
|
break;
|
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
|
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
|
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
|
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_UNDEFINED:
|
|
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
|
default:
|
|
fmt::throw_exception("Attempted to transition to an invalid layout");
|
|
}
|
|
|
|
switch (current_layout)
|
|
{
|
|
case VK_IMAGE_LAYOUT_GENERAL:
|
|
// Avoid this layout as it is unoptimized
|
|
if (new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ||
|
|
new_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
|
{
|
|
if (range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
|
|
{
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
}
|
|
else
|
|
{
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|
}
|
|
}
|
|
else if (new_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
|
|
new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
|
{
|
|
// Finish reading before writing
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
}
|
|
else
|
|
{
|
|
barrier.srcAccessMask =
|
|
{
|
|
VK_ACCESS_TRANSFER_READ_BIT |
|
|
VK_ACCESS_TRANSFER_WRITE_BIT |
|
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
|
VK_ACCESS_SHADER_READ_BIT |
|
|
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
|
|
};
|
|
src_stage =
|
|
{
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT |
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
};
|
|
}
|
|
break;
|
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
|
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
|
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
|
barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|
break;
|
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
|
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
|
src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
break;
|
|
default:
|
|
break; //TODO Investigate what happens here
|
|
}
|
|
|
|
barrier.srcAccessMask &= src_access_mask_bits;
|
|
barrier.dstAccessMask &= dst_access_mask_bits;
|
|
|
|
if (!barrier.srcAccessMask) src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
if (!barrier.dstAccessMask) dst_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
|
vkCmdPipelineBarrier(cmd, src_stage, dst_stage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
|
}
|
|
|
|
void change_image_layout(VkCommandBuffer cmd, vk::image* image, VkImageLayout new_layout, const VkImageSubresourceRange& range)
|
|
{
|
|
if (image->current_layout == new_layout) return;
|
|
|
|
change_image_layout(cmd, image->value, image->current_layout, new_layout, range);
|
|
image->current_layout = new_layout;
|
|
}
|
|
|
|
void change_image_layout(VkCommandBuffer cmd, vk::image* image, VkImageLayout new_layout)
|
|
{
|
|
if (image->current_layout == new_layout) return;
|
|
|
|
change_image_layout(cmd, image->value, image->current_layout, new_layout, { image->aspect(), 0, image->mipmaps(), 0, image->layers() });
|
|
image->current_layout = new_layout;
|
|
}
|
|
}
|