mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-07 22:29:48 +00:00
Some cleanups
This commit is contained in:
@@ -16,13 +16,16 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/div_ceil.h"
|
||||
#include "common/vector_math.h"
|
||||
#include <bit>
|
||||
#include "video_core/host_shaders/astc_decoder_comp_spv.h"
|
||||
#include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h"
|
||||
#include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h"
|
||||
#include "video_core/host_shaders/resolve_conditional_render_comp_spv.h"
|
||||
#include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h"
|
||||
#include "video_core/host_shaders/vulkan_uint8_comp_spv.h"
|
||||
#include "video_core/host_shaders/block_linear_unswizzle_3d_bcn_comp_spv.h"
|
||||
#include "video_core/host_shaders/block_linear_unswizzle_2d_comp_spv.h"
|
||||
#include "video_core/host_shaders/block_linear_unswizzle_3d_comp_spv.h"
|
||||
#include "video_core/host_shaders/pitch_unswizzle_comp_spv.h"
|
||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
||||
#include "video_core/surface.h"
|
||||
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
|
||||
@@ -185,6 +188,26 @@ struct AstcPushConstants {
|
||||
u32 block_height_mask;
|
||||
};
|
||||
|
||||
struct BlockLinear3DImagePushConstants {
|
||||
alignas(16) std::array<u32, 3> origin;
|
||||
alignas(16) std::array<s32, 3> destination;
|
||||
u32 bytes_per_block_log2;
|
||||
u32 slice_size;
|
||||
u32 block_size;
|
||||
u32 x_shift;
|
||||
u32 block_height;
|
||||
u32 block_height_mask;
|
||||
u32 block_depth;
|
||||
u32 block_depth_mask;
|
||||
};
|
||||
|
||||
struct PitchUnswizzlePushConstants {
|
||||
std::array<u32, 2> origin;
|
||||
std::array<s32, 2> destination;
|
||||
u32 bytes_per_block_log2;
|
||||
u32 pitch;
|
||||
};
|
||||
|
||||
struct QueriesPrefixScanPushConstants {
|
||||
u32 min_accumulation_base;
|
||||
u32 max_accumulation_base;
|
||||
@@ -616,260 +639,230 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0;
|
||||
constexpr u32 BL3D_BINDING_OUTPUT_BUFFER = 1;
|
||||
namespace {
|
||||
|
||||
struct alignas(16) BlockLinearUnswizzle3DPushConstants {
|
||||
u32 blocks_dim[3]; // Offset 0
|
||||
u32 bytes_per_block_log2; // Offset 12
|
||||
|
||||
u32 origin[3]; // Offset 16
|
||||
u32 slice_size; // Offset 28
|
||||
|
||||
u32 block_size; // Offset 32
|
||||
u32 x_shift; // Offset 36
|
||||
u32 block_height; // Offset 40
|
||||
u32 block_height_mask; // Offset 44
|
||||
|
||||
u32 block_depth; // Offset 48
|
||||
u32 block_depth_mask; // Offset 52
|
||||
s32 _pad; // Offset 56
|
||||
|
||||
s32 destination[3]; // Offset 60
|
||||
s32 _pad_end; // Offset 72
|
||||
};
|
||||
static_assert(sizeof(BlockLinearUnswizzle3DPushConstants) <= 128);
|
||||
|
||||
BlockLinearUnswizzle3DPass::BlockLinearUnswizzle3DPass(
|
||||
const Device& device_, Scheduler& scheduler_,
|
||||
DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
|
||||
: ComputePass(device_, scheduler_, descriptor_pool_,
|
||||
std::array<VkDescriptorSetLayoutBinding, 2>{{
|
||||
{
|
||||
.binding = BL3D_BINDING_INPUT_BUFFER,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // block-linear input
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
},
|
||||
{
|
||||
.binding = BL3D_BINDING_OUTPUT_BUFFER,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
},
|
||||
}},
|
||||
std::array<VkDescriptorUpdateTemplateEntry, 2>{{
|
||||
{
|
||||
.dstBinding = BL3D_BINDING_INPUT_BUFFER,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.offset = BL3D_BINDING_INPUT_BUFFER * sizeof(DescriptorUpdateEntry),
|
||||
.stride = sizeof(DescriptorUpdateEntry),
|
||||
},
|
||||
{
|
||||
.dstBinding = BL3D_BINDING_OUTPUT_BUFFER,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.offset = BL3D_BINDING_OUTPUT_BUFFER * sizeof(DescriptorUpdateEntry),
|
||||
.stride = sizeof(DescriptorUpdateEntry),
|
||||
}
|
||||
}},
|
||||
DescriptorBankInfo{
|
||||
.uniform_buffers = 0,
|
||||
.storage_buffers = 2,
|
||||
.texture_buffers = 0,
|
||||
.image_buffers = 0,
|
||||
.textures = 0,
|
||||
.images = 0,
|
||||
.score = 2,
|
||||
},
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(BlockLinearUnswizzle3DPushConstants)>,
|
||||
BLOCK_LINEAR_UNSWIZZLE_3D_BCN_COMP_SPV),
|
||||
scheduler{scheduler_},
|
||||
staging_buffer_pool{staging_buffer_pool_},
|
||||
compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
|
||||
|
||||
BlockLinearUnswizzle3DPass::~BlockLinearUnswizzle3DPass() = default;
|
||||
|
||||
// God have mercy on my soul
|
||||
void BlockLinearUnswizzle3DPass::Unswizzle(
|
||||
Image& image,
|
||||
const StagingBufferRef& swizzled,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles,
|
||||
u32 z_start, u32 z_count)
|
||||
{
|
||||
using namespace VideoCommon::Accelerated;
|
||||
|
||||
const u32 MAX_BATCH_SLICES = (std::min)(z_count, image.info.size.depth);
|
||||
|
||||
// Allocate or grow to cover this batch's slice count
|
||||
image.AllocateComputeUnswizzleBuffer(MAX_BATCH_SLICES);
|
||||
|
||||
ASSERT(swizzles.size() == 1);
|
||||
const auto& sw = swizzles[0];
|
||||
const auto params = MakeBlockLinearSwizzle3DParams(sw, image.info);
|
||||
|
||||
const u32 blocks_x = (image.info.size.width + 3) / 4;
|
||||
const u32 blocks_y = (image.info.size.height + 3) / 4;
|
||||
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
for (u32 z_offset = 0; z_offset < z_count; z_offset += MAX_BATCH_SLICES) {
|
||||
const u32 current_chunk_slices = (std::min)(MAX_BATCH_SLICES, z_count - z_offset);
|
||||
const u32 current_z_start = z_start + z_offset;
|
||||
|
||||
UnswizzleChunk(image, swizzled, sw, params, blocks_x, blocks_y,
|
||||
current_z_start, current_chunk_slices);
|
||||
void RecordUnswizzleBeginBarrier(Scheduler& scheduler, VkPipeline vk_pipeline, VkImage vk_image,
|
||||
VkImageAspectFlags aspect_mask, bool is_initialized) {
|
||||
VkAccessFlags src_access = VK_ACCESS_NONE;
|
||||
VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkPipelineStageFlags src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
if (is_initialized) {
|
||||
src_access = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
old_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
src_stage = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockLinearUnswizzle3DPass::UnswizzleChunk(
|
||||
Image& image,
|
||||
const StagingBufferRef& swizzled,
|
||||
const VideoCommon::SwizzleParameters& sw,
|
||||
const BlockLinearSwizzle3DParams& params,
|
||||
u32 blocks_x, u32 blocks_y,
|
||||
u32 z_start, u32 z_count)
|
||||
{
|
||||
BlockLinearUnswizzle3DPushConstants pc{};
|
||||
pc.origin[0] = params.origin[0];
|
||||
pc.origin[1] = params.origin[1];
|
||||
pc.origin[2] = z_start; // Current chunk's Z start
|
||||
|
||||
pc.destination[0] = params.destination[0];
|
||||
pc.destination[1] = params.destination[1];
|
||||
pc.destination[2] = 0; // Shader writes to start of output buffer
|
||||
|
||||
pc.bytes_per_block_log2 = params.bytes_per_block_log2;
|
||||
pc.slice_size = params.slice_size;
|
||||
pc.block_size = params.block_size;
|
||||
pc.x_shift = params.x_shift;
|
||||
pc.block_height = params.block_height;
|
||||
pc.block_height_mask = params.block_height_mask;
|
||||
pc.block_depth = params.block_depth;
|
||||
pc.block_depth_mask = params.block_depth_mask;
|
||||
|
||||
pc.blocks_dim[0] = blocks_x;
|
||||
pc.blocks_dim[1] = blocks_y;
|
||||
pc.blocks_dim[2] = z_count; // Only process the count
|
||||
|
||||
compute_pass_descriptor_queue.Acquire(scheduler, 3);
|
||||
compute_pass_descriptor_queue.AddBuffer(swizzled.buffer,
|
||||
sw.buffer_offset + swizzled.offset,
|
||||
image.guest_size_bytes - sw.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddBuffer(*image.compute_unswizzle_buffer, 0,
|
||||
image.compute_unswizzle_buffer_size);
|
||||
|
||||
const void* descriptor_data = compute_pass_descriptor_queue.UpdateData();
|
||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||
|
||||
const u32 gx = Common::DivCeil(blocks_x, 8u);
|
||||
const u32 gy = Common::DivCeil(blocks_y, 8u);
|
||||
const u32 gz = Common::DivCeil(z_count, 4u);
|
||||
|
||||
const u32 bytes_per_block = 1u << pc.bytes_per_block_log2;
|
||||
const VkDeviceSize output_slice_size =
|
||||
static_cast<VkDeviceSize>(blocks_x) * blocks_y * bytes_per_block;
|
||||
const VkDeviceSize barrier_size = output_slice_size * z_count;
|
||||
|
||||
const bool is_first_chunk = (z_start == 0);
|
||||
|
||||
const VkBuffer out_buffer = *image.compute_unswizzle_buffer;
|
||||
const VkImage dst_image = image.Handle();
|
||||
const VkImageAspectFlags aspect = image.AspectMask();
|
||||
const u32 image_width = image.info.size.width;
|
||||
const u32 image_height = image.info.size.height;
|
||||
|
||||
scheduler.Record([this, set, descriptor_data, pc, gx, gy, gz, z_start, z_count,
|
||||
barrier_size, is_first_chunk, out_buffer, dst_image, aspect,
|
||||
image_width, image_height
|
||||
](vk::CommandBuffer cmdbuf) {
|
||||
|
||||
if (dst_image == VK_NULL_HANDLE || out_buffer == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(pc), &pc);
|
||||
cmdbuf.Dispatch(gx, gy, gz);
|
||||
|
||||
// Single barrier for compute -> transfer (buffer ready, image transition)
|
||||
const VkBufferMemoryBarrier buffer_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = out_buffer,
|
||||
.offset = 0,
|
||||
.size = barrier_size,
|
||||
};
|
||||
|
||||
// Image layout transition
|
||||
const VkImageMemoryBarrier pre_barrier{
|
||||
scheduler.Record([vk_pipeline, vk_image, aspect_mask, src_access, old_layout,
|
||||
src_stage](vk::CommandBuffer cmdbuf) {
|
||||
const VkImageMemoryBarrier image_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = is_first_chunk ? VkAccessFlags{} :
|
||||
static_cast<VkAccessFlags>(VK_ACCESS_TRANSFER_WRITE_BIT),
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.oldLayout = is_first_chunk ? VK_IMAGE_LAYOUT_UNDEFINED :
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange = {aspect, 0, 1, 0, 1},
|
||||
};
|
||||
|
||||
// Single barrier handles both buffer and image
|
||||
cmdbuf.PipelineBarrier(
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0,
|
||||
nullptr, buffer_barrier, pre_barrier
|
||||
);
|
||||
|
||||
// Copy chunk to correct Z position in image
|
||||
const VkBufferImageCopy copy{
|
||||
.bufferOffset = 0, // Read from start of staging buffer
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource = {aspect, 0, 0, 1},
|
||||
.imageOffset = {0, 0, static_cast<s32>(z_start)}, // Write to correct Z
|
||||
.imageExtent = {image_width, image_height, z_count},
|
||||
};
|
||||
cmdbuf.CopyBufferToImage(out_buffer, dst_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy);
|
||||
|
||||
// Post-copy transition
|
||||
const VkImageMemoryBarrier post_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.srcAccessMask = src_access,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.oldLayout = old_layout,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange = {aspect, 0, 1, 0, 1},
|
||||
.image = vk_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
|
||||
cmdbuf.PipelineBarrier(
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
0,
|
||||
nullptr, nullptr, post_barrier
|
||||
);
|
||||
cmdbuf.PipelineBarrier(src_stage, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
||||
});
|
||||
}
|
||||
|
||||
void RecordUnswizzleEndBarrier(Scheduler& scheduler, VkImage vk_image,
|
||||
VkImageAspectFlags aspect_mask) {
|
||||
scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) {
|
||||
const VkImageMemoryBarrier image_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = vk_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, 0, image_barrier);
|
||||
});
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BlockLinearUnswizzleImage2DPass::BlockLinearUnswizzleImage2DPass(
|
||||
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
|
||||
: ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
|
||||
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(BlockLinearSwizzle2DParams)>,
|
||||
BLOCK_LINEAR_UNSWIZZLE_2D_COMP_SPV),
|
||||
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
|
||||
compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
|
||||
|
||||
BlockLinearUnswizzleImage2DPass::~BlockLinearUnswizzleImage2DPass() = default;
|
||||
|
||||
void BlockLinearUnswizzleImage2DPass::Unswizzle(
|
||||
Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
using namespace VideoCommon::Accelerated;
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||
const VkImage vk_image = image.Handle();
|
||||
RecordUnswizzleBeginBarrier(scheduler, *pipeline, vk_image, aspect_mask,
|
||||
image.ExchangeInitialization());
|
||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||
const size_t input_offset = swizzle.buffer_offset + map.offset;
|
||||
const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U);
|
||||
const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 8U);
|
||||
const u32 num_dispatches_z = image.info.resources.layers;
|
||||
|
||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
|
||||
image.guest_size_bytes - swizzle.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
||||
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
||||
|
||||
const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info);
|
||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, params,
|
||||
descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, params);
|
||||
cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, num_dispatches_z);
|
||||
});
|
||||
}
|
||||
RecordUnswizzleEndBarrier(scheduler, vk_image, aspect_mask);
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
BlockLinearUnswizzleImage3DPass::BlockLinearUnswizzleImage3DPass(
|
||||
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
|
||||
: ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
|
||||
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(BlockLinear3DImagePushConstants)>,
|
||||
BLOCK_LINEAR_UNSWIZZLE_3D_COMP_SPV),
|
||||
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
|
||||
compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
|
||||
|
||||
BlockLinearUnswizzleImage3DPass::~BlockLinearUnswizzleImage3DPass() = default;
|
||||
|
||||
void BlockLinearUnswizzleImage3DPass::Unswizzle(
|
||||
Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
using namespace VideoCommon::Accelerated;
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||
const VkImage vk_image = image.Handle();
|
||||
RecordUnswizzleBeginBarrier(scheduler, *pipeline, vk_image, aspect_mask,
|
||||
image.ExchangeInitialization());
|
||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||
const size_t input_offset = swizzle.buffer_offset + map.offset;
|
||||
const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 16U);
|
||||
const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 8U);
|
||||
const u32 num_dispatches_z = Common::DivCeil(swizzle.num_tiles.depth, 2U);
|
||||
|
||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
|
||||
image.guest_size_bytes - swizzle.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
||||
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
||||
|
||||
const auto p = MakeBlockLinearSwizzle3DParams(swizzle, image.info);
|
||||
const BlockLinear3DImagePushConstants params{
|
||||
.origin = p.origin,
|
||||
.destination = p.destination,
|
||||
.bytes_per_block_log2 = p.bytes_per_block_log2,
|
||||
.slice_size = p.slice_size,
|
||||
.block_size = p.block_size,
|
||||
.x_shift = p.x_shift,
|
||||
.block_height = p.block_height,
|
||||
.block_height_mask = p.block_height_mask,
|
||||
.block_depth = p.block_depth,
|
||||
.block_depth_mask = p.block_depth_mask,
|
||||
};
|
||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, params,
|
||||
descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, params);
|
||||
cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, num_dispatches_z);
|
||||
});
|
||||
}
|
||||
RecordUnswizzleEndBarrier(scheduler, vk_image, aspect_mask);
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
PitchUnswizzlePass::PitchUnswizzlePass(const Device& device_, Scheduler& scheduler_,
|
||||
DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
|
||||
: ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
|
||||
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(PitchUnswizzlePushConstants)>,
|
||||
PITCH_UNSWIZZLE_COMP_SPV),
|
||||
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
|
||||
compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
|
||||
|
||||
PitchUnswizzlePass::~PitchUnswizzlePass() = default;
|
||||
|
||||
void PitchUnswizzlePass::Unswizzle(Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
const u32 bytes_per_block = VideoCore::Surface::BytesPerBlock(image.info.format);
|
||||
ASSERT(std::has_single_bit(bytes_per_block));
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||
const VkImage vk_image = image.Handle();
|
||||
RecordUnswizzleBeginBarrier(scheduler, *pipeline, vk_image, aspect_mask,
|
||||
image.ExchangeInitialization());
|
||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||
const size_t input_offset = swizzle.buffer_offset + map.offset;
|
||||
const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U);
|
||||
const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 8U);
|
||||
|
||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
|
||||
image.guest_size_bytes - swizzle.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
||||
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
||||
|
||||
const PitchUnswizzlePushConstants params{
|
||||
.origin = {0, 0},
|
||||
.destination = {0, 0},
|
||||
.bytes_per_block_log2 = static_cast<u32>(std::countr_zero(bytes_per_block)),
|
||||
.pitch = image.info.pitch,
|
||||
};
|
||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, params,
|
||||
descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, params);
|
||||
cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, 1);
|
||||
});
|
||||
}
|
||||
RecordUnswizzleEndBarrier(scheduler, vk_image, aspect_mask);
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "video_core/texture_cache/types.h"
|
||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
#include "video_core/texture_cache/accelerated_swizzle.h"
|
||||
|
||||
namespace VideoCommon {
|
||||
struct SwizzleParameters;
|
||||
@@ -25,8 +24,6 @@ struct SwizzleParameters;
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
using VideoCommon::Accelerated::BlockLinearSwizzle3DParams;
|
||||
|
||||
class Device;
|
||||
class StagingBufferPool;
|
||||
class Scheduler;
|
||||
@@ -137,26 +134,50 @@ private:
|
||||
MemoryAllocator& memory_allocator;
|
||||
};
|
||||
|
||||
class BlockLinearUnswizzle3DPass final : public ComputePass {
|
||||
class BlockLinearUnswizzleImage2DPass final : public ComputePass {
|
||||
public:
|
||||
explicit BlockLinearUnswizzle3DPass(const Device& device_, Scheduler& scheduler_,
|
||||
DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
|
||||
~BlockLinearUnswizzle3DPass();
|
||||
explicit BlockLinearUnswizzleImage2DPass(
|
||||
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
|
||||
~BlockLinearUnswizzleImage2DPass();
|
||||
|
||||
void Unswizzle(Image& image,
|
||||
const StagingBufferRef& swizzled,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles,
|
||||
u32 z_start, u32 z_count);
|
||||
void Unswizzle(Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles);
|
||||
|
||||
void UnswizzleChunk(
|
||||
Image& image,
|
||||
const StagingBufferRef& swizzled,
|
||||
const VideoCommon::SwizzleParameters& sw,
|
||||
const BlockLinearSwizzle3DParams& params,
|
||||
u32 blocks_x, u32 blocks_y,
|
||||
u32 z_start, u32 z_count);
|
||||
private:
|
||||
Scheduler& scheduler;
|
||||
StagingBufferPool& staging_buffer_pool;
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue;
|
||||
};
|
||||
|
||||
class BlockLinearUnswizzleImage3DPass final : public ComputePass {
|
||||
public:
|
||||
explicit BlockLinearUnswizzleImage3DPass(
|
||||
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
|
||||
~BlockLinearUnswizzleImage3DPass();
|
||||
|
||||
void Unswizzle(Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles);
|
||||
|
||||
private:
|
||||
Scheduler& scheduler;
|
||||
StagingBufferPool& staging_buffer_pool;
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue;
|
||||
};
|
||||
|
||||
class PitchUnswizzlePass final : public ComputePass {
|
||||
public:
|
||||
explicit PitchUnswizzlePass(const Device& device_, Scheduler& scheduler_,
|
||||
DescriptorPool& descriptor_pool_,
|
||||
StagingBufferPool& staging_buffer_pool_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
|
||||
~PitchUnswizzlePass();
|
||||
|
||||
void Unswizzle(Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles);
|
||||
|
||||
private:
|
||||
Scheduler& scheduler;
|
||||
|
||||
@@ -160,6 +160,73 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
info.size.depth == 1;
|
||||
}
|
||||
|
||||
[[nodiscard]] VkFormat UnswizzleStorageFormat(u32 bytes_per_block) {
|
||||
switch (bytes_per_block) {
|
||||
case 1:
|
||||
return VK_FORMAT_R8_UINT;
|
||||
case 2:
|
||||
return VK_FORMAT_R16_UINT;
|
||||
case 4:
|
||||
return VK_FORMAT_R32_UINT;
|
||||
case 8:
|
||||
return VK_FORMAT_R32G32_UINT;
|
||||
case 16:
|
||||
return VK_FORMAT_R32G32B32A32_UINT;
|
||||
default:
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsUnswizzleStorageFormatSupported(const Device& device, u32 bytes_per_block) {
|
||||
switch (bytes_per_block) {
|
||||
case 1:
|
||||
return device.IsStorageBuffer8BitAccessSupported();
|
||||
case 2:
|
||||
return device.IsStorageBuffer16BitAccessSupported();
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsUnswizzleAcceleratedFormat(const Device& device, PixelFormat format) {
|
||||
if (IsPixelFormatASTC(format) || VideoCore::Surface::IsPixelFormatBCn(format)) {
|
||||
return false;
|
||||
}
|
||||
if (VideoCore::Surface::GetFormatType(format) != SurfaceType::ColorTexture) {
|
||||
return false;
|
||||
}
|
||||
return IsUnswizzleStorageFormatSupported(device, BytesPerBlock(format));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool WillUseAcceleratedUnswizzle(const Device& device, const ImageInfo& info) {
|
||||
switch (info.type) {
|
||||
case ImageType::e2D:
|
||||
case ImageType::e3D:
|
||||
case ImageType::Linear:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (info.num_samples > 1 || !device.IsKhrImageFormatListSupported()) {
|
||||
return false;
|
||||
}
|
||||
return IsUnswizzleAcceleratedFormat(device, info.format);
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageViewType UnswizzleStorageViewType(ImageType type) {
|
||||
if (type == ImageType::e3D) {
|
||||
return VK_IMAGE_VIEW_TYPE_3D;
|
||||
}
|
||||
if (type == ImageType::Linear) {
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
}
|
||||
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info,
|
||||
std::optional<VkFormat> format_override = {}) {
|
||||
auto format_info =
|
||||
@@ -249,7 +316,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
}
|
||||
|
||||
[[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image,
|
||||
VkFormat format) {
|
||||
VkFormat format,
|
||||
VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY) {
|
||||
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
@@ -260,7 +328,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
.pNext = &storage_image_view_usage_create_info,
|
||||
.flags = 0,
|
||||
.image = image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
||||
.viewType = view_type,
|
||||
.format = format,
|
||||
.components{
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
@@ -946,6 +1014,14 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue, memory_allocator);
|
||||
}
|
||||
if (device.IsKhrImageFormatListSupported()) {
|
||||
bl_unswizzle_2d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue);
|
||||
bl_unswizzle_3d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue);
|
||||
pitch_unswizzle_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue);
|
||||
}
|
||||
if (!device.IsKhrImageFormatListSupported()) {
|
||||
return;
|
||||
}
|
||||
@@ -953,6 +1029,8 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||
const auto image_format = static_cast<PixelFormat>(index_a);
|
||||
if (IsPixelFormatASTC(image_format) && !device.IsOptimalAstcSupported()) {
|
||||
view_formats[index_a].push_back(VK_FORMAT_A8B8G8R8_UNORM_PACK32);
|
||||
} else if (IsUnswizzleAcceleratedFormat(device, image_format)) {
|
||||
view_formats[index_a].push_back(UnswizzleStorageFormat(BytesPerBlock(image_format)));
|
||||
}
|
||||
for (size_t index_b = 0; index_b < VideoCore::Surface::MaxPixelFormat; index_b++) {
|
||||
const auto view_format = static_cast<PixelFormat>(index_b);
|
||||
@@ -964,18 +1042,14 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::values.gpu_unswizzle_enabled.GetValue()) {
|
||||
bl3d_unswizzle_pass.emplace(device, scheduler, descriptor_pool,
|
||||
staging_buffer_pool, compute_pass_descriptor_queue);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheRuntime::Finish() {
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
|
||||
return staging_buffer_pool.Request(size, MemoryUsage::Upload, deferred);
|
||||
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size) {
|
||||
return staging_buffer_pool.Request(size, MemoryUsage::Upload);
|
||||
}
|
||||
|
||||
StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
|
||||
@@ -1899,6 +1973,10 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
flags |= VideoCommon::ImageFlagBits::Converted;
|
||||
flags |= VideoCommon::ImageFlagBits::CostlyLoad;
|
||||
}
|
||||
if (False(flags & VideoCommon::ImageFlagBits::Converted) &&
|
||||
WillUseAcceleratedUnswizzle(runtime->device, info)) {
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
}
|
||||
if (runtime->device.HasDebuggingToolAttached()) {
|
||||
original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
|
||||
}
|
||||
@@ -1911,6 +1989,14 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
storage_image_views[level] =
|
||||
MakeStorageView(device, level, *original_image, storage_format);
|
||||
}
|
||||
} else if (True(flags & VideoCommon::ImageFlagBits::AcceleratedUpload)) {
|
||||
const auto& device = runtime->device.GetLogical();
|
||||
const VkFormat storage_format = UnswizzleStorageFormat(BytesPerBlock(info.format));
|
||||
const VkImageViewType view_type = UnswizzleStorageViewType(info.type);
|
||||
for (s32 level = 0; level < info.resources.levels; ++level) {
|
||||
storage_image_views[level] =
|
||||
MakeStorageView(device, level, *original_image, storage_format, view_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1927,48 +2013,6 @@ Image::~Image() {
|
||||
}
|
||||
}
|
||||
|
||||
void Image::AllocateComputeUnswizzleBuffer(u32 max_slices) {
|
||||
using VideoCore::Surface::BytesPerBlock;
|
||||
|
||||
const u32 block_bytes = BytesPerBlock(info.format); // 8 for BC1, 16 for BC6H
|
||||
const u32 block_width = 4;
|
||||
const u32 block_height = 4;
|
||||
|
||||
// BCn is 4x4x1 blocks
|
||||
const u32 blocks_x = (info.size.width + block_width - 1) / block_width;
|
||||
const u32 blocks_y = (info.size.height + block_height - 1) / block_height;
|
||||
const u32 blocks_z = (std::min)(max_slices, info.size.depth);
|
||||
|
||||
const u64 block_count =
|
||||
static_cast<u64>(blocks_x) *
|
||||
static_cast<u64>(blocks_y) *
|
||||
static_cast<u64>(blocks_z);
|
||||
|
||||
const VkDeviceSize required_size = block_count * block_bytes;
|
||||
if (has_compute_unswizzle_buffer && required_size <= compute_unswizzle_buffer_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
compute_unswizzle_buffer_size = required_size;
|
||||
|
||||
VkBufferCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = compute_unswizzle_buffer_size,
|
||||
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
};
|
||||
|
||||
compute_unswizzle_buffer =
|
||||
runtime->memory_allocator.CreateBuffer(ci, MemoryUsage::DeviceLocal);
|
||||
|
||||
has_compute_unswizzle_buffer = true;
|
||||
}
|
||||
|
||||
void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies) {
|
||||
// TODO: Move this to another API
|
||||
@@ -2326,11 +2370,15 @@ VkImageView Image::StorageImageView(s32 level) noexcept {
|
||||
if (!view) {
|
||||
auto format_info =
|
||||
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format);
|
||||
VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
if (WillUseAcceleratedAstcDecode(runtime->device, info)) {
|
||||
format_info.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
} else if (True(flags & VideoCommon::ImageFlagBits::AcceleratedUpload)) {
|
||||
format_info.format = UnswizzleStorageFormat(BytesPerBlock(info.format));
|
||||
view_type = UnswizzleStorageViewType(info.type);
|
||||
}
|
||||
view = MakeStorageView(runtime->device.GetLogical(), level, *(this->*current_image),
|
||||
format_info.format);
|
||||
format_info.format, view_type);
|
||||
}
|
||||
return *view;
|
||||
}
|
||||
@@ -3129,25 +3177,20 @@ VkRenderPass Framebuffer::RenderPassVariant(u32 color_clear_mask, bool depth_ste
|
||||
|
||||
void TextureCacheRuntime::AccelerateImageUpload(
|
||||
Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles,
|
||||
u32 z_start, u32 z_count) {
|
||||
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
if (IsPixelFormatASTC(image.info.format)) {
|
||||
return astc_decoder_pass->Assemble(image, map, swizzles);
|
||||
}
|
||||
|
||||
if (!Settings::values.gpu_unswizzle_enabled.GetValue() || !bl3d_unswizzle_pass) {
|
||||
if (IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D) {
|
||||
ASSERT(false && "GPU unswizzle is disabled for BCn 3D texture");
|
||||
}
|
||||
ASSERT(false);
|
||||
return;
|
||||
switch (image.info.type) {
|
||||
case ImageType::e2D:
|
||||
return bl_unswizzle_2d_pass->Unswizzle(image, map, swizzles);
|
||||
case ImageType::e3D:
|
||||
return bl_unswizzle_3d_pass->Unswizzle(image, map, swizzles);
|
||||
case ImageType::Linear:
|
||||
return pitch_unswizzle_pass->Unswizzle(image, map, swizzles);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bl3d_unswizzle_pass && IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D && image.info.resources.levels == 1 && image.info.resources.layers == 1) {
|
||||
return bl3d_unswizzle_pass->Unswizzle(image, map, swizzles, z_start, z_count);
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
void Finish();
|
||||
|
||||
StagingBufferRef UploadStagingBuffer(size_t size, bool deferred = false);
|
||||
StagingBufferRef UploadStagingBuffer(size_t size);
|
||||
|
||||
StagingBufferRef DownloadStagingBuffer(size_t size, bool deferred = false);
|
||||
|
||||
@@ -98,8 +98,7 @@ public:
|
||||
}
|
||||
|
||||
void AccelerateImageUpload(Image&, const StagingBufferRef&,
|
||||
std::span<const VideoCommon::SwizzleParameters>,
|
||||
u32 z_start, u32 z_count);
|
||||
std::span<const VideoCommon::SwizzleParameters>);
|
||||
|
||||
void InsertUploadMemoryBarrier() {}
|
||||
|
||||
@@ -157,8 +156,9 @@ public:
|
||||
BlitImageHelper& blit_image_helper;
|
||||
RenderPassCache& render_pass_cache;
|
||||
std::optional<ASTCDecoderPass> astc_decoder_pass;
|
||||
|
||||
std::optional<BlockLinearUnswizzle3DPass> bl3d_unswizzle_pass;
|
||||
std::optional<BlockLinearUnswizzleImage2DPass> bl_unswizzle_2d_pass;
|
||||
std::optional<BlockLinearUnswizzleImage3DPass> bl_unswizzle_3d_pass;
|
||||
std::optional<PitchUnswizzlePass> pitch_unswizzle_pass;
|
||||
const Settings::ResolutionScalingInfo& resolution;
|
||||
std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats;
|
||||
|
||||
@@ -334,8 +334,6 @@ public:
|
||||
void DownloadMemory(const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||
|
||||
void AllocateComputeUnswizzleImage();
|
||||
|
||||
[[nodiscard]] VkImage Handle() const noexcept {
|
||||
return *(this->*current_image);
|
||||
}
|
||||
@@ -361,10 +359,6 @@ public:
|
||||
|
||||
bool ScaleDown(bool ignore = false);
|
||||
|
||||
u64 allocation_tick;
|
||||
|
||||
friend class BlockLinearUnswizzle3DPass;
|
||||
|
||||
private:
|
||||
bool BlitScaleHelper(bool scale_up);
|
||||
|
||||
@@ -376,12 +370,6 @@ private:
|
||||
vk::Image original_image;
|
||||
vk::Image scaled_image;
|
||||
|
||||
vk::Buffer compute_unswizzle_buffer;
|
||||
VkDeviceSize compute_unswizzle_buffer_size = 0;
|
||||
bool has_compute_unswizzle_buffer = false;
|
||||
|
||||
void AllocateComputeUnswizzleBuffer(u32 max_slices);
|
||||
|
||||
// Use a pointer to field because it is relative, so that the object can be
|
||||
// moved without breaking the reference.
|
||||
vk::Image Image::*current_image{};
|
||||
|
||||
Reference in New Issue
Block a user