mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
Add GPU tilers/tests
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "common/profiler.h"
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/guest_gpu/tile.h"
|
||||
#include "graphics/host_gpu/gpuTiler.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/objects/textureCommon.h"
|
||||
#include "graphics/host_gpu/regionDefinitions.h"
|
||||
@@ -191,36 +192,39 @@ void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* ima
|
||||
const auto format = RenderTargetTransferFormat(info.bytes_per_element);
|
||||
auto layout = TextureCalcUploadLayout(format, info.width, info.height, info.levels,
|
||||
layer_count, info.pitch, info.tile_mode, upload_size,
|
||||
false, false, false, "TextureCache render target");
|
||||
false, false, "TextureCache render target");
|
||||
const bool render_target_tiled =
|
||||
info.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
|
||||
if (!standard64 && ((render_target_tiled && !layout.fmt_tiled_render_target) ||
|
||||
layout.pitch != info.pitch)) {
|
||||
if (!standard64 &&
|
||||
((render_target_tiled && layout.tile_family != TileBlockFamily::RenderTarget64KB) ||
|
||||
layout.pitch != info.pitch)) {
|
||||
EXIT("TextureCache: unsupported render-target mip upload layout, pitch=%u/%u tile=%u\n",
|
||||
info.pitch, layout.pitch, info.tile_mode);
|
||||
}
|
||||
auto regions = TextureBuildUploadRegions(
|
||||
layout, info.format, info.width, info.height, layer_count, info.levels, true, false,
|
||||
TextureUploadDestination::MipLevels, TextureUploadSliceLayout::MipChainPerSlice);
|
||||
auto regions = TextureBuildUploadRegions(layout, info.format, info.width, info.height,
|
||||
layer_count, info.levels, true, false,
|
||||
TextureUploadDestination::MipLevels);
|
||||
for (auto& region: regions) {
|
||||
region.dst_layer += base_layer;
|
||||
}
|
||||
const auto source_address = info.address + slice_size * base_layer;
|
||||
TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(source_address),
|
||||
upload_size, regions, layout, format, info.width, info.height,
|
||||
layer_count, info.levels,
|
||||
TextureUploadSliceLayout::MipChainPerSlice,
|
||||
"TextureCache render target", vk::ImageLayout::eGeneral);
|
||||
layer_count, info.levels, "TextureCache render target",
|
||||
vk::ImageLayout::eGeneral);
|
||||
return;
|
||||
}
|
||||
if (info.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||
Transfer::GuestBufferIsTiled(info.address, slice_size)) {
|
||||
Transfer::ScratchBuffer scratch(slice_size);
|
||||
TileConvertTiledToLinearRenderTarget(
|
||||
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
|
||||
info.pitch, info.bytes_per_element, slice_size);
|
||||
Transfer::UploadImage(ctx, image, scratch.Data(), slice_size, info.pitch,
|
||||
vk::ImageLayout::eGeneral);
|
||||
const auto format = RenderTargetTransferFormat(info.bytes_per_element);
|
||||
auto layout = TextureCalcUploadLayout(format, info.width, info.height, 1, 1, info.pitch,
|
||||
info.tile_mode, slice_size, false, false,
|
||||
"TextureCache render target");
|
||||
auto regions = TextureBuildUploadRegions(layout, info.format, info.width, info.height, 1, 1,
|
||||
true, false, TextureUploadDestination::MipLevels);
|
||||
TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(info.address), slice_size,
|
||||
regions, layout, format, info.width, info.height, 1, 1,
|
||||
"TextureCache render target", vk::ImageLayout::eGeneral);
|
||||
} else {
|
||||
Transfer::UploadImage(ctx, image, reinterpret_cast<const void*>(info.address), slice_size,
|
||||
info.pitch, vk::ImageLayout::eGeneral);
|
||||
@@ -383,20 +387,46 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
|
||||
Transfer::WaitForGraphicsIdle(ctx);
|
||||
}
|
||||
image->layout = vk::ImageLayout::eUndefined;
|
||||
Transfer::ScratchBuffer scratch(info.size);
|
||||
TileConvertTiledToLinearRenderTarget(
|
||||
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
|
||||
info.pitch, info.bytes_per_element, info.size);
|
||||
if (info.bgra16) {
|
||||
auto* pixels = static_cast<uint16_t*>(scratch.Data());
|
||||
for (uint64_t i = 0; i < info.size / sizeof(uint16_t); i += 4) {
|
||||
std::swap(pixels[i], pixels[i + 2]);
|
||||
}
|
||||
if (!info.bgra16) {
|
||||
auto layout =
|
||||
TextureCalcUploadLayout(info.guest_format, info.width, info.height, 1, 1, info.pitch,
|
||||
info.tile_mode, info.size, false, false, "VideoOut");
|
||||
auto regions = TextureBuildUploadRegions(layout, info.format, info.width, info.height, 1, 1,
|
||||
false, false, TextureUploadDestination::MipLevels);
|
||||
TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(info.address), info.size,
|
||||
regions, layout, info.guest_format, info.width, info.height, 1, 1,
|
||||
"VideoOut", vk::ImageLayout::eGeneral);
|
||||
return;
|
||||
}
|
||||
Transfer::ScratchBuffer scratch(info.size);
|
||||
TileBlockLayout block {};
|
||||
EXIT_NOT_IMPLEMENTED(
|
||||
!TileGetBlockLayout(TileBlockFamily::RenderTarget64KB, info.bytes_per_element, &block));
|
||||
const GpuTileInfo tile_info {block.family,
|
||||
block.bytes_per_element,
|
||||
0,
|
||||
info.size,
|
||||
0,
|
||||
info.size,
|
||||
0,
|
||||
info.width,
|
||||
info.height,
|
||||
1,
|
||||
info.pitch};
|
||||
GpuDetile(ctx, reinterpret_cast<const void*>(info.address), scratch.Data(), info.size,
|
||||
info.size, std::span<const GpuTileInfo>(&tile_info, 1));
|
||||
SwapVideoOutBgra16(scratch.Data(), info.size);
|
||||
Transfer::UploadImage(ctx, image, scratch.Data(), info.size, info.pitch,
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
|
||||
void SwapVideoOutBgra16(void* data, uint64_t size) {
|
||||
auto* pixels = static_cast<uint16_t*>(data);
|
||||
for (uint64_t i = 0; i < size / sizeof(uint16_t); i += 4) {
|
||||
std::swap(pixels[i], pixels[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d,
|
||||
bool storage) {
|
||||
auto* image = storage ? static_cast<GpuTextureVulkanImage*>(new StorageTextureVulkanImage)
|
||||
|
||||
@@ -119,6 +119,7 @@ void UploadRenderTarget(GraphicContext* ctx, RenderTextureVulkanImage* image,
|
||||
|
||||
void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info);
|
||||
[[nodiscard]] VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info);
|
||||
void SwapVideoOutBgra16(void* data, uint64_t size);
|
||||
void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const VideoOutInfo& info,
|
||||
bool refresh);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "graphics/guest_gpu/gpu_format.h"
|
||||
#include "graphics/guest_gpu/graphicsRun.h"
|
||||
#include "graphics/guest_gpu/tile.h"
|
||||
#include "graphics/host_gpu/gpuTiler.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/objects/label.h"
|
||||
#include "graphics/host_gpu/objects/textureCommon.h"
|
||||
@@ -587,7 +588,6 @@ struct TextureCache::ReadbackWorker {
|
||||
cached.image->extent.height, info.width, info.height, meta_overlap,
|
||||
buffer_overlap);
|
||||
}
|
||||
download.resize(transfer_size);
|
||||
auto regions = Transfer::MakeLayeredImageBufferCopies(info.layers, depth_slice_size,
|
||||
info.pitch, info.width, info.height,
|
||||
vk::ImageAspectFlagBits::eDepth);
|
||||
@@ -600,17 +600,55 @@ struct TextureCache::ReadbackWorker {
|
||||
}
|
||||
regions.insert(regions.end(), stencil_regions.begin(), stencil_regions.end());
|
||||
}
|
||||
Transfer::DownloadImage(cached.ctx, download.data(), transfer_size, regions, cached.image,
|
||||
cached.image->layout);
|
||||
guest.resize(info.size);
|
||||
cache.m_tiler.TileImage(guest.data(), download.data(), info);
|
||||
std::vector<GpuTileInfo> gpu_infos;
|
||||
TileBlockLayout depth_block {};
|
||||
TileBlockLayout stencil_block {};
|
||||
EXIT_NOT_IMPLEMENTED(
|
||||
!TileGetBlockLayout(TileBlockFamily::Depth64KB, info.bytes_per_element, &depth_block) ||
|
||||
(has_stencil && !TileGetBlockLayout(TileBlockFamily::Depth64KB, 1, &stencil_block)));
|
||||
gpu_infos.reserve(regions.size());
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
const uint64_t offset = depth_slice_size * layer;
|
||||
GpuTileInfo tile {depth_block.family,
|
||||
depth_block.bytes_per_element,
|
||||
offset,
|
||||
depth_slice_size,
|
||||
offset,
|
||||
depth_slice_size,
|
||||
0,
|
||||
info.width,
|
||||
info.height,
|
||||
1,
|
||||
info.pitch};
|
||||
tile.surface_z = layer;
|
||||
gpu_infos.push_back(tile);
|
||||
}
|
||||
if (has_stencil) {
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
const uint64_t offset = info.size + stencil_slice_size * layer;
|
||||
GpuTileInfo tile {stencil_block.family,
|
||||
stencil_block.bytes_per_element,
|
||||
offset,
|
||||
stencil_slice_size,
|
||||
offset,
|
||||
stencil_slice_size,
|
||||
0,
|
||||
info.width,
|
||||
info.height,
|
||||
1,
|
||||
expected_stencil_pitch};
|
||||
tile.surface_z = layer;
|
||||
gpu_infos.push_back(tile);
|
||||
}
|
||||
}
|
||||
guest.resize(transfer_size);
|
||||
Transfer::DownloadTiledImage(cached.ctx, guest.data(), transfer_size, transfer_size,
|
||||
gpu_infos, regions, cached.image, cached.image->layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, guest.data(), info.size);
|
||||
ReadbackTransfer transfer;
|
||||
transfer.Add(info.address, info.size);
|
||||
if (has_stencil) {
|
||||
guest.resize(info.stencil_size);
|
||||
cache.m_tiler.TileStencil(guest.data(), download.data() + info.size, info);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.stencil_address, guest.data(),
|
||||
Libs::LibKernel::Memory::WriteBacking(info.stencil_address, guest.data() + info.size,
|
||||
info.stencil_size);
|
||||
transfer.Add(info.stencil_address, info.stencil_size);
|
||||
}
|
||||
@@ -672,66 +710,48 @@ struct TextureCache::ReadbackWorker {
|
||||
info.address, info.size, meta_overlap, buffer_overlap,
|
||||
static_cast<uint32_t>(cached.kind));
|
||||
}
|
||||
download.resize(info.size);
|
||||
std::fill(download.begin(), download.end(), 0);
|
||||
std::vector<ImageBufferCopy> regions;
|
||||
if (target_mip_chain) {
|
||||
const auto format = ImageOps::RenderTargetTransferFormat(info.bytes_per_element);
|
||||
auto layout = TextureCalcUploadLayout(format, info.width, info.height, info.levels, 1,
|
||||
info.pitch, info.tile_mode, info.size, false,
|
||||
false, false, "RenderTargetReadback");
|
||||
if (!layout.fmt_tiled_render_target || layout.pitch != info.pitch) {
|
||||
std::vector<BufferImageCopy> tiled_regions;
|
||||
TextureUploadLayout tiled_layout {};
|
||||
const bool gpu_tiled = tiled_target || tiled_storage;
|
||||
if (gpu_tiled) {
|
||||
const auto format = storage
|
||||
? cached.info.format
|
||||
: ImageOps::RenderTargetTransferFormat(info.bytes_per_element);
|
||||
tiled_layout = TextureCalcUploadLayout(format, info.width, info.height, info.levels,
|
||||
layers, info.pitch, info.tile_mode, info.size,
|
||||
false, false, "RenderTargetReadback");
|
||||
if (target_mip_chain &&
|
||||
(tiled_layout.tile_family != TileBlockFamily::RenderTarget64KB ||
|
||||
tiled_layout.pitch != info.pitch)) {
|
||||
EXIT("TextureCache: inconsistent render-target readback layout, addr=0x%016" PRIx64
|
||||
" size=0x%016" PRIx64 " pitch=%u/%u levels=%u\n",
|
||||
info.address, info.size, info.pitch, layout.pitch, info.levels);
|
||||
}
|
||||
const auto uploads = TextureBuildUploadRegions(
|
||||
layout, info.format, info.width, info.height, 1, info.levels, true, false,
|
||||
TextureUploadDestination::MipLevels, TextureUploadSliceLayout::MipChainPerSlice);
|
||||
regions.reserve(uploads.size());
|
||||
for (const auto& upload: uploads) {
|
||||
regions.push_back({upload.offset, upload.pitch, upload.dst_level, upload.width,
|
||||
upload.height, upload.copy_height, upload.dst_layer,
|
||||
upload.dst_x, upload.dst_y, upload.dst_z, upload.aspect});
|
||||
info.address, info.size, info.pitch, tiled_layout.pitch, info.levels);
|
||||
}
|
||||
tiled_regions = TextureBuildUploadRegions(tiled_layout, info.format, info.width,
|
||||
info.height, layers, info.levels, layers > 1,
|
||||
false, TextureUploadDestination::MipLevels);
|
||||
regions = TextureBuildDownloadRegions(tiled_regions);
|
||||
} else {
|
||||
regions = Transfer::MakeLayeredImageBufferCopies(layers, slice_size, info.pitch,
|
||||
info.width, info.height);
|
||||
}
|
||||
Transfer::DownloadImage(cached.ctx, download.data(), info.size, regions, cached.image,
|
||||
cached.image->layout);
|
||||
if (target_mip_chain) {
|
||||
if (gpu_tiled) {
|
||||
std::vector<GpuTileInfo> infos;
|
||||
const auto format = storage
|
||||
? cached.info.format
|
||||
: ImageOps::RenderTargetTransferFormat(info.bytes_per_element);
|
||||
guest.resize(info.size);
|
||||
ImageInfo layout {};
|
||||
layout.address = info.address;
|
||||
layout.size = info.size;
|
||||
layout.format = ImageOps::RenderTargetTransferFormat(info.bytes_per_element);
|
||||
layout.width = info.width;
|
||||
layout.height = info.height;
|
||||
layout.pitch = info.pitch;
|
||||
layout.levels = info.levels;
|
||||
layout.view_levels = info.levels;
|
||||
layout.tile = info.tile_mode;
|
||||
layout.depth = 1;
|
||||
layout.type = Prospero::GpuEnumValue(Prospero::ImageType::kColor2D);
|
||||
cache.m_tiler.TileImage(guest.data(), download.data(), layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, guest.data(), info.size);
|
||||
} else if (tiled_target || tiled_storage) {
|
||||
guest.resize(info.size);
|
||||
const RenderTargetInfo layout =
|
||||
target ? cached.target : RenderTargetInfo {info.address,
|
||||
info.size,
|
||||
info.format,
|
||||
info.width,
|
||||
info.height,
|
||||
info.pitch,
|
||||
info.bytes_per_element,
|
||||
info.tile_mode,
|
||||
info.levels,
|
||||
1};
|
||||
cache.m_tiler.TileImage(guest.data(), download.data(), layout);
|
||||
EXIT_NOT_IMPLEMENTED(!TextureBuildGpuTileInfos(info.size, tiled_regions, tiled_layout,
|
||||
format, layers, info.levels, &infos));
|
||||
Transfer::DownloadTiledImage(cached.ctx, guest.data(), info.size, info.size, infos,
|
||||
regions, cached.image, cached.image->layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, guest.data(), info.size);
|
||||
} else {
|
||||
download.resize(info.size);
|
||||
std::fill(download.begin(), download.end(), 0);
|
||||
Transfer::DownloadImage(cached.ctx, download.data(), info.size, regions, cached.image,
|
||||
cached.image->layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, download.data(), info.size);
|
||||
}
|
||||
ReadbackTransfer transfer;
|
||||
@@ -1061,8 +1081,7 @@ bool Equal(const DepthTargetInfo& left, const DepthTargetInfo& right) {
|
||||
|
||||
[[nodiscard]] bool IsCoherentGuestImageSource(const BufferImageCopySource& source, uint64_t address,
|
||||
uint64_t size) {
|
||||
// The current PS5 Tiler consumes coherent guest backing directly. A native buffer is an
|
||||
// optional future GPU-detiler source or staging fallback.
|
||||
// The GPU tiler currently consumes coherent guest backing directly.
|
||||
return source.cpu_current && source.address == address && source.size == size &&
|
||||
(source.buffer != nullptr || source.offset == 0);
|
||||
}
|
||||
@@ -1384,8 +1403,7 @@ VulkanImage* TextureCache::FindTexture(CommandBuffer* command, GraphicContext* c
|
||||
}
|
||||
BufferImageCopySource source {nullptr, 0, info.address, info.size, true};
|
||||
if (m_buffer_cache.HasPageOverlap(info.address, info.size)) {
|
||||
// ObtainBufferForImage publishes dirty native-buffer bytes when necessary and otherwise
|
||||
// uses a CPU-current staging fallback through guest backing.
|
||||
// ObtainBufferForImage publishes dirty native-buffer bytes into coherent guest backing.
|
||||
source = m_buffer_cache.ObtainBufferForImage(info.address, info.size);
|
||||
if (!IsCoherentGuestImageSource(source, info.address, info.size)) {
|
||||
EXIT("TextureCache: sampled-image buffer source is inconsistent, addr=0x%016" PRIx64
|
||||
@@ -2963,6 +2981,7 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached, uint
|
||||
}
|
||||
const bool linear = target.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kLinear);
|
||||
const bool tiled = IsTiledRenderTarget(target);
|
||||
const bool bgra16 = video_out && cached.video_out.bgra16;
|
||||
TileSizeAlign exact {};
|
||||
bool single_slice = false;
|
||||
if (IsSupportedStandard64RenderTarget(target)) {
|
||||
@@ -3014,47 +3033,72 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached, uint
|
||||
target.address, target.size);
|
||||
}
|
||||
|
||||
// This is the CPU Tiler backend for the image-to-buffer synchronization seam.
|
||||
// The guest vector and Vulkan staging allocation retain capacity; a future PS5 GPU tiler can
|
||||
// replace this block without changing alias classification or ownership transitions.
|
||||
Transfer::WaitForGraphicsIdle(cached.ctx);
|
||||
std::vector<ImageBufferCopy> regions;
|
||||
std::vector<BufferImageCopy> tiled_regions;
|
||||
TextureUploadLayout tiled_layout {};
|
||||
uint32_t tiled_format = 0;
|
||||
if (storage) {
|
||||
auto layout = TextureCalcUploadLayout(
|
||||
const bool array_texture = TextureIsLayeredTexture(cached.info.type);
|
||||
const bool volume_texture = TextureIs3DTexture(cached.info.type);
|
||||
tiled_format = cached.info.format;
|
||||
tiled_layout = TextureCalcUploadLayout(
|
||||
cached.info.format, cached.info.width, cached.info.height, cached.info.levels,
|
||||
cached.info.depth, cached.info.pitch, cached.info.tile, cached.info.size, true, false,
|
||||
false, "StorageTextureReadback");
|
||||
auto uploads = TextureBuildUploadRegions(
|
||||
layout, cached.image->format, cached.info.width, cached.info.height, cached.info.depth,
|
||||
cached.info.levels, false, false, TextureUploadDestination::MipLevels,
|
||||
TextureUploadSliceLayout::MipChainPerSlice);
|
||||
regions.reserve(uploads.size());
|
||||
for (const auto& upload: uploads) {
|
||||
regions.push_back({upload.offset, upload.pitch, upload.dst_level, upload.width,
|
||||
upload.height, upload.copy_height, upload.dst_layer, upload.dst_x,
|
||||
upload.dst_y, upload.dst_z, upload.aspect});
|
||||
}
|
||||
cached.info.depth, cached.info.pitch, cached.info.tile, cached.info.size, true,
|
||||
volume_texture, "StorageTextureReadback");
|
||||
tiled_regions = TextureBuildUploadRegions(
|
||||
tiled_layout, cached.image->format, cached.info.width, cached.info.height,
|
||||
cached.info.depth, cached.info.levels, array_texture, volume_texture,
|
||||
TextureUploadDestination::MipLevels);
|
||||
regions = TextureBuildDownloadRegions(tiled_regions);
|
||||
} else if (tiled && !bgra16) {
|
||||
tiled_format = ImageOps::RenderTargetTransferFormat(target.bytes_per_element);
|
||||
tiled_layout = TextureCalcUploadLayout(
|
||||
tiled_format, target.width, target.height, target.levels, target.layers, target.pitch,
|
||||
target.tile_mode, target.size, false, false, "ColorBufferTransition");
|
||||
tiled_regions = TextureBuildUploadRegions(
|
||||
tiled_layout, target.format, target.width, target.height, target.layers, target.levels,
|
||||
target.layers > 1, false, TextureUploadDestination::MipLevels);
|
||||
regions = TextureBuildDownloadRegions(tiled_regions);
|
||||
} else {
|
||||
regions = Transfer::MakeLayeredImageBufferCopies(target.layers, slice_size, target.pitch,
|
||||
target.width, target.height);
|
||||
}
|
||||
Transfer::ProcessDownloadedImage(
|
||||
cached.ctx, target.size, regions, cached.image, cached.image->layout,
|
||||
[&](std::span<const uint8_t> linear) {
|
||||
if (storage) {
|
||||
m_buffer_transition_guest.resize(target.size);
|
||||
m_tiler.TileImage(m_buffer_transition_guest.data(), linear.data(), cached.info);
|
||||
Libs::LibKernel::Memory::WriteBacking(
|
||||
target.address, m_buffer_transition_guest.data(), target.size);
|
||||
} else if (tiled) {
|
||||
m_buffer_transition_guest.resize(target.size);
|
||||
m_tiler.TileImage(m_buffer_transition_guest.data(), linear.data(), target);
|
||||
Libs::LibKernel::Memory::WriteBacking(
|
||||
target.address, m_buffer_transition_guest.data(), target.size);
|
||||
} else {
|
||||
Libs::LibKernel::Memory::WriteBacking(target.address, linear.data(), target.size);
|
||||
}
|
||||
});
|
||||
if (tiled && !bgra16) {
|
||||
std::vector<GpuTileInfo> infos;
|
||||
const uint32_t depth = storage ? cached.info.depth : target.layers;
|
||||
EXIT_NOT_IMPLEMENTED(!TextureBuildGpuTileInfos(target.size, tiled_regions, tiled_layout,
|
||||
tiled_format, depth, target.levels, &infos));
|
||||
m_buffer_transition_guest.resize(target.size);
|
||||
Transfer::DownloadTiledImage(cached.ctx, m_buffer_transition_guest.data(), target.size,
|
||||
target.size, infos, regions, cached.image,
|
||||
cached.image->layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(target.address, m_buffer_transition_guest.data(),
|
||||
target.size);
|
||||
} else if (tiled) {
|
||||
std::vector<uint8_t> linear_data(target.size);
|
||||
Transfer::DownloadImage(cached.ctx, linear_data.data(), target.size, regions, cached.image,
|
||||
cached.image->layout);
|
||||
ImageOps::SwapVideoOutBgra16(linear_data.data(), target.size);
|
||||
TileBlockLayout block {};
|
||||
EXIT_NOT_IMPLEMENTED(!TileGetBlockLayout(TileBlockFamily::RenderTarget64KB,
|
||||
target.bytes_per_element, &block));
|
||||
const GpuTileInfo info {
|
||||
block.family, block.bytes_per_element, 0, target.size, 0, target.size, 0,
|
||||
target.width, target.height, 1, target.pitch};
|
||||
m_buffer_transition_guest.resize(target.size);
|
||||
GpuTile(cached.ctx, linear_data.data(), m_buffer_transition_guest.data(), target.size,
|
||||
target.size, std::span<const GpuTileInfo>(&info, 1));
|
||||
Libs::LibKernel::Memory::WriteBacking(target.address, m_buffer_transition_guest.data(),
|
||||
target.size);
|
||||
} else {
|
||||
Transfer::ProcessDownloadedImage(cached.ctx, target.size, regions, cached.image,
|
||||
cached.image->layout,
|
||||
[&](std::span<const uint8_t> linear_data) {
|
||||
Libs::LibKernel::Memory::WriteBacking(
|
||||
target.address, linear_data.data(), target.size);
|
||||
});
|
||||
}
|
||||
m_memory_tracker.ForEachDownloadRange<true>(target.address, target.size,
|
||||
[](uint64_t, uint64_t) noexcept {});
|
||||
// Only the impending buffer-write range needs publication into BufferCache ownership. The
|
||||
@@ -3103,14 +3147,26 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint
|
||||
Transfer::WaitForGraphicsIdle(cached.ctx);
|
||||
const auto regions = Transfer::MakeLayeredImageBufferCopies(
|
||||
1, info.size, info.pitch, info.width, info.height, vk::ImageAspectFlagBits::eDepth);
|
||||
Transfer::ProcessDownloadedImage(
|
||||
cached.ctx, info.size, regions, cached.image, cached.image->layout,
|
||||
[&](std::span<const uint8_t> linear) {
|
||||
m_buffer_transition_guest.resize(info.size);
|
||||
m_tiler.TileImage(m_buffer_transition_guest.data(), linear.data(), info);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, m_buffer_transition_guest.data(),
|
||||
info.size);
|
||||
});
|
||||
TileBlockLayout block {};
|
||||
EXIT_NOT_IMPLEMENTED(
|
||||
!TileGetBlockLayout(TileBlockFamily::Depth64KB, info.bytes_per_element, &block));
|
||||
const GpuTileInfo tile_info {block.family,
|
||||
block.bytes_per_element,
|
||||
0,
|
||||
info.size,
|
||||
0,
|
||||
info.size,
|
||||
0,
|
||||
info.width,
|
||||
info.height,
|
||||
1,
|
||||
info.pitch};
|
||||
m_buffer_transition_guest.resize(info.size);
|
||||
Transfer::DownloadTiledImage(cached.ctx, m_buffer_transition_guest.data(), info.size, info.size,
|
||||
std::span<const GpuTileInfo>(&tile_info, 1), regions, cached.image,
|
||||
cached.image->layout);
|
||||
Libs::LibKernel::Memory::WriteBacking(info.address, m_buffer_transition_guest.data(),
|
||||
info.size);
|
||||
m_memory_tracker.ForEachDownloadRange<true>(info.address, info.size,
|
||||
[](uint64_t, uint64_t) noexcept {});
|
||||
m_buffer_cache.PublishImageBacking(write_address, write_size);
|
||||
|
||||
@@ -4,86 +4,132 @@
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/guest_gpu/gpu_format.h"
|
||||
#include "graphics/guest_gpu/tile.h"
|
||||
#include "graphics/host_gpu/gpuTiler.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/objects/textureCommon.h"
|
||||
#include "graphics/host_gpu/renderer/image.h"
|
||||
#include "graphics/host_gpu/transfer.h"
|
||||
#include "graphics/host_gpu/vulkanCommon.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
namespace {
|
||||
|
||||
struct DepthTransfer {
|
||||
std::vector<GpuTileInfo> infos;
|
||||
std::vector<BufferImageCopy> regions;
|
||||
};
|
||||
|
||||
DepthTransfer MakeDepthTransfer(uint64_t size, uint32_t layers, uint32_t format,
|
||||
uint32_t bytes_per_element, uint32_t width, uint32_t height,
|
||||
uint32_t pitch, uint32_t base_layer, vk::ImageAspectFlags aspect) {
|
||||
EXIT_IF(size == 0 || layers == 0 || size % layers != 0);
|
||||
TileBlockLayout block {};
|
||||
EXIT_NOT_IMPLEMENTED(
|
||||
!TileGetBlockLayout(TileBlockFamily::Depth64KB, bytes_per_element, &block) ||
|
||||
Prospero::NumBytesPerElement(format) != bytes_per_element);
|
||||
|
||||
const uint64_t slice_size = size / layers;
|
||||
DepthTransfer transfer;
|
||||
transfer.infos.reserve(layers);
|
||||
transfer.regions.reserve(layers);
|
||||
for (uint32_t layer = 0; layer < layers; layer++) {
|
||||
const uint64_t offset = slice_size * layer;
|
||||
GpuTileInfo info {block.family,
|
||||
block.bytes_per_element,
|
||||
offset,
|
||||
slice_size,
|
||||
offset,
|
||||
slice_size,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
1,
|
||||
pitch};
|
||||
info.surface_z = base_layer + layer;
|
||||
transfer.infos.push_back(info);
|
||||
|
||||
BufferImageCopy region {};
|
||||
region.offset = static_cast<uint32_t>(offset);
|
||||
region.pitch = pitch;
|
||||
region.width = width;
|
||||
region.height = height;
|
||||
region.dst_layer = base_layer + layer;
|
||||
region.aspect = aspect;
|
||||
transfer.regions.push_back(region);
|
||||
}
|
||||
return transfer;
|
||||
}
|
||||
|
||||
void UploadDepth(GraphicContext* ctx, DepthStencilVulkanImage* image, uint64_t source_address,
|
||||
uint64_t size, uint32_t layers, uint32_t format, uint32_t bytes_per_element,
|
||||
uint32_t width, uint32_t height, uint32_t pitch, uint32_t base_layer,
|
||||
vk::ImageAspectFlags aspect) {
|
||||
auto transfer = MakeDepthTransfer(size, layers, format, bytes_per_element, width, height, pitch,
|
||||
base_layer, aspect);
|
||||
Transfer::UploadTiledImage(ctx, image, reinterpret_cast<const void*>(source_address), size,
|
||||
size, transfer.infos, transfer.regions,
|
||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
}
|
||||
|
||||
template <uint32_t (*Encode)(uint16_t)>
|
||||
static void UploadPromotedD16Depth(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
uint32_t base_layer) {
|
||||
const uint64_t slice_size = info.size / info.layers;
|
||||
void UploadPromotedD16Depth(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
uint32_t base_layer) {
|
||||
const uint64_t guest_slice_size = info.size / info.layers;
|
||||
const uint64_t texels = static_cast<uint64_t>(info.pitch) * info.height;
|
||||
const uint64_t host_slice_size = texels * sizeof(uint32_t);
|
||||
const uint64_t host_upload_size = host_slice_size * info.layers;
|
||||
if (host_upload_size > UINT32_MAX) {
|
||||
EXIT("Tiler: invalid D16 host-promotion footprint, guest_slice=0x%016" PRIx64
|
||||
" host_slice=0x%016" PRIx64 " layers=%u\n",
|
||||
slice_size, host_slice_size, info.layers);
|
||||
}
|
||||
Transfer::ScratchBuffer host_linear(host_upload_size);
|
||||
std::vector<uint16_t> guest_linear(slice_size / sizeof(uint16_t));
|
||||
std::vector<BufferImageCopy> regions;
|
||||
regions.reserve(info.layers);
|
||||
EXIT_IF(host_upload_size > UINT32_MAX);
|
||||
|
||||
auto transfer = MakeDepthTransfer(info.size, info.layers, info.guest_format,
|
||||
info.bytes_per_element, info.width, info.height, info.pitch,
|
||||
base_layer, vk::ImageAspectFlagBits::eDepth);
|
||||
std::vector<uint16_t> guest_linear(info.size / sizeof(uint16_t));
|
||||
GpuDetile(ctx, reinterpret_cast<const void*>(source.address), guest_linear.data(), info.size,
|
||||
info.size, transfer.infos);
|
||||
|
||||
Transfer::ScratchBuffer host_linear(host_upload_size);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
|
||||
TileConvertTiledToLinearDepth(guest_linear.data(), guest_slice, info.guest_format,
|
||||
info.width, info.height, info.pitch, slice_size);
|
||||
auto* host_slice = reinterpret_cast<uint32_t*>(static_cast<uint8_t*>(host_linear.Data()) +
|
||||
host_slice_size * layer);
|
||||
const auto* guest = guest_linear.data() + guest_slice_size / sizeof(uint16_t) * layer;
|
||||
auto* host = reinterpret_cast<uint32_t*>(static_cast<uint8_t*>(host_linear.Data()) +
|
||||
host_slice_size * layer);
|
||||
for (uint64_t texel = 0; texel < texels; texel++) {
|
||||
host_slice[texel] = Encode(guest_linear[texel]);
|
||||
host[texel] = Encode(guest[texel]);
|
||||
}
|
||||
BufferImageCopy region {};
|
||||
region.offset = static_cast<uint32_t>(host_slice_size * layer);
|
||||
region.pitch = info.pitch;
|
||||
region.width = info.width;
|
||||
region.height = info.height;
|
||||
region.dst_layer = base_layer + layer;
|
||||
region.aspect = vk::ImageAspectFlagBits::eDepth;
|
||||
regions.push_back(region);
|
||||
transfer.regions[layer].offset = static_cast<uint32_t>(host_slice_size * layer);
|
||||
}
|
||||
Transfer::UploadImage(ctx, image, host_linear.Data(), host_upload_size, regions,
|
||||
Transfer::UploadImage(ctx, image, host_linear.Data(), host_upload_size, transfer.regions,
|
||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
|
||||
const BufferImageCopySource& source, bool refresh, bool storage) const {
|
||||
if (refresh) {
|
||||
Transfer::WaitForGraphicsIdle(ctx);
|
||||
}
|
||||
if (refresh) Transfer::WaitForGraphicsIdle(ctx);
|
||||
|
||||
const bool array_texture = TextureIsLayeredTexture(info.type);
|
||||
const bool volume_texture = TextureIs3DTexture(info.type);
|
||||
auto layout = TextureCalcUploadLayout(
|
||||
info.format, info.width, info.height, info.levels, info.depth, info.pitch, info.tile,
|
||||
info.size, true, false, volume_texture, storage ? "StorageTextureCache" : "TextureCache");
|
||||
const auto slice_layout = TextureUploadSliceLayout::MipChainPerSlice;
|
||||
info.size, true, volume_texture, storage ? "StorageTextureCache" : "TextureCache");
|
||||
auto regions = TextureBuildUploadRegions(layout, image->format, info.width, info.height,
|
||||
info.depth, info.levels, array_texture, volume_texture,
|
||||
TextureUploadDestination::MipLevels, slice_layout);
|
||||
TextureUploadGuestImage(
|
||||
ctx, image, reinterpret_cast<const void*>(source.address), info.size, regions, layout,
|
||||
info.format, info.width, info.height, info.depth, info.levels, slice_layout,
|
||||
storage ? "StorageTextureCache" : "TextureCache",
|
||||
storage ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
TextureUploadDestination::MipLevels);
|
||||
TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(source.address), info.size,
|
||||
regions, layout, info.format, info.width, info.height, info.depth,
|
||||
info.levels, storage ? "StorageTextureCache" : "TextureCache",
|
||||
storage ? vk::ImageLayout::eGeneral
|
||||
: vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
}
|
||||
|
||||
void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
bool refresh, uint32_t base_layer) const {
|
||||
if (info.samples != 1 || image == nullptr || image->samples != 1) {
|
||||
EXIT("Tiler: multisampled depth upload is unsupported, samples=%u/%u\n", info.samples,
|
||||
image != nullptr ? image->samples : 0);
|
||||
}
|
||||
if (refresh) {
|
||||
Transfer::WaitForGraphicsIdle(ctx);
|
||||
}
|
||||
EXIT_NOT_IMPLEMENTED(info.samples != 1 || image->samples != 1);
|
||||
if (refresh) Transfer::WaitForGraphicsIdle(ctx);
|
||||
|
||||
if (DepthAspectTransferBytes(info.format) != info.bytes_per_element) {
|
||||
switch (info.format) {
|
||||
case vk::Format::eD24UnormS8Uint:
|
||||
@@ -92,165 +138,25 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
case vk::Format::eD32SfloatS8Uint:
|
||||
UploadPromotedD16Depth<EncodeD16AsD32>(ctx, image, info, source, base_layer);
|
||||
return;
|
||||
default:
|
||||
EXIT("Tiler: unsupported depth transfer conversion, format=%d guest_bpe=%u\n",
|
||||
static_cast<int>(info.format), info.bytes_per_element);
|
||||
default: EXIT_NOT_IMPLEMENTED(true);
|
||||
}
|
||||
}
|
||||
const auto slice_size = info.size / info.layers;
|
||||
Transfer::ScratchBuffer linear(info.size);
|
||||
std::vector<BufferImageCopy> regions;
|
||||
regions.reserve(info.layers);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* linear_slice = static_cast<uint8_t*>(linear.Data()) + slice_size * layer;
|
||||
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
|
||||
TileConvertTiledToLinearDepth(linear_slice, guest_slice, info.guest_format, info.width,
|
||||
info.height, info.pitch, slice_size);
|
||||
BufferImageCopy region {};
|
||||
region.offset = static_cast<uint32_t>(slice_size * layer);
|
||||
region.pitch = info.pitch;
|
||||
region.width = info.width;
|
||||
region.height = info.height;
|
||||
region.dst_layer = base_layer + layer;
|
||||
region.aspect = vk::ImageAspectFlagBits::eDepth;
|
||||
regions.push_back(region);
|
||||
}
|
||||
Transfer::UploadImage(ctx, image, linear.Data(), info.size, regions,
|
||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
UploadDepth(ctx, image, source.address, info.size, info.layers, info.guest_format,
|
||||
info.bytes_per_element, info.width, info.height, info.pitch, base_layer,
|
||||
vk::ImageAspectFlagBits::eDepth);
|
||||
}
|
||||
|
||||
void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
bool refresh, uint32_t base_layer) const {
|
||||
if (info.samples != 1 || image == nullptr || image->samples != 1) {
|
||||
EXIT("Tiler: multisampled stencil upload is unsupported, samples=%u/%u\n", info.samples,
|
||||
image != nullptr ? image->samples : 0);
|
||||
}
|
||||
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
|
||||
const auto stencil_pitch = TileGetTexturePitch(
|
||||
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
if (refresh) {
|
||||
Transfer::WaitForGraphicsIdle(ctx);
|
||||
}
|
||||
const auto slice_size = info.stencil_size / info.layers;
|
||||
Transfer::ScratchBuffer linear(info.stencil_size);
|
||||
std::vector<BufferImageCopy> regions;
|
||||
regions.reserve(info.layers);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* linear_slice = static_cast<uint8_t*>(linear.Data()) + slice_size * layer;
|
||||
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
|
||||
TileConvertTiledToLinearDepth(linear_slice, guest_slice, stencil_format, info.width,
|
||||
info.height, stencil_pitch, slice_size);
|
||||
BufferImageCopy region {};
|
||||
region.offset = static_cast<uint32_t>(slice_size * layer);
|
||||
region.pitch = stencil_pitch;
|
||||
region.width = info.width;
|
||||
region.height = info.height;
|
||||
region.dst_layer = base_layer + layer;
|
||||
region.aspect = vk::ImageAspectFlagBits::eStencil;
|
||||
regions.push_back(region);
|
||||
}
|
||||
Transfer::UploadImage(ctx, image, linear.Data(), info.stencil_size, regions,
|
||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
}
|
||||
EXIT_NOT_IMPLEMENTED(info.samples != 1 || image->samples != 1);
|
||||
if (refresh) Transfer::WaitForGraphicsIdle(ctx);
|
||||
|
||||
void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info) const {
|
||||
const bool standard64 = IsSupportedStandard64RenderTarget(info);
|
||||
if ((info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||
!standard64) ||
|
||||
info.levels != 1 || info.samples != 1) {
|
||||
EXIT("Tiler: unsupported render-target tile, dst=%p src=%p "
|
||||
"addr=0x%016" PRIx64 "+0x%016" PRIx64
|
||||
" extent=%ux%u pitch=%u levels=%u tile=%u bpe=%u\n",
|
||||
dst, src, info.address, info.size, info.width, info.height, info.pitch, info.levels,
|
||||
info.tile_mode, info.bytes_per_element);
|
||||
}
|
||||
const auto slice_size = info.size / info.layers;
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* guest_slice = static_cast<uint8_t*>(dst) + slice_size * layer;
|
||||
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
|
||||
if (standard64) {
|
||||
TileConvertLinearToTiledStandard64KB32(guest_slice, linear_slice, info.width,
|
||||
info.height, info.pitch, slice_size);
|
||||
} else {
|
||||
TileConvertLinearToTiledRenderTarget(guest_slice, linear_slice, info.width, info.height,
|
||||
info.pitch, info.bytes_per_element, slice_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tiler::TileImage(void* dst, const void* src, const ImageInfo& info) const {
|
||||
const bool image_2d =
|
||||
info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && info.depth == 1;
|
||||
const auto bytes_per_element = Prospero::RenderTargetBytesPerElement(info.format);
|
||||
if (!image_2d || info.levels == 0 || info.levels > 16 ||
|
||||
info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
|
||||
bytes_per_element == 0) {
|
||||
EXIT("Tiler: unsupported storage-texture tile, addr=0x%016" PRIx64 "+0x%016" PRIx64
|
||||
" extent=%ux%ux%u levels=%u tile=%u format=%u\n",
|
||||
info.address, info.size, info.width, info.height, info.depth, info.levels, info.tile,
|
||||
info.format);
|
||||
}
|
||||
auto layout = TextureCalcUploadLayout(info.format, info.width, info.height, info.levels,
|
||||
info.depth, info.pitch, info.tile, info.size, true, false,
|
||||
false, "StorageTextureReadback");
|
||||
auto regions = TextureBuildUploadRegions(
|
||||
layout, VulkanFormat(info.format), info.width, info.height, info.depth, info.levels, false,
|
||||
false, TextureUploadDestination::MipLevels, TextureUploadSliceLayout::MipChainPerSlice);
|
||||
std::memset(dst, 0, info.size);
|
||||
for (uint32_t level = 0; level < info.levels; level++) {
|
||||
const auto& level_size = layout.level_sizes[level];
|
||||
const auto guest_offset =
|
||||
level_size.src_size != 0 ? level_size.src_offset : level_size.offset;
|
||||
auto* guest = static_cast<uint8_t*>(dst) + guest_offset;
|
||||
const auto* linear = static_cast<const uint8_t*>(src) + regions[level].offset;
|
||||
TileConvertLinearToTiledRenderTarget(
|
||||
guest, linear, regions[level].width, regions[level].height, regions[level].pitch,
|
||||
bytes_per_element, level_size.size, level_size.src_size, level_size.x, level_size.y);
|
||||
}
|
||||
}
|
||||
|
||||
void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) const {
|
||||
if (info.samples != 1 || info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
|
||||
!IsSupportedDepthReadbackFormat(info)) {
|
||||
EXIT("Tiler: unsupported depth-target tile, dst=%p src=%p "
|
||||
"depth=0x%016" PRIx64 "+0x%016" PRIx64 " stencil=0x%016" PRIx64 "+0x%016" PRIx64
|
||||
" extent=%ux%u pitch=%u tile=%u format=%d guest_format=%u bpe=%u\n",
|
||||
dst, src, info.address, info.size, info.stencil_address, info.stencil_size, info.width,
|
||||
info.height, info.pitch, info.tile_mode, static_cast<int>(info.format),
|
||||
info.guest_format, info.bytes_per_element);
|
||||
}
|
||||
const auto slice_size = info.size / info.layers;
|
||||
std::memset(dst, 0, info.size);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* guest_slice = static_cast<uint8_t*>(dst) + slice_size * layer;
|
||||
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
|
||||
TileConvertLinearToTiledDepth(guest_slice, linear_slice, info.guest_format, info.width,
|
||||
info.height, info.pitch, slice_size);
|
||||
}
|
||||
}
|
||||
|
||||
void Tiler::TileStencil(void* dst, const void* src, const DepthTargetInfo& info) const {
|
||||
const auto format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
|
||||
const auto pitch = TileGetTexturePitch(format, info.width, 1,
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
|
||||
if (info.samples != 1 || info.stencil_address == 0 || info.stencil_size == 0 ||
|
||||
info.layers == 0 || info.stencil_size % info.layers != 0 ||
|
||||
!IsSupportedDepthReadbackFormat(info)) {
|
||||
EXIT("Tiler: unsupported stencil-target tile, dst=%p src=%p "
|
||||
"stencil=0x%016" PRIx64 "+0x%016" PRIx64
|
||||
" extent=%ux%u pitch=%u layers=%u format=%d compressed=%d\n",
|
||||
dst, src, info.stencil_address, info.stencil_size, info.width, info.height, pitch,
|
||||
info.layers, static_cast<int>(info.format), info.stencil_htile_compressed);
|
||||
}
|
||||
const auto slice_size = info.stencil_size / info.layers;
|
||||
std::memset(dst, 0, info.stencil_size);
|
||||
for (uint32_t layer = 0; layer < info.layers; layer++) {
|
||||
auto* guest_slice = static_cast<uint8_t*>(dst) + slice_size * layer;
|
||||
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
|
||||
TileConvertLinearToTiledDepth(guest_slice, linear_slice, format, info.width, info.height,
|
||||
pitch, slice_size);
|
||||
}
|
||||
UploadDepth(ctx, image, source.address, info.stencil_size, info.layers, format, 1, info.width,
|
||||
info.height, pitch, base_layer, vk::ImageAspectFlagBits::eStencil);
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
@@ -24,10 +24,6 @@ public:
|
||||
void DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
|
||||
const DepthTargetInfo& info, const BufferImageCopySource& source,
|
||||
bool refresh, uint32_t base_layer = 0) const;
|
||||
void TileImage(void* dst, const void* src, const RenderTargetInfo& info) const;
|
||||
void TileImage(void* dst, const void* src, const ImageInfo& info) const;
|
||||
void TileImage(void* dst, const void* src, const DepthTargetInfo& info) const;
|
||||
void TileStencil(void* dst, const void* src, const DepthTargetInfo& info) const;
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
Reference in New Issue
Block a user