diff options
| -rw-r--r-- | src/video_core/engines/maxwell_dma.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.h | 3 |
3 files changed, 36 insertions, 23 deletions
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index b5f57e534..a71d98e36 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/settings.h" | ||
| 8 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
| 9 | #include "video_core/engines/maxwell_dma.h" | 10 | #include "video_core/engines/maxwell_dma.h" |
| 10 | #include "video_core/memory_manager.h" | 11 | #include "video_core/memory_manager.h" |
| @@ -84,13 +85,17 @@ void MaxwellDMA::HandleCopy() { | |||
| 84 | ASSERT(regs.exec.enable_2d == 1); | 85 | ASSERT(regs.exec.enable_2d == 1); |
| 85 | 86 | ||
| 86 | if (regs.exec.is_dst_linear && !regs.exec.is_src_linear) { | 87 | if (regs.exec.is_dst_linear && !regs.exec.is_src_linear) { |
| 87 | ASSERT(regs.src_params.size_z == 1); | 88 | ASSERT(regs.src_params.BlockDepth() == 0); |
| 88 | // If the input is tiled and the output is linear, deswizzle the input and copy it over. | 89 | // If the input is tiled and the output is linear, deswizzle the input and copy it over. |
| 89 | const u32 src_bytes_per_pixel = regs.src_pitch / regs.src_params.size_x; | 90 | const u32 bytes_per_pixel = regs.dst_pitch / regs.x_count; |
| 90 | const std::size_t src_size = Texture::CalculateSize( | 91 | const std::size_t src_size = Texture::CalculateSize( |
| 91 | true, src_bytes_per_pixel, regs.src_params.size_x, regs.src_params.size_y, | 92 | true, bytes_per_pixel, regs.src_params.size_x, regs.src_params.size_y, |
| 92 | regs.src_params.size_z, regs.src_params.BlockHeight(), regs.src_params.BlockDepth()); | 93 | regs.src_params.size_z, regs.src_params.BlockHeight(), regs.src_params.BlockDepth()); |
| 93 | 94 | ||
| 95 | const std::size_t src_layer_size = Texture::CalculateSize( | ||
| 96 | true, bytes_per_pixel, regs.src_params.size_x, regs.src_params.size_y, 1, | ||
| 97 | regs.src_params.BlockHeight(), regs.src_params.BlockDepth()); | ||
| 98 | |||
| 94 | const std::size_t dst_size = regs.dst_pitch * regs.y_count; | 99 | const std::size_t dst_size = regs.dst_pitch * regs.y_count; |
| 95 | 100 | ||
| 96 | if (read_buffer.size() < src_size) { | 101 | if (read_buffer.size() < src_size) { |
| @@ -104,23 +109,23 @@ void MaxwellDMA::HandleCopy() { | |||
| 104 | memory_manager.ReadBlock(source, read_buffer.data(), src_size); | 109 | memory_manager.ReadBlock(source, read_buffer.data(), src_size); |
| 105 | memory_manager.ReadBlock(dest, write_buffer.data(), dst_size); | 110 | memory_manager.ReadBlock(dest, write_buffer.data(), dst_size); |
| 106 | 111 | ||
| 107 | Texture::UnswizzleSubrect(regs.x_count, regs.y_count, regs.dst_pitch, | 112 | Texture::UnswizzleSubrect( |
| 108 | regs.src_params.size_x, src_bytes_per_pixel, read_buffer.data(), | 113 | regs.x_count, regs.y_count, regs.dst_pitch, regs.src_params.size_x, bytes_per_pixel, |
| 109 | write_buffer.data(), regs.src_params.BlockHeight(), | 114 | read_buffer.data() + src_layer_size * regs.src_params.pos_z, write_buffer.data(), |
| 110 | regs.src_params.pos_x, regs.src_params.pos_y); | 115 | regs.src_params.BlockHeight(), regs.src_params.pos_x, regs.src_params.pos_y); |
| 111 | 116 | ||
| 112 | memory_manager.WriteBlock(dest, write_buffer.data(), dst_size); | 117 | memory_manager.WriteBlock(dest, write_buffer.data(), dst_size); |
| 113 | } else { | 118 | } else { |
| 114 | ASSERT(regs.dst_params.BlockDepth() == 0); | 119 | ASSERT(regs.dst_params.BlockDepth() == 0); |
| 115 | 120 | ||
| 116 | const u32 src_bytes_per_pixel = regs.src_pitch / regs.x_count; | 121 | const u32 bytes_per_pixel = regs.src_pitch / regs.x_count; |
| 117 | 122 | ||
| 118 | const std::size_t dst_size = Texture::CalculateSize( | 123 | const std::size_t dst_size = Texture::CalculateSize( |
| 119 | true, src_bytes_per_pixel, regs.dst_params.size_x, regs.dst_params.size_y, | 124 | true, bytes_per_pixel, regs.dst_params.size_x, regs.dst_params.size_y, |
| 120 | regs.dst_params.size_z, regs.dst_params.BlockHeight(), regs.dst_params.BlockDepth()); | 125 | regs.dst_params.size_z, regs.dst_params.BlockHeight(), regs.dst_params.BlockDepth()); |
| 121 | 126 | ||
| 122 | const std::size_t dst_layer_size = Texture::CalculateSize( | 127 | const std::size_t dst_layer_size = Texture::CalculateSize( |
| 123 | true, src_bytes_per_pixel, regs.dst_params.size_x, regs.dst_params.size_y, 1, | 128 | true, bytes_per_pixel, regs.dst_params.size_x, regs.dst_params.size_y, 1, |
| 124 | regs.dst_params.BlockHeight(), regs.dst_params.BlockDepth()); | 129 | regs.dst_params.BlockHeight(), regs.dst_params.BlockDepth()); |
| 125 | 130 | ||
| 126 | const std::size_t src_size = regs.src_pitch * regs.y_count; | 131 | const std::size_t src_size = regs.src_pitch * regs.y_count; |
| @@ -133,14 +138,19 @@ void MaxwellDMA::HandleCopy() { | |||
| 133 | write_buffer.resize(dst_size); | 138 | write_buffer.resize(dst_size); |
| 134 | } | 139 | } |
| 135 | 140 | ||
| 136 | memory_manager.ReadBlock(source, read_buffer.data(), src_size); | 141 | if (Settings::values.use_accurate_gpu_emulation) { |
| 137 | memory_manager.ReadBlock(dest, write_buffer.data(), dst_size); | 142 | memory_manager.ReadBlock(source, read_buffer.data(), src_size); |
| 143 | memory_manager.ReadBlock(dest, write_buffer.data(), dst_size); | ||
| 144 | } else { | ||
| 145 | memory_manager.ReadBlockUnsafe(source, read_buffer.data(), src_size); | ||
| 146 | memory_manager.ReadBlockUnsafe(dest, write_buffer.data(), dst_size); | ||
| 147 | } | ||
| 138 | 148 | ||
| 139 | // If the input is linear and the output is tiled, swizzle the input and copy it over. | 149 | // If the input is linear and the output is tiled, swizzle the input and copy it over. |
| 140 | Texture::SwizzleSubrect(regs.x_count, regs.y_count, regs.src_pitch, regs.dst_params.size_x, | 150 | Texture::SwizzleSubrect( |
| 141 | src_bytes_per_pixel, | 151 | regs.x_count, regs.y_count, regs.src_pitch, regs.dst_params.size_x, bytes_per_pixel, |
| 142 | write_buffer.data() + dst_layer_size * regs.dst_params.pos_z, | 152 | write_buffer.data() + dst_layer_size * regs.dst_params.pos_z, read_buffer.data(), |
| 143 | read_buffer.data(), regs.dst_params.BlockHeight()); | 153 | regs.dst_params.BlockHeight(), regs.dst_params.pos_x, regs.dst_params.pos_y); |
| 144 | 154 | ||
| 145 | memory_manager.WriteBlock(dest, write_buffer.data(), dst_size); | 155 | memory_manager.WriteBlock(dest, write_buffer.data(), dst_size); |
| 146 | } | 156 | } |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 7e8295944..7df5f1452 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -257,19 +257,21 @@ std::vector<u8> UnswizzleTexture(u8* address, u32 tile_size_x, u32 tile_size_y, | |||
| 257 | 257 | ||
| 258 | void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 swizzled_width, | 258 | void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 swizzled_width, |
| 259 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, | 259 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, |
| 260 | u32 block_height_bit) { | 260 | u32 block_height_bit, u32 offset_x, u32 offset_y) { |
| 261 | const u32 block_height = 1U << block_height_bit; | 261 | const u32 block_height = 1U << block_height_bit; |
| 262 | const u32 image_width_in_gobs{(swizzled_width * bytes_per_pixel + (gob_size_x - 1)) / | 262 | const u32 image_width_in_gobs{(swizzled_width * bytes_per_pixel + (gob_size_x - 1)) / |
| 263 | gob_size_x}; | 263 | gob_size_x}; |
| 264 | for (u32 line = 0; line < subrect_height; ++line) { | 264 | for (u32 line = 0; line < subrect_height; ++line) { |
| 265 | const u32 dst_y = line + offset_y; | ||
| 265 | const u32 gob_address_y = | 266 | const u32 gob_address_y = |
| 266 | (line / (gob_size_y * block_height)) * gob_size * block_height * image_width_in_gobs + | 267 | (dst_y / (gob_size_y * block_height)) * gob_size * block_height * image_width_in_gobs + |
| 267 | ((line % (gob_size_y * block_height)) / gob_size_y) * gob_size; | 268 | ((dst_y % (gob_size_y * block_height)) / gob_size_y) * gob_size; |
| 268 | const auto& table = legacy_swizzle_table[line % gob_size_y]; | 269 | const auto& table = legacy_swizzle_table[dst_y % gob_size_y]; |
| 269 | for (u32 x = 0; x < subrect_width; ++x) { | 270 | for (u32 x = 0; x < subrect_width; ++x) { |
| 271 | const u32 dst_x = x + offset_x; | ||
| 270 | const u32 gob_address = | 272 | const u32 gob_address = |
| 271 | gob_address_y + (x * bytes_per_pixel / gob_size_x) * gob_size * block_height; | 273 | gob_address_y + (dst_x * bytes_per_pixel / gob_size_x) * gob_size * block_height; |
| 272 | const u32 swizzled_offset = gob_address + table[(x * bytes_per_pixel) % gob_size_x]; | 274 | const u32 swizzled_offset = gob_address + table[(dst_x * bytes_per_pixel) % gob_size_x]; |
| 273 | u8* source_line = unswizzled_data + line * source_pitch + x * bytes_per_pixel; | 275 | u8* source_line = unswizzled_data + line * source_pitch + x * bytes_per_pixel; |
| 274 | u8* dest_addr = swizzled_data + swizzled_offset; | 276 | u8* dest_addr = swizzled_data + swizzled_offset; |
| 275 | 277 | ||
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index eaec9b5a5..f1e3952bc 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -44,7 +44,8 @@ std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height | |||
| 44 | 44 | ||
| 45 | /// Copies an untiled subrectangle into a tiled surface. | 45 | /// Copies an untiled subrectangle into a tiled surface. |
| 46 | void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 swizzled_width, | 46 | void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 swizzled_width, |
| 47 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, u32 block_height); | 47 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, u32 block_height, |
| 48 | u32 offset_x, u32 offset_y); | ||
| 48 | 49 | ||
| 49 | /// Copies a tiled subrectangle into a linear surface. | 50 | /// Copies a tiled subrectangle into a linear surface. |
| 50 | void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width, | 51 | void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width, |