[Vulkan] Generalize texture conversion, and fix cube textures in the process.
This commit is contained in:
parent
1def8cfc59
commit
9231317eeb
|
@ -17,6 +17,7 @@
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/base/memory.h"
|
#include "xenia/base/memory.h"
|
||||||
|
#include "xenia/base/profiling.h"
|
||||||
|
|
||||||
#include "third_party/xxhash/xxhash.h"
|
#include "third_party/xxhash/xxhash.h"
|
||||||
|
|
||||||
|
@ -108,6 +109,7 @@ static uint32_t TiledOffset2DInner(uint32_t x, uint32_t y, uint32_t log2_bpp,
|
||||||
|
|
||||||
void Untile(uint8_t* output_buffer, const uint8_t* input_buffer,
|
void Untile(uint8_t* output_buffer, const uint8_t* input_buffer,
|
||||||
const UntileInfo* untile_info) {
|
const UntileInfo* untile_info) {
|
||||||
|
SCOPE_profile_cpu_f("gpu");
|
||||||
assert_not_null(untile_info);
|
assert_not_null(untile_info);
|
||||||
assert_not_null(untile_info->input_format_info);
|
assert_not_null(untile_info->input_format_info);
|
||||||
assert_not_null(untile_info->output_format_info);
|
assert_not_null(untile_info->output_format_info);
|
||||||
|
|
|
@ -919,66 +919,11 @@ void TextureCache::FlushPendingCommands(VkCommandBuffer command_buffer,
|
||||||
vkBeginCommandBuffer(command_buffer, &begin_info);
|
vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::ConvertTexture2D(uint8_t* dest,
|
bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
|
||||||
VkBufferImageCopy* copy_region,
|
uint32_t mip, const TextureInfo& src) {
|
||||||
uint32_t mip, const TextureInfo& src) {
|
#if FINE_GRAINED_DRAW_SCOPES
|
||||||
uint32_t offset_x = 0;
|
SCOPE_profile_cpu_f("gpu");
|
||||||
uint32_t offset_y = 0;
|
#endif // FINE_GRAINED_DRAW_SCOPES
|
||||||
uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true);
|
|
||||||
void* host_address = memory_->TranslatePhysical(address);
|
|
||||||
|
|
||||||
auto src_usage = src.GetMipMemoryUsage(mip, true);
|
|
||||||
auto dst_usage = GetMipMemoryUsage(src, mip);
|
|
||||||
|
|
||||||
uint32_t mip_width, mip_height;
|
|
||||||
src.GetMipSize(mip, &mip_width, &mip_height);
|
|
||||||
|
|
||||||
auto copy_block = GetFormatCopyBlock(src.format);
|
|
||||||
|
|
||||||
if (!src.is_tiled) {
|
|
||||||
uint32_t src_pitch =
|
|
||||||
src_usage.block_pitch * src.format_info()->bytes_per_block();
|
|
||||||
uint32_t dst_pitch =
|
|
||||||
dst_usage.block_pitch * GetFormatInfo(src.format)->bytes_per_block();
|
|
||||||
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
|
|
||||||
src_mem += offset_y * src_pitch;
|
|
||||||
src_mem += offset_x * src.format_info()->bytes_per_block();
|
|
||||||
for (uint32_t y = 0; y < dst_usage.block_height; y++) {
|
|
||||||
copy_block(src.endianness, dest + y * dst_pitch, src_mem + y * src_pitch,
|
|
||||||
dst_pitch);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Untile image.
|
|
||||||
// We could do this in a shader to speed things up, as this is pretty slow.
|
|
||||||
|
|
||||||
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
|
|
||||||
|
|
||||||
texture_conversion::UntileInfo untile_info;
|
|
||||||
std::memset(&untile_info, 0, sizeof(untile_info));
|
|
||||||
untile_info.offset_x = offset_x;
|
|
||||||
untile_info.offset_y = offset_y;
|
|
||||||
untile_info.width = dst_usage.block_pitch;
|
|
||||||
untile_info.height = dst_usage.block_height;
|
|
||||||
untile_info.input_pitch = src_usage.block_pitch;
|
|
||||||
untile_info.output_pitch = dst_usage.block_pitch;
|
|
||||||
untile_info.input_format_info = src.format_info();
|
|
||||||
untile_info.output_format_info = GetFormatInfo(src.format);
|
|
||||||
untile_info.copy_callback = [=](auto o, auto i, auto l) {
|
|
||||||
copy_block(src.endianness, o, i, l);
|
|
||||||
};
|
|
||||||
texture_conversion::Untile(dest, src_mem, &untile_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_region->bufferRowLength = dst_usage.pitch;
|
|
||||||
copy_region->bufferImageHeight = dst_usage.height;
|
|
||||||
copy_region->imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, mip, 0, 1};
|
|
||||||
copy_region->imageExtent = {mip_width, mip_height, 1};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureCache::ConvertTextureCube(uint8_t* dest,
|
|
||||||
VkBufferImageCopy* copy_region,
|
|
||||||
uint32_t mip, const TextureInfo& src) {
|
|
||||||
uint32_t offset_x = 0;
|
uint32_t offset_x = 0;
|
||||||
uint32_t offset_y = 0;
|
uint32_t offset_y = 0;
|
||||||
uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true);
|
uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true);
|
||||||
|
@ -997,9 +942,9 @@ bool TextureCache::ConvertTextureCube(uint8_t* dest,
|
||||||
|
|
||||||
auto copy_block = GetFormatCopyBlock(src.format);
|
auto copy_block = GetFormatCopyBlock(src.format);
|
||||||
|
|
||||||
|
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
|
||||||
if (!src.is_tiled) {
|
if (!src.is_tiled) {
|
||||||
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
|
for (uint32_t face = 0; face < dst_usage.depth; face++) {
|
||||||
for (int face = 0; face < 6; face++) {
|
|
||||||
src_mem += offset_y * src_pitch;
|
src_mem += offset_y * src_pitch;
|
||||||
src_mem += offset_x * src.format_info()->bytes_per_block();
|
src_mem += offset_x * src.format_info()->bytes_per_block();
|
||||||
for (uint32_t y = 0; y < dst_usage.block_height; y++) {
|
for (uint32_t y = 0; y < dst_usage.block_height; y++) {
|
||||||
|
@ -1010,8 +955,9 @@ bool TextureCache::ConvertTextureCube(uint8_t* dest,
|
||||||
dest += dst_pitch * dst_usage.block_height;
|
dest += dst_pitch * dst_usage.block_height;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
|
// Untile image.
|
||||||
for (int face = 0; face < 6; face++) {
|
// We could do this in a shader to speed things up, as this is pretty slow.
|
||||||
|
for (uint32_t face = 0; face < dst_usage.depth; face++) {
|
||||||
texture_conversion::UntileInfo untile_info;
|
texture_conversion::UntileInfo untile_info;
|
||||||
std::memset(&untile_info, 0, sizeof(untile_info));
|
std::memset(&untile_info, 0, sizeof(untile_info));
|
||||||
untile_info.offset_x = offset_x;
|
untile_info.offset_x = offset_x;
|
||||||
|
@ -1025,7 +971,7 @@ bool TextureCache::ConvertTextureCube(uint8_t* dest,
|
||||||
untile_info.copy_callback = [=](auto o, auto i, auto l) {
|
untile_info.copy_callback = [=](auto o, auto i, auto l) {
|
||||||
copy_block(src.endianness, o, i, l);
|
copy_block(src.endianness, o, i, l);
|
||||||
};
|
};
|
||||||
|
texture_conversion::Untile(dest, src_mem, &untile_info);
|
||||||
src_mem += src_pitch * src_usage.block_height;
|
src_mem += src_pitch * src_usage.block_height;
|
||||||
dest += dst_pitch * dst_usage.block_height;
|
dest += dst_pitch * dst_usage.block_height;
|
||||||
}
|
}
|
||||||
|
@ -1033,28 +979,12 @@ bool TextureCache::ConvertTextureCube(uint8_t* dest,
|
||||||
|
|
||||||
copy_region->bufferRowLength = dst_usage.pitch;
|
copy_region->bufferRowLength = dst_usage.pitch;
|
||||||
copy_region->bufferImageHeight = dst_usage.height;
|
copy_region->bufferImageHeight = dst_usage.height;
|
||||||
copy_region->imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, mip, 0, 6};
|
copy_region->imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, mip, 0,
|
||||||
|
dst_usage.depth};
|
||||||
copy_region->imageExtent = {mip_width, mip_height, 1};
|
copy_region->imageExtent = {mip_width, mip_height, 1};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
|
|
||||||
uint32_t mip, const TextureInfo& src) {
|
|
||||||
switch (src.dimension) {
|
|
||||||
case Dimension::k1D:
|
|
||||||
assert_always();
|
|
||||||
break;
|
|
||||||
case Dimension::k2D:
|
|
||||||
return ConvertTexture2D(dest, copy_region, mip, src);
|
|
||||||
case Dimension::k3D:
|
|
||||||
assert_always();
|
|
||||||
break;
|
|
||||||
case Dimension::kCube:
|
|
||||||
return ConvertTextureCube(dest, copy_region, mip, src);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
|
bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
|
||||||
VkFence completion_fence, Texture* dest,
|
VkFence completion_fence, Texture* dest,
|
||||||
const TextureInfo& src) {
|
const TextureInfo& src) {
|
||||||
|
|
|
@ -150,10 +150,6 @@ class TextureCache {
|
||||||
void FlushPendingCommands(VkCommandBuffer command_buffer,
|
void FlushPendingCommands(VkCommandBuffer command_buffer,
|
||||||
VkFence completion_fence);
|
VkFence completion_fence);
|
||||||
|
|
||||||
bool ConvertTexture2D(uint8_t* dest, VkBufferImageCopy* copy_region,
|
|
||||||
uint32_t mip, const TextureInfo& src);
|
|
||||||
bool ConvertTextureCube(uint8_t* dest, VkBufferImageCopy* copy_regions,
|
|
||||||
uint32_t mip, const TextureInfo& src);
|
|
||||||
bool ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
|
bool ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
|
||||||
uint32_t mip, const TextureInfo& src);
|
uint32_t mip, const TextureInfo& src);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue