[GPU] Track unaligned (visible) block width in texture info.
[Vulkan] Don't use power of two for mip width/height calculation for host textures. [Vulkan] Add more Vulkan error logging. [Vulkan/GPU] Rudimentary texture dumping.
This commit is contained in:
110
src/xenia/gpu/texture_dump.cc
Normal file
110
src/xenia/gpu/texture_dump.cc
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include "xenia/gpu/texture_info.h"
|
||||
|
||||
DEFINE_bool(texture_dump, false, "Dump textures to DDS");
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
void TextureDump(const TextureInfo& src, void* buffer, size_t length) {
|
||||
struct {
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t pitch_or_linear_size;
|
||||
uint32_t depth;
|
||||
uint32_t mip_levels;
|
||||
uint32_t reserved1[11];
|
||||
struct {
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t fourcc;
|
||||
uint32_t rgb_bit_count;
|
||||
uint32_t r_bit_mask;
|
||||
uint32_t g_bit_mask;
|
||||
uint32_t b_bit_mask;
|
||||
uint32_t a_bit_mask;
|
||||
} pixel_format;
|
||||
uint32_t caps[4];
|
||||
uint32_t reserved2;
|
||||
} dds_header;
|
||||
|
||||
std::memset(&dds_header, 0, sizeof(dds_header));
|
||||
dds_header.size = sizeof(dds_header);
|
||||
dds_header.flags = 1u | 2u | 4u | 0x1000u | 0x20000u;
|
||||
if (src.is_compressed()) {
|
||||
dds_header.flags |= 0x80000u;
|
||||
} else {
|
||||
dds_header.flags |= 0x8u;
|
||||
}
|
||||
dds_header.height = src.height + 1;
|
||||
dds_header.width = src.width + 1;
|
||||
dds_header.pitch_or_linear_size = src.GetMipExtent(0, false).block_pitch_h *
|
||||
src.format_info()->bytes_per_block();
|
||||
dds_header.mip_levels = src.mip_levels;
|
||||
|
||||
dds_header.pixel_format.size = sizeof(dds_header.pixel_format);
|
||||
switch (src.format) {
|
||||
case TextureFormat::k_DXT1: {
|
||||
dds_header.pixel_format.flags = 0x4u;
|
||||
dds_header.pixel_format.fourcc = '1TXD';
|
||||
break;
|
||||
}
|
||||
case TextureFormat::k_DXT2_3: {
|
||||
dds_header.pixel_format.flags = 0x4u;
|
||||
dds_header.pixel_format.fourcc = '3TXD';
|
||||
break;
|
||||
}
|
||||
case TextureFormat::k_DXT4_5: {
|
||||
dds_header.pixel_format.flags = 0x4u;
|
||||
dds_header.pixel_format.fourcc = '5TXD';
|
||||
break;
|
||||
}
|
||||
case TextureFormat::k_8_8_8_8: {
|
||||
dds_header.pixel_format.flags = 0x1u | 0x40u;
|
||||
dds_header.pixel_format.rgb_bit_count = 32;
|
||||
dds_header.pixel_format.r_bit_mask = 0x00FF0000u;
|
||||
dds_header.pixel_format.g_bit_mask = 0x0000FF00u;
|
||||
dds_header.pixel_format.b_bit_mask = 0x000000FFu;
|
||||
dds_header.pixel_format.a_bit_mask = 0xFF000000u;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert_unhandled_case(src.format);
|
||||
std::memset(&dds_header.pixel_format, 0xCD,
|
||||
sizeof(dds_header.pixel_format));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dds_header.caps[0] = 8u | 0x1000u;
|
||||
|
||||
static int dump_counter = 0;
|
||||
char path[256];
|
||||
sprintf(path, "texture_dumps\\%05d_%.8X_%.8X_%s.dds", dump_counter++,
|
||||
src.memory.base_address, src.memory.mip_address,
|
||||
src.format_info()->name);
|
||||
|
||||
FILE* handle = fopen(path, "wb");
|
||||
if (handle) {
|
||||
const uint32_t signature = ' SDD';
|
||||
fwrite(&signature, sizeof(signature), 1, handle);
|
||||
fwrite(&dds_header, sizeof(dds_header), 1, handle);
|
||||
fwrite(buffer, 1, length, handle);
|
||||
fclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
Reference in New Issue
Block a user