[D3D12] Fix mipmapped cubemaps and stacked textures
This commit is contained in:
parent
e4a7d1dc5e
commit
251f078baf
|
@ -1051,7 +1051,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
|
||||||
// resolve to 8bpp or 16bpp textures at very odd locations.
|
// resolve to 8bpp or 16bpp textures at very odd locations.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint32_t dest_size = texture_util::GetGuestMipStorageSize(
|
uint32_t dest_size = texture_util::GetGuestMipSliceStorageSize(
|
||||||
xe::align(dest_pitch, 32u), xe::align(dest_height, 32u), 1, true,
|
xe::align(dest_pitch, 32u), xe::align(dest_height, 32u), 1, true,
|
||||||
dest_format, nullptr);
|
dest_format, nullptr);
|
||||||
if (dest_info & (1 << 3)) {
|
if (dest_info & (1 << 3)) {
|
||||||
|
|
|
@ -846,7 +846,7 @@ bool TextureCache::TileResolvedTexture(
|
||||||
|
|
||||||
// Calculate the texture size for memory operations and ensure we can write to
|
// Calculate the texture size for memory operations and ensure we can write to
|
||||||
// the specified shared memory location.
|
// the specified shared memory location.
|
||||||
uint32_t texture_size = texture_util::GetGuestMipStorageSize(
|
uint32_t texture_size = texture_util::GetGuestMipSliceStorageSize(
|
||||||
texture_pitch, texture_height, 1, true, format, nullptr);
|
texture_pitch, texture_height, 1, true, format, nullptr);
|
||||||
if (texture_size == 0) {
|
if (texture_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1187,21 +1187,25 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
|
||||||
texture->state = state;
|
texture->state = state;
|
||||||
texture->mip_offsets[0] = 0;
|
texture->mip_offsets[0] = 0;
|
||||||
uint32_t width_blocks, height_blocks, depth_blocks;
|
uint32_t width_blocks, height_blocks, depth_blocks;
|
||||||
|
uint32_t array_size = key.dimension != Dimension::k3D ? key.depth : 1;
|
||||||
if (key.base_page != 0) {
|
if (key.base_page != 0) {
|
||||||
texture_util::GetGuestMipBlocks(key.dimension, key.width, key.height,
|
texture_util::GetGuestMipBlocks(key.dimension, key.width, key.height,
|
||||||
key.depth, key.format, 0, width_blocks,
|
key.depth, key.format, 0, width_blocks,
|
||||||
height_blocks, depth_blocks);
|
height_blocks, depth_blocks);
|
||||||
texture->base_slice_size = texture_util::GetGuestMipStorageSize(
|
uint32_t slice_size = texture_util::GetGuestMipSliceStorageSize(
|
||||||
width_blocks, height_blocks, depth_blocks, key.tiled, key.format,
|
width_blocks, height_blocks, depth_blocks, key.tiled, key.format,
|
||||||
&texture->mip_pitches[0]);
|
&texture->pitches[0]);
|
||||||
|
texture->slice_sizes[0] = slice_size;
|
||||||
|
texture->base_size = slice_size * array_size;
|
||||||
texture->base_in_sync = false;
|
texture->base_in_sync = false;
|
||||||
} else {
|
} else {
|
||||||
texture->base_slice_size = 0;
|
texture->base_size = 0;
|
||||||
texture->mip_pitches[0] = 0;
|
texture->slice_sizes[0] = 0;
|
||||||
|
texture->pitches[0] = 0;
|
||||||
// Never try to upload the base level if there is none.
|
// Never try to upload the base level if there is none.
|
||||||
texture->base_in_sync = true;
|
texture->base_in_sync = true;
|
||||||
}
|
}
|
||||||
texture->mip_slice_size = 0;
|
texture->mip_size = 0;
|
||||||
if (key.mip_page != 0) {
|
if (key.mip_page != 0) {
|
||||||
uint32_t mip_max_storage_level = key.mip_max_level;
|
uint32_t mip_max_storage_level = key.mip_max_level;
|
||||||
if (key.packed_mips) {
|
if (key.packed_mips) {
|
||||||
|
@ -1213,32 +1217,31 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
|
||||||
texture_util::GetGuestMipBlocks(key.dimension, key.width, key.height,
|
texture_util::GetGuestMipBlocks(key.dimension, key.width, key.height,
|
||||||
key.depth, key.format, i, width_blocks,
|
key.depth, key.format, i, width_blocks,
|
||||||
height_blocks, depth_blocks);
|
height_blocks, depth_blocks);
|
||||||
texture->mip_offsets[i] = texture->mip_slice_size;
|
texture->mip_offsets[i] = texture->mip_size;
|
||||||
texture->mip_slice_size += texture_util::GetGuestMipStorageSize(
|
uint32_t slice_size = texture_util::GetGuestMipSliceStorageSize(
|
||||||
width_blocks, height_blocks, depth_blocks, key.tiled, key.format,
|
width_blocks, height_blocks, depth_blocks, key.tiled, key.format,
|
||||||
&texture->mip_pitches[i]);
|
&texture->pitches[i]);
|
||||||
|
texture->slice_sizes[i] = slice_size;
|
||||||
|
texture->mip_size += slice_size * array_size;
|
||||||
}
|
}
|
||||||
// The rest are either packed levels or don't exist at all.
|
// The rest are either packed levels or don't exist at all.
|
||||||
for (uint32_t i = mip_max_storage_level + 1;
|
for (uint32_t i = mip_max_storage_level + 1;
|
||||||
i < xe::countof(texture->mip_offsets); ++i) {
|
i < xe::countof(texture->mip_offsets); ++i) {
|
||||||
texture->mip_offsets[i] = texture->mip_offsets[mip_max_storage_level];
|
texture->mip_offsets[i] = texture->mip_offsets[mip_max_storage_level];
|
||||||
texture->mip_pitches[i] = texture->mip_pitches[mip_max_storage_level];
|
texture->slice_sizes[i] = texture->slice_sizes[mip_max_storage_level];
|
||||||
|
texture->pitches[i] = texture->pitches[mip_max_storage_level];
|
||||||
}
|
}
|
||||||
texture->mips_in_sync = false;
|
texture->mips_in_sync = false;
|
||||||
} else {
|
} else {
|
||||||
std::memset(&texture->mip_offsets[1], 0,
|
std::memset(&texture->mip_offsets[1], 0,
|
||||||
(xe::countof(texture->mip_offsets) - 1) * sizeof(uint32_t));
|
(xe::countof(texture->mip_offsets) - 1) * sizeof(uint32_t));
|
||||||
std::memset(&texture->mip_pitches[1], 0,
|
std::memset(&texture->slice_sizes[1], 0,
|
||||||
(xe::countof(texture->mip_pitches) - 1) * sizeof(uint32_t));
|
(xe::countof(texture->slice_sizes) - 1) * sizeof(uint32_t));
|
||||||
|
std::memset(&texture->pitches[1], 0,
|
||||||
|
(xe::countof(texture->pitches) - 1) * sizeof(uint32_t));
|
||||||
// Never try to upload the mipmaps if there are none.
|
// Never try to upload the mipmaps if there are none.
|
||||||
texture->mips_in_sync = true;
|
texture->mips_in_sync = true;
|
||||||
}
|
}
|
||||||
texture->base_size = texture->base_slice_size;
|
|
||||||
texture->mip_size = texture->mip_slice_size;
|
|
||||||
if (key.dimension != Dimension::k3D) {
|
|
||||||
texture->base_size *= key.depth;
|
|
||||||
texture->mip_size *= key.depth;
|
|
||||||
}
|
|
||||||
texture->base_watch_handle = nullptr;
|
texture->base_watch_handle = nullptr;
|
||||||
texture->mip_watch_handle = nullptr;
|
texture->mip_watch_handle = nullptr;
|
||||||
textures_.insert(std::make_pair(map_key, texture));
|
textures_.insert(std::make_pair(map_key, texture));
|
||||||
|
@ -1363,16 +1366,15 @@ bool TextureCache::LoadTextureData(Texture* texture) {
|
||||||
copy_buffer_state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
copy_buffer_state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||||
for (uint32_t j = mip_first; j <= mip_last; ++j) {
|
for (uint32_t j = mip_first; j <= mip_last; ++j) {
|
||||||
if (j == 0) {
|
if (j == 0) {
|
||||||
load_constants.guest_base =
|
load_constants.guest_base = texture->key.base_page << 12;
|
||||||
(texture->key.base_page << 12) + i * texture->base_slice_size;
|
|
||||||
} else {
|
} else {
|
||||||
load_constants.guest_base =
|
load_constants.guest_base = texture->key.mip_page << 12;
|
||||||
(texture->key.mip_page << 12) + i * texture->mip_slice_size;
|
|
||||||
}
|
}
|
||||||
load_constants.guest_base += texture->mip_offsets[j];
|
load_constants.guest_base +=
|
||||||
|
texture->mip_offsets[j] + i * texture->slice_sizes[j];
|
||||||
load_constants.guest_pitch = texture->key.tiled
|
load_constants.guest_pitch = texture->key.tiled
|
||||||
? LoadConstants::kGuestPitchTiled
|
? LoadConstants::kGuestPitchTiled
|
||||||
: texture->mip_pitches[j];
|
: texture->pitches[j];
|
||||||
load_constants.host_base = uint32_t(host_layouts[j].Offset);
|
load_constants.host_base = uint32_t(host_layouts[j].Offset);
|
||||||
load_constants.host_pitch = host_layouts[j].Footprint.RowPitch;
|
load_constants.host_pitch = host_layouts[j].Footprint.RowPitch;
|
||||||
load_constants.size_texels[0] = std::max(width >> j, 1u);
|
load_constants.size_texels[0] = std::max(width >> j, 1u);
|
||||||
|
|
|
@ -292,18 +292,19 @@ class TextureCache {
|
||||||
TextureKey key;
|
TextureKey key;
|
||||||
ID3D12Resource* resource;
|
ID3D12Resource* resource;
|
||||||
D3D12_RESOURCE_STATES state;
|
D3D12_RESOURCE_STATES state;
|
||||||
// Byte size of one array slice of the top guest mip level.
|
|
||||||
uint32_t base_slice_size;
|
|
||||||
// Byte size of the top guest mip level.
|
// Byte size of the top guest mip level.
|
||||||
uint32_t base_size;
|
uint32_t base_size;
|
||||||
// Byte size of one array slice of mips between 1 and key.mip_max_level.
|
// Byte size of mips between 1 and key.mip_max_level, containing all array
|
||||||
uint32_t mip_slice_size;
|
// slices.
|
||||||
// Byte size of mips between 1 and key.mip_max_level.
|
|
||||||
uint32_t mip_size;
|
uint32_t mip_size;
|
||||||
// Byte offsets of each mipmap within one slice.
|
// Offsets of all the array slices on a mip level relative to mips_address
|
||||||
|
// (0 for mip 0, it's relative to base_address then, and for mip 1).
|
||||||
uint32_t mip_offsets[14];
|
uint32_t mip_offsets[14];
|
||||||
// Byte pitches of each mipmap within one slice (for linear layout mainly).
|
// Byte sizes of an array slice on each mip level.
|
||||||
uint32_t mip_pitches[14];
|
uint32_t slice_sizes[14];
|
||||||
|
// Row pitches on each mip level (for linear layout mainly).
|
||||||
|
uint32_t pitches[14];
|
||||||
|
|
||||||
// Watch handles for the memory ranges (protected by the shared memory watch
|
// Watch handles for the memory ranges (protected by the shared memory watch
|
||||||
// mutex).
|
// mutex).
|
||||||
|
|
|
@ -54,9 +54,11 @@ void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetGuestMipStorageSize(uint32_t width_blocks, uint32_t height_blocks,
|
uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks,
|
||||||
uint32_t depth_blocks, bool is_tiled,
|
uint32_t height_blocks,
|
||||||
TextureFormat format, uint32_t* row_pitch_out) {
|
uint32_t depth_blocks, bool is_tiled,
|
||||||
|
TextureFormat format,
|
||||||
|
uint32_t* row_pitch_out) {
|
||||||
const FormatInfo* format_info = FormatInfo::Get(format);
|
const FormatInfo* format_info = FormatInfo::Get(format);
|
||||||
uint32_t row_pitch = width_blocks * format_info->block_width *
|
uint32_t row_pitch = width_blocks * format_info->block_width *
|
||||||
format_info->block_height * format_info->bits_per_pixel /
|
format_info->block_height * format_info->bits_per_pixel /
|
||||||
|
|
|
@ -29,11 +29,14 @@ void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height,
|
||||||
uint32_t& width_blocks_out, uint32_t& height_blocks_out,
|
uint32_t& width_blocks_out, uint32_t& height_blocks_out,
|
||||||
uint32_t& depth_blocks_out);
|
uint32_t& depth_blocks_out);
|
||||||
|
|
||||||
// Calculates the number of bytes required to store a single mip level - width,
|
// Calculates the number of bytes required to store a single array slice within
|
||||||
// height and depth must be obtained via GetGuestMipExtent.
|
// a single mip level - width, height and depth must be obtained via
|
||||||
uint32_t GetGuestMipStorageSize(uint32_t width_blocks, uint32_t height_blocks,
|
// GetGuestMipBlocks.
|
||||||
uint32_t depth_blocks, bool is_tiled,
|
uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks,
|
||||||
TextureFormat format, uint32_t* row_pitch_out);
|
uint32_t height_blocks,
|
||||||
|
uint32_t depth_blocks, bool is_tiled,
|
||||||
|
TextureFormat format,
|
||||||
|
uint32_t* row_pitch_out);
|
||||||
|
|
||||||
// Gets the number of the mipmap level where the packed mips are stored.
|
// Gets the number of the mipmap level where the packed mips are stored.
|
||||||
inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) {
|
inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) {
|
||||||
|
|
Loading…
Reference in New Issue