diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index 9e87058dc..291ecb5df 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -1634,6 +1634,10 @@ RenderTargetCache::ResolveTarget* RenderTargetCache::FindOrCreateResolveTarget( device->GetCopyableFootprints(&resource_desc, 0, 1, 0, &resolve_target->footprint, nullptr, nullptr, ©_buffer_size); + // Safety (though if width and height are aligned to 32 it will be fine, but + // just in case this changes). + copy_buffer_size = + xe::align(copy_buffer_size, UINT64(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT)); resolve_target->copy_buffer_size = uint32_t(copy_buffer_size); resolve_targets_.insert(std::make_pair(key.value, resolve_target)); diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 29772ae57..df5f43bca 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -941,6 +941,13 @@ bool TextureCache::LoadTextureData(Texture* texture) { device->GetCopyableFootprints(&resource_desc, 0, resource_desc.MipLevels, 0, host_layouts, nullptr, nullptr, &host_slice_size); + // The shaders deliberately overflow for simplicity, and GetCopyableFootprints + // doesn't align the size of the last row (or the size if there's only one + // row, not really sure) to row pitch, so add some excess bytes for safety. + // 1x1 8-bit and 16-bit textures even give a device loss because the raw UAV + // has a size of 0. + host_slice_size = + xe::align(host_slice_size, UINT64(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT)); D3D12_RESOURCE_STATES copy_buffer_state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; ID3D12Resource* copy_buffer = command_processor_->RequestScratchGPUBuffer(