gpu: fix 10-11-11 render-target storage
Co-authored-by: Çağatay Güçlü <33038942+defektu@users.noreply.github.com>
This commit is contained in:
parent
07c84876a1
commit
5940e623d5
|
|
@ -259,7 +259,7 @@ set(gpu_tiler_shader_names
|
|||
depth
|
||||
promote_d16
|
||||
demote_d16
|
||||
swap_bgra16
|
||||
color_transform
|
||||
)
|
||||
file(GLOB gpu_tiler_shader_includes CONFIGURE_DEPENDS "${gpu_tiler_shader_dir}/gpu_tiler_*.inc")
|
||||
foreach(shader_name IN LISTS gpu_tiler_shader_names)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ struct FormatInfo {
|
|||
constexpr FormatInfo kFormatInfo[] = {
|
||||
{BufferFormat::k8UNorm, 1, 0, 1, true, false},
|
||||
{BufferFormat::k8UScaled, 1, 0, 0, true, false},
|
||||
{BufferFormat::k8SNorm, 0, 0, 1, false, false},
|
||||
{BufferFormat::k8SNorm, 1, 0, 1, false, false},
|
||||
{BufferFormat::k8UInt, 1, 0, 1, true, true},
|
||||
{BufferFormat::k16UNorm, 2, 0, 2, true, false},
|
||||
{BufferFormat::k16SNorm, 2, 0, 2, true, false},
|
||||
|
|
@ -43,6 +43,7 @@ constexpr FormatInfo kFormatInfo[] = {
|
|||
{BufferFormat::k16_16Float, 4, 0, 4, true, false},
|
||||
{BufferFormat::k11_11_10UInt, 4, 0, 4, true, true},
|
||||
{BufferFormat::k11_11_10Float, 4, 0, 4, true, false},
|
||||
{BufferFormat::k10_11_11Float, 4, 0, 4, true, false},
|
||||
{BufferFormat::k10_10_10_2UNorm, 4, 0, 4, true, false},
|
||||
{BufferFormat::k10_10_10_2UInt, 4, 0, 4, true, true},
|
||||
{BufferFormat::k8_8_8_8UNorm, 4, 0, 4, true, false},
|
||||
|
|
@ -69,7 +70,7 @@ constexpr FormatInfo kFormatInfo[] = {
|
|||
{BufferFormat::k9_9_9_5Float, 4, 0, 0, true, false},
|
||||
{BufferFormat::k5_6_5UNorm, 2, 0, 2, true, false},
|
||||
{BufferFormat::k5_5_5_1UNorm, 2, 0, 2, true, false},
|
||||
{BufferFormat::k1_5_5_5UNorm, 0, 0, 2, false, false},
|
||||
{BufferFormat::k1_5_5_5UNorm, 2, 0, 2, false, false},
|
||||
{BufferFormat::k4_4_4_4UNorm, 2, 0, 2, true, false},
|
||||
{BufferFormat::kFmask8_S2_F1, 1, 0, 1, true, false},
|
||||
{BufferFormat::kFmask8_S4_F1, 1, 0, 1, true, false},
|
||||
|
|
|
|||
|
|
@ -195,6 +195,9 @@ bool TextureCache::SameBacking(const ImageInfo& cached, const ImageInfo& request
|
|||
if (cached.tile_mode != requested.tile_mode) {
|
||||
return false;
|
||||
}
|
||||
if (cached.GetColorTransform() != requested.GetColorTransform()) {
|
||||
return false;
|
||||
}
|
||||
if (!ImageViewOps::FormatsCompatible(cached.pixel_format, requested.pixel_format) ||
|
||||
cached.type != requested.type) {
|
||||
return false;
|
||||
|
|
@ -634,6 +637,7 @@ void TextureCache::CopyImage(ImageId destination_id, ImageId source_id) {
|
|||
const bool source_depth = source.info.IsDepth();
|
||||
const bool dest_depth = destination.info.IsDepth();
|
||||
const bool direct_copy =
|
||||
source.info.GetColorTransform() == destination.info.GetColorTransform() &&
|
||||
(source.backing.image_type == destination.backing.image_type ||
|
||||
(source.backing.image_type != vk::ImageType::e1D &&
|
||||
destination.backing.image_type != vk::ImageType::e1D)) &&
|
||||
|
|
@ -647,7 +651,7 @@ void TextureCache::CopyImage(ImageId destination_id, ImageId source_id) {
|
|||
EXIT("TextureCache: cross-format multisample image copy is unsupported\n");
|
||||
}
|
||||
auto& copy_buffer = m_buffer_cache.GetUtilityBuffer(MemoryUsage::DeviceLocal);
|
||||
destination.CopyImageWithBuffer(source, copy_buffer);
|
||||
destination.CopyImageWithBuffer(source, copy_buffer, m_tiler);
|
||||
}
|
||||
if (source.IsGpuModified()) {
|
||||
destination.MarkGpuModified();
|
||||
|
|
@ -801,6 +805,9 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques
|
|||
}
|
||||
return {merged_id};
|
||||
}
|
||||
if (requested.GetColorTransform() != cached.info.GetColorTransform()) {
|
||||
return {ExpandImage(requested, cached_id)};
|
||||
}
|
||||
if (requested.IsBlock() && !cached.info.IsBlock()) {
|
||||
return {ExpandImage(requested, cached_id)};
|
||||
}
|
||||
|
|
@ -905,8 +912,8 @@ struct TextureCache::TextureTransfer {
|
|||
TextureUploadLayout layout;
|
||||
std::vector<vk::BufferImageCopy> regions;
|
||||
std::vector<GpuTileInfo> tiles;
|
||||
bool swap_bgra16 = false;
|
||||
bool valid = false;
|
||||
ColorTransform color_transform = ColorTransform::None;
|
||||
bool valid = false;
|
||||
|
||||
[[nodiscard]] uint64_t LinearSize() const {
|
||||
uint64_t size = 0;
|
||||
|
|
@ -935,7 +942,7 @@ TextureCache::BuildTextureTransfer(const Image& image, BindingType binding,
|
|||
const char* owner = "TextureCache readback";
|
||||
|
||||
TextureTransfer transfer;
|
||||
transfer.swap_bgra16 = info.bgra16;
|
||||
transfer.color_transform = info.GetColorTransform();
|
||||
if (upload) {
|
||||
if ((render_target || video_out) &&
|
||||
(info.resources.layers == 0 || info.data.size % info.resources.layers != 0 ||
|
||||
|
|
@ -1023,10 +1030,9 @@ void TextureCache::UploadImage(Image& image, Buffer& source, uint64_t source_off
|
|||
TileManager::Result linear {source.Handle(), source_offset, info.data.size};
|
||||
if (!transfer.tiles.empty()) {
|
||||
linear = m_tiler.Detile(source.Handle(), source_offset, info.data.size,
|
||||
transfer.LinearSize(), transfer.tiles);
|
||||
}
|
||||
if (transfer.swap_bgra16) {
|
||||
linear = m_tiler.SwapBgra16(linear);
|
||||
transfer.LinearSize(), transfer.tiles, transfer.color_transform);
|
||||
} else if (transfer.color_transform != ColorTransform::None) {
|
||||
linear = m_tiler.TransformColor(linear, transfer.color_transform, true);
|
||||
}
|
||||
upload(transfer.regions, linear);
|
||||
return;
|
||||
|
|
@ -1741,14 +1747,14 @@ void TextureCache::DownloadImage(Image& image, Buffer& destination, uint64_t des
|
|||
}
|
||||
|
||||
auto& texture = transfer.texture;
|
||||
const auto transform = texture.swap_bgra16 ? TileManager::ColorTransform::SwapBgra16
|
||||
: TileManager::ColorTransform::None;
|
||||
const auto transform = texture.color_transform;
|
||||
if (texture.tiles.empty()) {
|
||||
if (transform == TileManager::ColorTransform::SwapBgra16) {
|
||||
if (transform != ColorTransform::None) {
|
||||
auto linear = m_tiler.GetScratchBuffer(destination_size);
|
||||
image.Download(texture.regions, linear.buffer, 0, linear.size);
|
||||
m_tiler.SwapBgra16(linear,
|
||||
{destination.Handle(), destination_offset, destination_size});
|
||||
m_tiler.TransformColor(linear,
|
||||
{destination.Handle(), destination_offset, destination_size},
|
||||
transform, false);
|
||||
return;
|
||||
}
|
||||
for (auto& copy: texture.regions) {
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ void RenderExecutor::ResolveRenderColorTarget(CommandBuffer& buffer, RenderColor
|
|||
desc.type = TextureCache::BindingType::RenderTarget;
|
||||
desc.info.data = {rt.base.addr, backing_size};
|
||||
desc.info.pixel_format = target_format.format;
|
||||
desc.info.guest_format = transfer_format;
|
||||
desc.info.guest_format = target_format.guest_format;
|
||||
desc.info.type = image_type;
|
||||
desc.info.extent = {width, height, depth};
|
||||
desc.info.resources = {levels, volume ? 1u : view.image_layers};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "graphics/host_gpu/renderer/cache/streamBuffer.h"
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
#include "graphics/host_gpu/renderer/image/imageView.h"
|
||||
#include "graphics/host_gpu/renderer/image/tiler.h"
|
||||
#include "graphics/host_gpu/renderer/renderTarget.h"
|
||||
#include "kernel/memory.h"
|
||||
|
||||
|
|
@ -456,7 +457,7 @@ uint32_t Image::CopyRows(uint64_t row_size, uint32_t rows, uint64_t capacity) no
|
|||
return static_cast<uint32_t>(std::min<uint64_t>(rows, capacity / row_size));
|
||||
}
|
||||
|
||||
void Image::CopyImageWithBuffer(Image& source, Buffer& buffer) {
|
||||
void Image::CopyImageWithBuffer(Image& source, Buffer& buffer, TileManager& tiler) {
|
||||
EXIT_IF(buffer.Handle() == nullptr || source.backing.samples != 1 || backing.samples != 1);
|
||||
m_scheduler.EndRendering();
|
||||
const uint32_t levels = std::min(source.backing.mip_levels, backing.mip_levels);
|
||||
|
|
@ -474,6 +475,8 @@ void Image::CopyImageWithBuffer(Image& source, Buffer& buffer) {
|
|||
const uint32_t destination_block = info.IsBlock() ? 4u : 1u;
|
||||
EXIT_IF(levels == 0 || source_bytes == 0 || source_bytes != destination_bytes ||
|
||||
source_block != destination_block);
|
||||
const auto source_transform = source.info.GetColorTransform();
|
||||
const auto target_transform = info.GetColorTransform();
|
||||
|
||||
vk::BufferMemoryBarrier2 barrier {};
|
||||
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTransfer;
|
||||
|
|
@ -535,9 +538,19 @@ void Image::CopyImageWithBuffer(Image& source, Buffer& buffer) {
|
|||
command.copyImageToBuffer(source.backing.image,
|
||||
vk::ImageLayout::eTransferSrcOptimal, buffer.Handle(),
|
||||
source_copy);
|
||||
barrier.srcAccessMask = vk::AccessFlagBits2::eTransferWrite;
|
||||
barrier.dstAccessMask = vk::AccessFlagBits2::eTransferRead;
|
||||
command.pipelineBarrier2(dependency);
|
||||
if (source_transform != target_transform) {
|
||||
const TileManager::Result bytes {buffer.Handle(), 0, copy_size};
|
||||
if (source_transform != ColorTransform::None) {
|
||||
tiler.TransformColor(bytes, bytes, source_transform, false);
|
||||
}
|
||||
if (target_transform != ColorTransform::None) {
|
||||
tiler.TransformColor(bytes, bytes, target_transform, true);
|
||||
}
|
||||
} else {
|
||||
barrier.srcAccessMask = vk::AccessFlagBits2::eTransferWrite;
|
||||
barrier.dstAccessMask = vk::AccessFlagBits2::eTransferRead;
|
||||
command.pipelineBarrier2(dependency);
|
||||
}
|
||||
command.copyBufferToImage(buffer.Handle(), backing.image,
|
||||
vk::ImageLayout::eTransferDstOptimal, destination_copy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ namespace Libs::Graphics {
|
|||
|
||||
class Buffer;
|
||||
class CommandScheduler;
|
||||
class TileManager;
|
||||
struct ImageTestAccess;
|
||||
|
||||
using ImageId = Common::SlotId;
|
||||
|
|
@ -66,7 +67,7 @@ public:
|
|||
void CopyImage(Image& source);
|
||||
void Resolve(Image& source, const ImageSubresourceRange& source_range,
|
||||
const ImageSubresourceRange& destination_range);
|
||||
void CopyImageWithBuffer(Image& source, Buffer& buffer);
|
||||
void CopyImageWithBuffer(Image& source, Buffer& buffer, TileManager& tiler);
|
||||
void CopyMip(Image& source, uint32_t mip, uint32_t layer);
|
||||
|
||||
void InvalidateCpuWrite(uint64_t vaddr, uint64_t size) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
enum class ColorTransform : uint32_t { None, SwapBgra16, Reverse10_11_11 };
|
||||
|
||||
enum class VideoOutCompression : uint8_t { Uncompressed, Dcc256_256_0, Dcc256_64_64, Unsupported };
|
||||
|
||||
enum class ImageMetadataKind : uint8_t { None, Htile, Dcc, Cmask };
|
||||
|
|
@ -70,6 +72,14 @@ struct ImageInfo {
|
|||
bool bgra16 = false;
|
||||
std::array<ImageMipInfo, 16> mip_layout {};
|
||||
|
||||
[[nodiscard]] ColorTransform GetColorTransform() const noexcept {
|
||||
if (bgra16) return ColorTransform::SwapBgra16;
|
||||
switch (guest_format) {
|
||||
case Prospero::BufferFormat::k10_11_11Float:
|
||||
return ColorTransform::Reverse10_11_11;
|
||||
default: return ColorTransform::None;
|
||||
}
|
||||
}
|
||||
[[nodiscard]] constexpr bool HasStencil() const noexcept { return !stencil.Empty(); }
|
||||
[[nodiscard]] constexpr bool HasMetadata() const noexcept {
|
||||
return metadata.kind != ImageMetadataKind::None;
|
||||
|
|
@ -91,7 +101,8 @@ struct ImageInfo {
|
|||
}
|
||||
[[nodiscard]] bool IsCompatible(const ImageInfo& other) const noexcept {
|
||||
return pixel_format == other.pixel_format && samples == other.samples &&
|
||||
bytes_per_block == other.bytes_per_block;
|
||||
bytes_per_block == other.bytes_per_block &&
|
||||
GetColorTransform() == other.GetColorTransform();
|
||||
}
|
||||
[[nodiscard]] int32_t MipOf(const ImageInfo& container) const noexcept {
|
||||
if (container.resources.levels > container.mip_layout.size()) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ struct HostFormatInfo {
|
|||
|
||||
HostFormatInfo ResolveHostFormat(Prospero::BufferFormat guest_format,
|
||||
Prospero::ChannelOrder order) {
|
||||
if (guest_format == Prospero::BufferFormat::k10_11_11Float) {
|
||||
return {vk::Format::eB10G11R11UfloatPack32, Prospero::ColorMappingBgra};
|
||||
}
|
||||
if (order == Prospero::ChannelOrder::kAlt) {
|
||||
switch (guest_format) {
|
||||
case Prospero::BufferFormat::k8_8_8_8UNorm:
|
||||
|
|
@ -131,7 +134,8 @@ RenderTargetFormatInfo TextureGetRenderTargetFormat(Prospero::ChannelLayout layo
|
|||
if (host_format.format != vk::Format::eUndefined && bytes != 0) {
|
||||
const auto order_mapping =
|
||||
kRenderTargetColorMappings[static_cast<size_t>(order)][encoding.components - 1u];
|
||||
return {host_format.format, bytes, host_format.host_to_storage.Then(order_mapping)};
|
||||
return {host_format.format, bytes, host_format.host_to_storage.Then(order_mapping),
|
||||
encoding.buffer_format};
|
||||
}
|
||||
}
|
||||
EXIT("unsupported render-target format combination: layout=%u type=%u order=%u\n",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ struct RenderTargetFormatInfo {
|
|||
vk::Format format = vk::Format::eUndefined;
|
||||
uint32_t bytes_per_element = 0;
|
||||
Prospero::ColorComponentMapping export_mapping;
|
||||
Prospero::BufferFormat guest_format = Prospero::BufferFormat::kInvalid;
|
||||
};
|
||||
|
||||
struct SurfaceFormatInfo {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "gpu_tiler_shaders/gpu_tiler_standard4_spv.h"
|
||||
#include "gpu_tiler_shaders/gpu_tiler_standard64_3d_spv.h"
|
||||
#include "gpu_tiler_shaders/gpu_tiler_standard64_spv.h"
|
||||
#include "gpu_tiler_shaders/gpu_tiler_swap_bgra16_spv.h"
|
||||
#include "gpu_tiler_shaders/gpu_tiler_color_transform_spv.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/renderer/cache/streamBuffer.h"
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
|
|
@ -31,7 +31,7 @@ TileManager::TileManager(GraphicContext& graphics, CommandScheduler& scheduler,
|
|||
StreamBuffer& stream_buffer)
|
||||
: m_graphics(graphics), m_scheduler(scheduler), m_stream_buffer(stream_buffer) {
|
||||
static_assert(FamilyCount == 9);
|
||||
static_assert(sizeof(Push) == 52);
|
||||
static_assert(sizeof(Push) == 60);
|
||||
std::array<vk::DescriptorSetLayoutBinding, 3> bindings {};
|
||||
for (uint32_t index = 0; index < 2; index++) {
|
||||
bindings[index] = {index, vk::DescriptorType::eStorageBuffer, 1,
|
||||
|
|
@ -77,8 +77,8 @@ TileManager::~TileManager() {
|
|||
if (m_d32_to_d16 != nullptr) {
|
||||
m_graphics.device.destroyPipeline(m_d32_to_d16, nullptr);
|
||||
}
|
||||
if (m_swap_bgra16 != nullptr) {
|
||||
m_graphics.device.destroyPipeline(m_swap_bgra16, nullptr);
|
||||
if (m_color_transform != nullptr) {
|
||||
m_graphics.device.destroyPipeline(m_color_transform, nullptr);
|
||||
}
|
||||
if (m_pipeline_layout != nullptr) {
|
||||
m_graphics.device.destroyPipelineLayout(m_pipeline_layout, nullptr);
|
||||
|
|
@ -90,7 +90,8 @@ TileManager::~TileManager() {
|
|||
|
||||
void TileManager::Prepare(bool tile, uint64_t tiled_capacity, uint64_t linear_capacity,
|
||||
std::span<const GpuTileInfo> infos, uint64_t source_base,
|
||||
uint64_t target_base, std::vector<Dispatch>& dispatches) {
|
||||
uint64_t target_base, std::vector<Dispatch>& dispatches,
|
||||
ColorTransform transform) {
|
||||
EXIT_IF(infos.empty() || tiled_capacity == 0 || linear_capacity == 0);
|
||||
const auto& limits = m_graphics.GetPhysicalDeviceProperties().limits;
|
||||
EXIT_NOT_IMPLEMENTED(tiled_capacity > UINT32_MAX || linear_capacity > UINT32_MAX);
|
||||
|
|
@ -108,6 +109,8 @@ void TileManager::Prepare(bool tile, uint64_t tiled_capacity, uint64_t linear_ca
|
|||
dispatches.clear();
|
||||
dispatches.reserve(infos.size());
|
||||
for (const auto& info: infos) {
|
||||
EXIT_IF((transform == ColorTransform::SwapBgra16 && info.bytes_per_element != 8u) ||
|
||||
(transform == ColorTransform::Reverse10_11_11 && info.bytes_per_element != 4u));
|
||||
TileBlockLayout block {};
|
||||
const uint32_t tiled_width = info.tiled_width != 0 ? info.tiled_width : info.pitch;
|
||||
const uint32_t tiled_height = info.tiled_height != 0 ? info.tiled_height : info.height;
|
||||
|
|
@ -193,6 +196,7 @@ void TileManager::Prepare(bool tile, uint64_t tiled_capacity, uint64_t linear_ca
|
|||
dispatch.push.tail_x = info.tail_x;
|
||||
dispatch.push.tail_y = info.tail_y;
|
||||
dispatch.push.tail = info.tail;
|
||||
dispatch.push.color_transform = static_cast<uint32_t>(transform);
|
||||
dispatches.push_back(dispatch);
|
||||
}
|
||||
|
||||
|
|
@ -338,13 +342,14 @@ void TileManager::Record(vk::Buffer source, uint64_t source_offset,
|
|||
|
||||
TileManager::Result TileManager::Detile(vk::Buffer tiled, uint64_t tiled_offset,
|
||||
uint64_t tiled_capacity, uint64_t linear_capacity,
|
||||
std::span<const GpuTileInfo> infos) {
|
||||
std::span<const GpuTileInfo> infos,
|
||||
ColorTransform transform) {
|
||||
const auto& limits = m_graphics.GetPhysicalDeviceProperties().limits;
|
||||
const uint64_t descriptor_alignment =
|
||||
std::max<uint64_t>(limits.minStorageBufferOffsetAlignment, 4);
|
||||
const uint64_t source_base = tiled_offset & (descriptor_alignment - 1);
|
||||
std::vector<Dispatch> dispatches;
|
||||
Prepare(false, tiled_capacity, linear_capacity, infos, source_base, 0, dispatches);
|
||||
Prepare(false, tiled_capacity, linear_capacity, infos, source_base, 0, dispatches, transform);
|
||||
auto scratch = GetScratchBuffer(linear_capacity, tiled);
|
||||
Record(tiled, tiled_offset, tiled_capacity, scratch.buffer, 0, scratch.size, dispatches,
|
||||
true);
|
||||
|
|
@ -375,15 +380,11 @@ void TileManager::TileImage(Image& image, std::span<const vk::BufferImageCopy> r
|
|||
std::max<uint64_t>(limits.minStorageBufferOffsetAlignment, 4);
|
||||
const uint64_t target_base = tiled_offset & (descriptor_alignment - 1);
|
||||
std::vector<Dispatch> dispatches;
|
||||
// Reserve stream parameters before recording the image download and conversion.
|
||||
Prepare(true, tiled_capacity, linear_capacity, infos, 0, target_base, dispatches);
|
||||
// Reserve stream parameters before recording the image download.
|
||||
Prepare(true, tiled_capacity, linear_capacity, infos, 0, target_base, dispatches, transform);
|
||||
auto linear = GetScratchBuffer(linear_capacity, tiled);
|
||||
image.Download(regions, linear.buffer, 0, linear.size);
|
||||
Result source {linear.buffer, 0, linear.size};
|
||||
if (transform == ColorTransform::SwapBgra16) {
|
||||
source = SwapBgra16(source);
|
||||
}
|
||||
Record(source.buffer, source.offset, linear_capacity, tiled, tiled_offset, tiled_capacity,
|
||||
Record(linear.buffer, 0, linear_capacity, tiled, tiled_offset, tiled_capacity,
|
||||
dispatches, false);
|
||||
}
|
||||
|
||||
|
|
@ -582,9 +583,20 @@ void TileManager::ConvertD16(Result source, Result target, D16Direction directio
|
|||
&barriers[1], 0, nullptr);
|
||||
}
|
||||
|
||||
void TileManager::SwapBgra16(Result input, Result output, uint32_t pixels) {
|
||||
if (m_swap_bgra16 == nullptr) {
|
||||
const auto module = CompileSPV(GPU_TILER_SWAP_BGRA16_SPV, m_graphics.device);
|
||||
void TileManager::TransformColor(Result input, Result output, ColorTransform transform,
|
||||
bool to_host) {
|
||||
uint32_t element_bytes = 0;
|
||||
switch (transform) {
|
||||
case ColorTransform::SwapBgra16: element_bytes = 8; break;
|
||||
case ColorTransform::Reverse10_11_11: element_bytes = 4; break;
|
||||
default: EXIT("invalid color transform\n");
|
||||
}
|
||||
EXIT_IF(input.size == 0 || input.size % element_bytes != 0 ||
|
||||
input.size / element_bytes > UINT32_MAX ||
|
||||
output.size < input.size);
|
||||
const auto pixels = static_cast<uint32_t>(input.size / element_bytes);
|
||||
if (m_color_transform == nullptr) {
|
||||
const auto module = CompileSPV(GPU_TILER_COLOR_TRANSFORM_SPV, m_graphics.device);
|
||||
vk::PipelineShaderStageCreateInfo stage {};
|
||||
stage.stage = vk::ShaderStageFlagBits::eCompute;
|
||||
stage.module = module;
|
||||
|
|
@ -593,14 +605,12 @@ void TileManager::SwapBgra16(Result input, Result output, uint32_t pixels) {
|
|||
create.stage = stage;
|
||||
create.layout = m_pipeline_layout;
|
||||
const auto result =
|
||||
m_graphics.device.createComputePipelines(nullptr, 1, &create, nullptr, &m_swap_bgra16);
|
||||
m_graphics.device.createComputePipelines(nullptr, 1, &create, nullptr, &m_color_transform);
|
||||
m_graphics.device.destroyShaderModule(module, nullptr);
|
||||
RequireVulkanSuccess(result, "create BGRA16 swap pipeline");
|
||||
RequireVulkanSuccess(result, "create color transform pipeline");
|
||||
}
|
||||
const uint64_t bytes = static_cast<uint64_t>(pixels) * 8u;
|
||||
EXIT_IF(pixels == 0);
|
||||
const auto input_binding = BindStorage(input, bytes);
|
||||
const auto output_binding = BindStorage(output, bytes);
|
||||
const auto input_binding = BindStorage(input, input.size);
|
||||
const auto output_binding = BindStorage(output, input.size);
|
||||
|
||||
const vk::DescriptorBufferInfo infos[] {
|
||||
input_binding.info,
|
||||
|
|
@ -631,13 +641,15 @@ void TileManager::SwapBgra16(Result input, Result output, uint32_t pixels) {
|
|||
command.pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eAllCommands | vk::PipelineStageFlagBits::eHost,
|
||||
vk::PipelineStageFlagBits::eComputeShader, {}, 0, nullptr, 2, barriers, 0, nullptr);
|
||||
command.bindPipeline(vk::PipelineBindPoint::eCompute, m_swap_bgra16);
|
||||
command.bindPipeline(vk::PipelineBindPoint::eCompute, m_color_transform);
|
||||
command.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, m_pipeline_layout, 0,
|
||||
static_cast<uint32_t>(writes.size()), writes.data());
|
||||
Push push {};
|
||||
push.src_base = input_binding.base;
|
||||
push.dst_base = output_binding.base;
|
||||
push.width = pixels;
|
||||
push.src_base = input_binding.base;
|
||||
push.dst_base = output_binding.base;
|
||||
push.width = pixels;
|
||||
push.color_transform = static_cast<uint32_t>(transform);
|
||||
push.to_host = to_host;
|
||||
command.pushConstants(m_pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(push),
|
||||
&push);
|
||||
command.dispatch((pixels + 63u) / 64u, 1, 1);
|
||||
|
|
@ -648,17 +660,11 @@ void TileManager::SwapBgra16(Result input, Result output, uint32_t pixels) {
|
|||
0, nullptr);
|
||||
}
|
||||
|
||||
TileManager::Result TileManager::SwapBgra16(Result input) {
|
||||
EXIT_NOT_IMPLEMENTED(input.size == 0 || input.size % 8u != 0 || input.size / 8u > UINT32_MAX);
|
||||
TileManager::Result TileManager::TransformColor(Result input, ColorTransform transform,
|
||||
bool to_host) {
|
||||
auto result = GetScratchBuffer(input.size, input.buffer);
|
||||
SwapBgra16(input, result, static_cast<uint32_t>(input.size / 8u));
|
||||
TransformColor(input, result, transform, to_host);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TileManager::SwapBgra16(Result input, Result output) {
|
||||
EXIT_NOT_IMPLEMENTED(input.size == 0 || input.size % 8u != 0 || input.size / 8u > UINT32_MAX ||
|
||||
output.size < input.size);
|
||||
SwapBgra16(input, output, static_cast<uint32_t>(input.size / 8u));
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "common/common.h"
|
||||
#include "graphics/guest_gpu/tile.h"
|
||||
#include "graphics/host_gpu/renderer/image/imageInfo.h"
|
||||
#include "graphics/host_gpu/vulkanCommon.h"
|
||||
|
||||
#include <array>
|
||||
|
|
@ -42,7 +43,6 @@ struct GpuTileInfo {
|
|||
class TileManager final {
|
||||
public:
|
||||
enum class D16Direction { Promote, Demote };
|
||||
enum class ColorTransform { None, SwapBgra16 };
|
||||
|
||||
struct Result {
|
||||
vk::Buffer buffer = nullptr;
|
||||
|
|
@ -65,7 +65,8 @@ public:
|
|||
|
||||
// Consume scratch results before the next acquisition, or pass their buffer as input.
|
||||
[[nodiscard]] Result Detile(vk::Buffer tiled, uint64_t tiled_offset, uint64_t tiled_capacity,
|
||||
uint64_t linear_capacity, std::span<const GpuTileInfo> infos);
|
||||
uint64_t linear_capacity, std::span<const GpuTileInfo> infos,
|
||||
ColorTransform transform = ColorTransform::None);
|
||||
void Tile(vk::Buffer linear, uint64_t linear_offset, uint64_t linear_capacity, vk::Buffer tiled,
|
||||
uint64_t tiled_offset, uint64_t tiled_capacity, std::span<const GpuTileInfo> infos);
|
||||
void TileImage(Image& image, std::span<const vk::BufferImageCopy> regions, vk::Buffer tiled,
|
||||
|
|
@ -75,8 +76,8 @@ public:
|
|||
[[nodiscard]] Result GetScratchBuffer(uint64_t size, vk::Buffer input = nullptr);
|
||||
void ConvertD16(Result source, Result target, D16Direction direction, bool d32,
|
||||
const D16Layout& layout);
|
||||
[[nodiscard]] Result SwapBgra16(Result input);
|
||||
void SwapBgra16(Result input, Result output);
|
||||
[[nodiscard]] Result TransformColor(Result input, ColorTransform transform, bool to_host);
|
||||
void TransformColor(Result input, Result output, ColorTransform transform, bool to_host);
|
||||
|
||||
private:
|
||||
friend struct TileManagerTestAccess;
|
||||
|
|
@ -100,6 +101,8 @@ private:
|
|||
uint32_t tail_x;
|
||||
uint32_t tail_y;
|
||||
uint32_t tail;
|
||||
uint32_t color_transform;
|
||||
uint32_t to_host;
|
||||
};
|
||||
struct Dispatch {
|
||||
Push push {};
|
||||
|
|
@ -118,12 +121,11 @@ private:
|
|||
uint32_t max_groups) noexcept;
|
||||
void Prepare(bool tile, uint64_t tiled_capacity, uint64_t linear_capacity,
|
||||
std::span<const GpuTileInfo> infos, uint64_t source_base, uint64_t target_base,
|
||||
std::vector<Dispatch>& dispatches);
|
||||
std::vector<Dispatch>& dispatches, ColorTransform transform = ColorTransform::None);
|
||||
void Record(vk::Buffer source, uint64_t source_offset, uint64_t source_capacity,
|
||||
vk::Buffer target, uint64_t target_offset, uint64_t target_capacity,
|
||||
std::span<Dispatch> dispatches, bool clear_target);
|
||||
[[nodiscard]] vk::Pipeline GetPipeline(uint32_t slot);
|
||||
void SwapBgra16(Result input, Result output, uint32_t pixels);
|
||||
|
||||
GraphicContext& m_graphics;
|
||||
CommandScheduler& m_scheduler;
|
||||
|
|
@ -132,11 +134,11 @@ private:
|
|||
vk::DescriptorSetLayout m_descriptor_layout = nullptr;
|
||||
vk::PipelineLayout m_pipeline_layout = nullptr;
|
||||
std::array<vk::Pipeline, PipelineCount> m_pipelines {};
|
||||
vk::Pipeline m_d16_to_d24 = nullptr;
|
||||
vk::Pipeline m_d16_to_d32 = nullptr;
|
||||
vk::Pipeline m_d24_to_d16 = nullptr;
|
||||
vk::Pipeline m_d32_to_d16 = nullptr;
|
||||
vk::Pipeline m_swap_bgra16 = nullptr;
|
||||
vk::Pipeline m_d16_to_d24 = nullptr;
|
||||
vk::Pipeline m_d16_to_d32 = nullptr;
|
||||
vk::Pipeline m_d24_to_d16 = nullptr;
|
||||
vk::Pipeline m_d32_to_d16 = nullptr;
|
||||
vk::Pipeline m_color_transform = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// ColorTransform values match imageInfo.h. Preserve the floating-point bit fields exactly.
|
||||
uvec2 transform_color(uvec2 value, uint transform, bool to_host) {
|
||||
switch (transform) {
|
||||
case 1u:
|
||||
return uvec2((value.y & 0xffffu) | (value.x & 0xffff0000u),
|
||||
(value.x & 0xffffu) | (value.y & 0xffff0000u));
|
||||
case 2u: {
|
||||
uint packed = value.x;
|
||||
if (to_host) {
|
||||
value.x = (packed >> 21u) | (((packed >> 10u) & 0x7ffu) << 11u) |
|
||||
((packed & 0x3ffu) << 22u);
|
||||
} else {
|
||||
value.x = (packed >> 22u) | (((packed >> 11u) & 0x7ffu) << 10u) |
|
||||
((packed & 0x7ffu) << 21u);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
layout(local_size_x = 64) in;
|
||||
|
||||
|
|
@ -19,17 +20,23 @@ layout(push_constant, std430) uniform Push {
|
|||
uint tail_x;
|
||||
uint tail_y;
|
||||
uint tail;
|
||||
uint color_transform;
|
||||
uint to_host;
|
||||
} params;
|
||||
|
||||
#include "gpu_tiler_color.inc"
|
||||
|
||||
void main() {
|
||||
uint pixel = gl_GlobalInvocationID.x;
|
||||
if (pixel >= params.width) {
|
||||
return;
|
||||
}
|
||||
uint src = (params.src_base >> 2u) + pixel * 2u;
|
||||
uint dst = (params.dst_base >> 2u) + pixel * 2u;
|
||||
uint bg = input_buffer.data[src];
|
||||
uint ra = input_buffer.data[src + 1u];
|
||||
output_buffer.data[dst] = (ra & 0x0000ffffu) | (bg & 0xffff0000u);
|
||||
output_buffer.data[dst + 1u] = (bg & 0x0000ffffu) | (ra & 0xffff0000u);
|
||||
uint words = params.color_transform == 1u ? 2u : 1u;
|
||||
uint src = (params.src_base >> 2u) + pixel * words;
|
||||
uint dst = (params.dst_base >> 2u) + pixel * words;
|
||||
uvec2 value = uvec2(input_buffer.data[src], 0u);
|
||||
if (words == 2u) value.y = input_buffer.data[src + 1u];
|
||||
value = transform_color(value, params.color_transform, params.to_host != 0u);
|
||||
output_buffer.data[dst] = value.x;
|
||||
if (words == 2u) output_buffer.data[dst + 1u] = value.y;
|
||||
}
|
||||
|
|
@ -17,10 +17,19 @@ layout(set = 0, binding = 2, std140) uniform Push {
|
|||
uint tail_x;
|
||||
uint tail_y;
|
||||
uint tail;
|
||||
uint color_transform;
|
||||
} params;
|
||||
|
||||
#include "gpu_tiler_color.inc"
|
||||
|
||||
void copy_element(uint src, uint dst) {
|
||||
if (ELEMENT_BYTES >= 4) {
|
||||
if ((ELEMENT_BYTES == 4u || ELEMENT_BYTES == 8u) && params.color_transform != 0u) {
|
||||
uvec2 value = uvec2(input_buffer.data[src >> 2], 0u);
|
||||
if (ELEMENT_BYTES == 8u) value.y = input_buffer.data[(src >> 2) + 1u];
|
||||
value = transform_color(value, params.color_transform, TILE == 0u);
|
||||
output_buffer.data[dst >> 2] = value.x;
|
||||
if (ELEMENT_BYTES == 8u) output_buffer.data[(dst >> 2) + 1u] = value.y;
|
||||
} else if (ELEMENT_BYTES >= 4) {
|
||||
for (uint i = 0; i < ELEMENT_BYTES; i += 4) {
|
||||
output_buffer.data[(dst + i) >> 2] = input_buffer.data[(src + i) >> 2];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8848,6 +8848,8 @@ public:
|
|||
total.size >= 8 && total.size <= allocation_size,
|
||||
"BGRA16 tiled layout exceeds its guest allocation");
|
||||
std::memset(mapped, 0x5a, total.size);
|
||||
constexpr std::array<uint16_t, 4> initial{0x3c00u, 0x4000u, 0x4200u, 0x4400u};
|
||||
std::memcpy(mapped, initial.data(), sizeof(initial));
|
||||
|
||||
ImageDesc desc{};
|
||||
desc.type = BindingType::RenderTarget;
|
||||
|
|
@ -8870,6 +8872,11 @@ public:
|
|||
|
||||
auto &cache = resources.GetTextureCache();
|
||||
const auto id = cache.FindImage(desc);
|
||||
(void)cache.FindRenderTarget(id, desc);
|
||||
Require(name, "tiled BGRA16 upload",
|
||||
ReadCachedTexel(name, context, id) ==
|
||||
std::vector<u32>{0x40004200u, 0x44003c00u},
|
||||
"fused detiling lost the BGRA16 component transform");
|
||||
auto &image = cache.GetImage(id);
|
||||
image.Transit(vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::AccessFlagBits2::eTransferWrite, {},
|
||||
|
|
@ -10480,6 +10487,15 @@ public:
|
|||
target.format == vk::Format::eR5G5B5A1UnormPack16 &&
|
||||
target.export_mapping == Prospero::ColorMappingAbgr,
|
||||
"shared format resolution changed the existing 1555 render target");
|
||||
for (const auto native : {target, TextureGetRenderTargetFormat(
|
||||
Prospero::ChannelLayout::k8, Prospero::ChannelType::kSNorm,
|
||||
Prospero::ChannelOrder::kStandard)}) {
|
||||
const auto upload = TextureCalcUploadLayout(native.guest_format, 4, 1, 1, 1,
|
||||
Prospero::TileMode::kLinear, 256, false, name);
|
||||
Require(name, "render-target guest upload layout",
|
||||
upload.pitch * native.bytes_per_element == 256 && upload.mips[0].size == 256,
|
||||
"retaining the render-target format lost its physical byte width");
|
||||
}
|
||||
EnsureRuntimeContext();
|
||||
int64_t direct_offset = -1;
|
||||
Require(name, "allocation",
|
||||
|
|
@ -10568,6 +10584,134 @@ public:
|
|||
resources.UnmapMemory(base, allocation_size);
|
||||
scheduler.Finish();
|
||||
}
|
||||
for (const auto tile : {Prospero::TileMode::kLinear, Prospero::TileMode::kRenderTarget}) {
|
||||
constexpr std::array<u32, 4> words{0x883005e1u, 0x7c0e81c0u,
|
||||
0x800f0000u, 0x98120280u};
|
||||
constexpr std::array<std::array<float, 4>, 4> channels{{
|
||||
{1.03125f, 2.03125f, 4.0625f, 1.f}, {0.5f, 0.75f, 1.5f, 1.f},
|
||||
{0.f, 1.f, 2.f, 1.f}, {32.f, 8.f, 16.f, 1.f}}};
|
||||
const auto target = TextureGetRenderTargetFormat(
|
||||
Prospero::ChannelLayout::k10_11_11, Prospero::ChannelType::kFloat,
|
||||
Prospero::ChannelOrder::kReversed);
|
||||
Require(name, "10_11_11 reversed render target",
|
||||
target.format == vk::Format::eB10G11R11UfloatPack32 &&
|
||||
target.guest_format == Prospero::BufferFormat::k10_11_11Float &&
|
||||
target.export_mapping == Prospero::ColorMappingRgba,
|
||||
"PPSA24156 reversed packed-float target lost its physical encoding");
|
||||
std::memset(mapped, 0, allocation_size);
|
||||
std::array<u32, 4> offsets{0, 4, 8, 12};
|
||||
if (tile == Prospero::TileMode::kRenderTarget) {
|
||||
TileBlockLayout block{};
|
||||
u32 block_xor = 0;
|
||||
Require(name, "10_11_11 tile layout",
|
||||
TileGetBlockLayout(TileBlockFamily::RenderTarget64KB, 4, block) &&
|
||||
TileGetBlockXor(block, 0, 0, 0, block_xor),
|
||||
"packed-float render-target layout is unavailable");
|
||||
for (u32 pixel = 0; pixel < words.size(); ++pixel) {
|
||||
Require(name, "10_11_11 tile offset",
|
||||
TileGetBlockOffset(block, pixel, 0, 0, offsets[pixel]),
|
||||
"packed-float texel offset is unavailable");
|
||||
offsets[pixel] ^= block_xor;
|
||||
}
|
||||
}
|
||||
for (u32 pixel = 0; pixel < words.size(); ++pixel) {
|
||||
std::memcpy(static_cast<uint8_t *>(mapped) + offsets[pixel], &words[pixel], sizeof(u32));
|
||||
}
|
||||
RenderContext context(m_runtime_context);
|
||||
auto &scheduler = context.GetCommandScheduler();
|
||||
HW::Context registers{};
|
||||
HW::UserConfig user_config{};
|
||||
HW::Shader shaders{};
|
||||
scheduler.Begin(registers, user_config, shaders);
|
||||
context.MapMemory(base, allocation_size);
|
||||
auto &cache = context.GetTextureCache();
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
constexpr u32 swizzle = DstSel(4, 5, 6, 1);
|
||||
ShaderTextureResource descriptor{{static_cast<u32>(base >> 8u),
|
||||
(static_cast<u32>(Prospero::BufferFormat::k10_11_11Float) << 20u) |
|
||||
(3u << 30u), 0,
|
||||
swizzle | (static_cast<u32>(tile) << 20u) |
|
||||
(static_cast<u32>(Prospero::ImageType::kColor2D) << 28u),
|
||||
0, 0x00700000u, 0, 0}};
|
||||
TestCase test;
|
||||
test.name = name;
|
||||
test.has_user_data = true;
|
||||
test.image_descriptor_swizzle = swizzle;
|
||||
std::copy_n(descriptor.fields, 8, test.user_data.begin());
|
||||
test.user_data[50] = 16 * sizeof(u32);
|
||||
for (u32 pixel = 0; pixel < words.size(); ++pixel) {
|
||||
AppendVMovU32(&test.code, 20, pixel);
|
||||
AppendVMovU32(&test.code, 21, 0);
|
||||
test.code.push_back(EncodeMimg0(0x00, 0xf));
|
||||
test.code.push_back(EncodeMimg1(0, 20));
|
||||
for (u32 channel = 0; channel < 4; ++channel) {
|
||||
AppendStoreVgpr(&test.code, channel, pixel * 4 + channel);
|
||||
test.expected.push_back(std::bit_cast<u32>(channels[pixel][channel]));
|
||||
}
|
||||
}
|
||||
AppendEnd(&test.code);
|
||||
const auto compiled = CompileCase(test, SubgroupSize());
|
||||
ShaderRecompiler::IR::DescriptorValue value{};
|
||||
value.dword_count = 8;
|
||||
std::copy_n(descriptor.fields, 8, value.dwords.begin());
|
||||
const auto binding = RenderExecutorTestAccess::ResolveTexture(
|
||||
executor, compiled.program.info.images.at(0), value);
|
||||
Image sampled;
|
||||
sampled.view = cache.FindTexture(binding.image_id, binding.desc);
|
||||
sampled.layout = cache.GetImage(binding.image_id).backing.state.layout;
|
||||
scheduler.Finish();
|
||||
auto output = CreateStorageBuffer(name, {}, 16);
|
||||
Dispatch(test, compiled, output, nullptr, &sampled);
|
||||
Require(name, "10_11_11 uploaded components",
|
||||
ReadBuffer(name, output, 16) == test.expected,
|
||||
"packed-float upload or sample changed a component's width or order");
|
||||
DestroyBuffer(&output);
|
||||
|
||||
const auto clear = [&](std::array<float, 4> channels) {
|
||||
auto &native = cache.GetImage(binding.image_id);
|
||||
native.Transit(vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::AccessFlagBits2::eTransferWrite, {},
|
||||
scheduler.Current().Handle());
|
||||
const vk::ImageSubresourceRange range{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1};
|
||||
scheduler.Current().Handle().clearColorImage(native.backing.image,
|
||||
vk::ImageLayout::eTransferDstOptimal, vk::ClearColorValue{channels}, range);
|
||||
cache.MarkGpuWritten(binding.image_id);
|
||||
};
|
||||
clear({8.f, 4.f, 2.f, 1.f});
|
||||
Require(name, "10_11_11 guest download",
|
||||
TextureCacheTestAccess::TryDownload(cache, binding.image_id),
|
||||
"packed-float native contents could not be downloaded");
|
||||
scheduler.Finish();
|
||||
scheduler.DrainPriorityOperations();
|
||||
std::array<u32, 4> guest{};
|
||||
for (u32 pixel = 0; pixel < words.size(); ++pixel) {
|
||||
Require(name, "10_11_11 guest texel",
|
||||
Libs::LibKernel::Memory::TryReadBacking(base + offsets[pixel],
|
||||
&guest[pixel], sizeof(u32)),
|
||||
"packed-float guest texel is inaccessible");
|
||||
}
|
||||
Require(name, "10_11_11 exact guest words",
|
||||
guest == std::array<u32, 4>{0x90110200u, 0x90110200u, 0x90110200u, 0x90110200u},
|
||||
"native packed-float write lost the guest 10/11/11 bit layout");
|
||||
|
||||
clear({16.f, 8.f, 4.f, 1.f});
|
||||
auto alias_desc = binding.desc;
|
||||
alias_desc.info.guest_format = Prospero::BufferFormat::k11_11_10Float;
|
||||
alias_desc.view_info.mapping = {};
|
||||
Require(name, "same-format transform compatibility",
|
||||
!alias_desc.info.IsCompatible(binding.desc.info),
|
||||
"equal Vulkan formats hid incompatible guest color transforms");
|
||||
const auto alias = cache.FindImage(alias_desc);
|
||||
(void)cache.FindTexture(alias, alias_desc);
|
||||
Require(name, "same-format transformed alias",
|
||||
alias != binding.image_id &&
|
||||
ReadCachedTexel(name, context, alias, {}, {4, 1, 1}) ==
|
||||
std::vector<u32>(4, 0x98120220u),
|
||||
"packed-float alias reused a transformed image or bypassed guest bytes");
|
||||
RenderExecutorTestAccess::ResetBindings(executor);
|
||||
context.UnmapMemory(base, allocation_size);
|
||||
scheduler.Finish();
|
||||
}
|
||||
Require(name, "release",
|
||||
Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0 &&
|
||||
Libs::LibKernel::Memory::KernelReleaseDirectMemory(
|
||||
|
|
@ -15980,13 +16124,16 @@ public:
|
|||
};
|
||||
// Keep all four conversions in flight to check growth, overwrite ordering,
|
||||
// the requested span on reuse, and two simultaneously live workspaces.
|
||||
const auto first = tile_manager.SwapBgra16({scratch_input.buffer, 0, 8});
|
||||
const auto first = tile_manager.TransformColor(
|
||||
{scratch_input.buffer, 0, 8}, ColorTransform::SwapBgra16, true);
|
||||
copy_scratch(first, 0);
|
||||
const auto grown = tile_manager.SwapBgra16({scratch_input.buffer, 0, 32});
|
||||
const auto grown = tile_manager.TransformColor(
|
||||
{scratch_input.buffer, 0, 32}, ColorTransform::SwapBgra16, true);
|
||||
copy_scratch(grown, 8);
|
||||
const auto reused = tile_manager.SwapBgra16({scratch_input.buffer, 8, 8});
|
||||
const auto reused = tile_manager.TransformColor(
|
||||
{scratch_input.buffer, 8, 8}, ColorTransform::SwapBgra16, true);
|
||||
copy_scratch(reused, 40);
|
||||
const auto paired = tile_manager.SwapBgra16(reused);
|
||||
const auto paired = tile_manager.TransformColor(reused, ColorTransform::SwapBgra16, true);
|
||||
copy_scratch(paired, 48);
|
||||
Require(name, "scratch workspace reuse",
|
||||
first.buffer != grown.buffer && grown.buffer == reused.buffer &&
|
||||
|
|
@ -35223,7 +35370,9 @@ void CheckImageTransitionState(RenderContext &renderer) {
|
|||
buffered_upload_offset, buffered_expected.size());
|
||||
Buffer copy_scratch(context, scheduler, MemoryUsage::DeviceLocal, 0, AllFlags,
|
||||
16);
|
||||
buffered_destination.CopyImageWithBuffer(buffered_source, copy_scratch);
|
||||
StreamBuffer copy_parameters(context, scheduler, MemoryUsage::Stream, 4096);
|
||||
TileManager copy_tiler(context, scheduler, copy_parameters);
|
||||
buffered_destination.CopyImageWithBuffer(buffered_source, copy_scratch, copy_tiler);
|
||||
const auto [buffered_download_data, buffered_download_offset] =
|
||||
download.Map(buffered_expected.size(), 4);
|
||||
Require(name, "buffered-copy download map", buffered_download_data != nullptr,
|
||||
|
|
@ -38898,6 +39047,7 @@ int main(int argc, char **argv) {
|
|||
if (argc == 2 && std::strcmp(argv[1], "--packed-texture-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
vulkan.CheckPackedTextureComponents();
|
||||
vulkan.CheckBgra16Readback();
|
||||
RunCase(&vulkan, ImageLoadPackedUintUnpacksAndSwizzles());
|
||||
RunCase(&vulkan, ImageSamplePackedUintConvertsSampleAndGather());
|
||||
return 0;
|
||||
|
|
@ -39374,6 +39524,11 @@ int main(int argc, char **argv) {
|
|||
vulkan.CheckRenderExecutorColor1DArrayDiscovery();
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--image-transition-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckImageTransitionState(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
if (argc == 2 && std::strcmp(argv[1], "--reverse-rt-death") == 0) {
|
||||
RunReverseRenderTargetDeathCase();
|
||||
|
|
@ -39396,11 +39551,6 @@ int main(int argc, char **argv) {
|
|||
CheckSampledColorViews();
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--image-transition-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckImageTransitionState(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--storage-bgra-only") == 0) {
|
||||
CheckSampledColorViews();
|
||||
CheckBasicStorageTextureDescriptor();
|
||||
|
|
|
|||
Loading…
Reference in New Issue