diff options
| author | 2018-04-24 00:19:36 -0400 | |
|---|---|---|
| committer | 2018-04-24 22:31:45 -0400 | |
| commit | 4415e00181f71b35eea779157976773d9bccf638 (patch) | |
| tree | 604e0f8de1fe238ac74eee4fd3d5eabdb59e7bc1 /src | |
| parent | memory_manager: Add implement CpuToGpuAddress. (diff) | |
| download | yuzu-4415e00181f71b35eea779157976773d9bccf638.tar.gz yuzu-4415e00181f71b35eea779157976773d9bccf638.tar.xz yuzu-4415e00181f71b35eea779157976773d9bccf638.zip | |
gl_rasterizer_cache: Update to be based on GPU addresses, not CPU addresses.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/memory.cpp | 64 | ||||
| -rw-r--r-- | src/core/memory.h | 3 | ||||
| -rw-r--r-- | src/video_core/memory_manager.h | 1 | ||||
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 63 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 1 |
10 files changed, 122 insertions, 67 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 291bf066f..ff0420c56 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -325,15 +325,29 @@ u8* GetPhysicalPointer(PAddr address) { | |||
| 325 | return target_pointer; | 325 | return target_pointer; |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { | 328 | void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) { |
| 329 | if (start == 0) { | 329 | if (gpu_addr == 0) { |
| 330 | return; | 330 | return; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | u64 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; | 333 | // Iterate over a contiguous CPU address space, which corresponds to the specified GPU address |
| 334 | VAddr vaddr = start; | 334 | // space, marking the region as un/cached. The region is marked un/cached at a granularity of |
| 335 | // CPU pages, hence why we iterate on a CPU page basis (note: GPU page size is different). This | ||
| 336 | // assumes the specified GPU address region is contiguous as well. | ||
| 337 | |||
| 338 | u64 num_pages = ((gpu_addr + size - 1) >> PAGE_BITS) - (gpu_addr >> PAGE_BITS) + 1; | ||
| 339 | for (unsigned i = 0; i < num_pages; ++i, gpu_addr += PAGE_SIZE) { | ||
| 340 | boost::optional<VAddr> maybe_vaddr = | ||
| 341 | Core::System::GetInstance().GPU().memory_manager->GpuToCpuAddress(gpu_addr); | ||
| 342 | // The GPU <-> CPU virtual memory mapping is not 1:1 | ||
| 343 | if (!maybe_vaddr) { | ||
| 344 | LOG_ERROR(HW_Memory, | ||
| 345 | "Trying to flush a cached region to an invalid physical address %08X", | ||
| 346 | gpu_addr); | ||
| 347 | continue; | ||
| 348 | } | ||
| 349 | VAddr vaddr = *maybe_vaddr; | ||
| 335 | 350 | ||
| 336 | for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { | ||
| 337 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 351 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 338 | 352 | ||
| 339 | if (cached) { | 353 | if (cached) { |
| @@ -347,6 +361,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { | |||
| 347 | page_type = PageType::RasterizerCachedMemory; | 361 | page_type = PageType::RasterizerCachedMemory; |
| 348 | current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; | 362 | current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; |
| 349 | break; | 363 | break; |
| 364 | case PageType::RasterizerCachedMemory: | ||
| 365 | // There can be more than one GPU region mapped per CPU region, so it's common that | ||
| 366 | // this area is already marked as cached. | ||
| 367 | break; | ||
| 350 | default: | 368 | default: |
| 351 | UNREACHABLE(); | 369 | UNREACHABLE(); |
| 352 | } | 370 | } |
| @@ -357,6 +375,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { | |||
| 357 | // It is not necessary for a process to have this region mapped into its address | 375 | // It is not necessary for a process to have this region mapped into its address |
| 358 | // space, for example, a system module need not have a VRAM mapping. | 376 | // space, for example, a system module need not have a VRAM mapping. |
| 359 | break; | 377 | break; |
| 378 | case PageType::Memory: | ||
| 379 | // There can be more than one GPU region mapped per CPU region, so it's common that | ||
| 380 | // this area is already unmarked as cached. | ||
| 381 | break; | ||
| 360 | case PageType::RasterizerCachedMemory: { | 382 | case PageType::RasterizerCachedMemory: { |
| 361 | u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); | 383 | u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); |
| 362 | if (pointer == nullptr) { | 384 | if (pointer == nullptr) { |
| @@ -394,19 +416,29 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { | |||
| 394 | 416 | ||
| 395 | VAddr overlap_start = std::max(start, region_start); | 417 | VAddr overlap_start = std::max(start, region_start); |
| 396 | VAddr overlap_end = std::min(end, region_end); | 418 | VAddr overlap_end = std::min(end, region_end); |
| 419 | |||
| 420 | std::vector<Tegra::GPUVAddr> gpu_addresses = | ||
| 421 | Core::System::GetInstance().GPU().memory_manager->CpuToGpuAddress(overlap_start); | ||
| 422 | |||
| 423 | if (gpu_addresses.empty()) { | ||
| 424 | return; | ||
| 425 | } | ||
| 426 | |||
| 397 | u64 overlap_size = overlap_end - overlap_start; | 427 | u64 overlap_size = overlap_end - overlap_start; |
| 398 | 428 | ||
| 399 | auto* rasterizer = VideoCore::g_renderer->Rasterizer(); | 429 | for (const auto& gpu_address : gpu_addresses) { |
| 400 | switch (mode) { | 430 | auto* rasterizer = VideoCore::g_renderer->Rasterizer(); |
| 401 | case FlushMode::Flush: | 431 | switch (mode) { |
| 402 | rasterizer->FlushRegion(overlap_start, overlap_size); | 432 | case FlushMode::Flush: |
| 403 | break; | 433 | rasterizer->FlushRegion(gpu_address, overlap_size); |
| 404 | case FlushMode::Invalidate: | 434 | break; |
| 405 | rasterizer->InvalidateRegion(overlap_start, overlap_size); | 435 | case FlushMode::Invalidate: |
| 406 | break; | 436 | rasterizer->InvalidateRegion(gpu_address, overlap_size); |
| 407 | case FlushMode::FlushAndInvalidate: | 437 | break; |
| 408 | rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); | 438 | case FlushMode::FlushAndInvalidate: |
| 409 | break; | 439 | rasterizer->FlushAndInvalidateRegion(gpu_address, overlap_size); |
| 440 | break; | ||
| 441 | } | ||
| 410 | } | 442 | } |
| 411 | }; | 443 | }; |
| 412 | 444 | ||
diff --git a/src/core/memory.h b/src/core/memory.h index e9b8ca873..3f56a2c6a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <boost/optional.hpp> | 14 | #include <boost/optional.hpp> |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "core/memory_hook.h" | 16 | #include "core/memory_hook.h" |
| 17 | #include "video_core/memory_manager.h" | ||
| 17 | 18 | ||
| 18 | namespace Kernel { | 19 | namespace Kernel { |
| 19 | class Process; | 20 | class Process; |
| @@ -258,7 +259,7 @@ enum class FlushMode { | |||
| 258 | /** | 259 | /** |
| 259 | * Mark each page touching the region as cached. | 260 | * Mark each page touching the region as cached. |
| 260 | */ | 261 | */ |
| 261 | void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached); | 262 | void RasterizerMarkRegionCached(Tegra::GPUVAddr start, u64 size, bool cached); |
| 262 | 263 | ||
| 263 | /** | 264 | /** |
| 264 | * Flushes and invalidates any externally cached rasterizer resources touching the given virtual | 265 | * Flushes and invalidates any externally cached rasterizer resources touching the given virtual |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 7d745101f..08140c83a 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include <boost/optional.hpp> | 11 | #include <boost/optional.hpp> |
| 12 | 12 | ||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/memory.h" | ||
| 15 | 14 | ||
| 16 | namespace Tegra { | 15 | namespace Tegra { |
| 17 | 16 | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 36629dd11..f0e48a802 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "video_core/gpu.h" | 8 | #include "video_core/gpu.h" |
| 9 | #include "video_core/memory_manager.h" | ||
| 9 | 10 | ||
| 10 | struct ScreenInfo; | 11 | struct ScreenInfo; |
| 11 | 12 | ||
| @@ -25,14 +26,14 @@ public: | |||
| 25 | virtual void FlushAll() = 0; | 26 | virtual void FlushAll() = 0; |
| 26 | 27 | ||
| 27 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 28 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 28 | virtual void FlushRegion(VAddr addr, u64 size) = 0; | 29 | virtual void FlushRegion(Tegra::GPUVAddr addr, u64 size) = 0; |
| 29 | 30 | ||
| 30 | /// Notify rasterizer that any caches of the specified region should be invalidated | 31 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 31 | virtual void InvalidateRegion(VAddr addr, u64 size) = 0; | 32 | virtual void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0; |
| 32 | 33 | ||
| 33 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 34 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 34 | /// and invalidated | 35 | /// and invalidated |
| 35 | virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; | 36 | virtual void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0; |
| 36 | 37 | ||
| 37 | /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0 | 38 | /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0 |
| 38 | virtual bool AccelerateDisplayTransfer(const void* config) { | 39 | virtual bool AccelerateDisplayTransfer(const void* config) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 71612790b..bc9368877 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -150,9 +150,8 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, | |||
| 150 | u64 size = end - start + 1; | 150 | u64 size = end - start + 1; |
| 151 | 151 | ||
| 152 | // Copy vertex array data | 152 | // Copy vertex array data |
| 153 | const VAddr data_addr{*memory_manager->GpuToCpuAddress(start)}; | 153 | res_cache.FlushRegion(start, size, nullptr); |
| 154 | res_cache.FlushRegion(data_addr, size, nullptr); | 154 | Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size); |
| 155 | Memory::ReadBlock(data_addr, array_ptr, size); | ||
| 156 | 155 | ||
| 157 | // Bind the vertex array to the buffer at the current offset. | 156 | // Bind the vertex array to the buffer at the current offset. |
| 158 | glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride); | 157 | glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride); |
| @@ -519,17 +518,17 @@ void RasterizerOpenGL::FlushAll() { | |||
| 519 | res_cache.FlushAll(); | 518 | res_cache.FlushAll(); |
| 520 | } | 519 | } |
| 521 | 520 | ||
| 522 | void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { | 521 | void RasterizerOpenGL::FlushRegion(Tegra::GPUVAddr addr, u64 size) { |
| 523 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 522 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 524 | res_cache.FlushRegion(addr, size); | 523 | res_cache.FlushRegion(addr, size); |
| 525 | } | 524 | } |
| 526 | 525 | ||
| 527 | void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { | 526 | void RasterizerOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, u64 size) { |
| 528 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 527 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 529 | res_cache.InvalidateRegion(addr, size, nullptr); | 528 | res_cache.InvalidateRegion(addr, size, nullptr); |
| 530 | } | 529 | } |
| 531 | 530 | ||
| 532 | void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 531 | void RasterizerOpenGL::FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) { |
| 533 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 532 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 534 | res_cache.FlushRegion(addr, size); | 533 | res_cache.FlushRegion(addr, size); |
| 535 | res_cache.InvalidateRegion(addr, size, nullptr); | 534 | res_cache.InvalidateRegion(addr, size, nullptr); |
| @@ -560,7 +559,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu | |||
| 560 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 559 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 561 | 560 | ||
| 562 | SurfaceParams src_params; | 561 | SurfaceParams src_params; |
| 563 | src_params.addr = framebuffer_addr; | 562 | src_params.cpu_addr = framebuffer_addr; |
| 564 | src_params.width = std::min(framebuffer.width, pixel_stride); | 563 | src_params.width = std::min(framebuffer.width, pixel_stride); |
| 565 | src_params.height = framebuffer.height; | 564 | src_params.height = framebuffer.height; |
| 566 | src_params.stride = pixel_stride; | 565 | src_params.stride = pixel_stride; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 544714b95..9709e595e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <glad/glad.h> | 11 | #include <glad/glad.h> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "video_core/engines/maxwell_3d.h" | 13 | #include "video_core/engines/maxwell_3d.h" |
| 14 | #include "video_core/memory_manager.h" | ||
| 14 | #include "video_core/rasterizer_interface.h" | 15 | #include "video_core/rasterizer_interface.h" |
| 15 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 16 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| 16 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 17 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -29,9 +30,9 @@ public: | |||
| 29 | void DrawArrays() override; | 30 | void DrawArrays() override; |
| 30 | void NotifyMaxwellRegisterChanged(u32 method) override; | 31 | void NotifyMaxwellRegisterChanged(u32 method) override; |
| 31 | void FlushAll() override; | 32 | void FlushAll() override; |
| 32 | void FlushRegion(VAddr addr, u64 size) override; | 33 | void FlushRegion(Tegra::GPUVAddr addr, u64 size) override; |
| 33 | void InvalidateRegion(VAddr addr, u64 size) override; | 34 | void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) override; |
| 34 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | 35 | void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) override; |
| 35 | bool AccelerateDisplayTransfer(const void* config) override; | 36 | bool AccelerateDisplayTransfer(const void* config) override; |
| 36 | bool AccelerateTextureCopy(const void* config) override; | 37 | bool AccelerateTextureCopy(const void* config) override; |
| 37 | bool AccelerateFill(const void* config) override; | 38 | bool AccelerateFill(const void* config) override; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index ced648c12..d139d51e9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -83,26 +83,30 @@ static u16 GetResolutionScaleFactor() { | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | template <bool morton_to_gl, PixelFormat format> | 85 | template <bool morton_to_gl, PixelFormat format> |
| 86 | void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start, | 86 | void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::GPUVAddr base, |
| 87 | VAddr end) { | 87 | Tegra::GPUVAddr start, Tegra::GPUVAddr end) { |
| 88 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; | 88 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; |
| 89 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); | 89 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); |
| 90 | const auto& gpu = Core::System::GetInstance().GPU(); | ||
| 90 | 91 | ||
| 91 | if (morton_to_gl) { | 92 | if (morton_to_gl) { |
| 92 | auto data = Tegra::Texture::UnswizzleTexture( | 93 | auto data = Tegra::Texture::UnswizzleTexture( |
| 93 | base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, | 94 | *gpu.memory_manager->GpuToCpuAddress(base), |
| 94 | block_height); | 95 | SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height); |
| 95 | std::memcpy(gl_buffer, data.data(), data.size()); | 96 | std::memcpy(gl_buffer, data.data(), data.size()); |
| 96 | } else { | 97 | } else { |
| 97 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check | 98 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check |
| 98 | // the configuration for this and perform more generic un/swizzle | 99 | // the configuration for this and perform more generic un/swizzle |
| 99 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | 100 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); |
| 100 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, | 101 | VideoCore::MortonCopyPixels128( |
| 101 | Memory::GetPointer(base), gl_buffer, morton_to_gl); | 102 | stride, height, bytes_per_pixel, gl_bytes_per_pixel, |
| 103 | Memory::GetPointer(*gpu.memory_manager->GpuToCpuAddress(base)), gl_buffer, | ||
| 104 | morton_to_gl); | ||
| 102 | } | 105 | } |
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), | 108 | static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr, |
| 109 | Tegra::GPUVAddr), | ||
| 106 | SurfaceParams::MaxPixelFormat> | 110 | SurfaceParams::MaxPixelFormat> |
| 107 | morton_to_gl_fns = { | 111 | morton_to_gl_fns = { |
| 108 | MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, | 112 | MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, |
| @@ -110,7 +114,8 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), | |||
| 110 | MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, | 114 | MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, |
| 111 | }; | 115 | }; |
| 112 | 116 | ||
| 113 | static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), | 117 | static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr, |
| 118 | Tegra::GPUVAddr), | ||
| 114 | SurfaceParams::MaxPixelFormat> | 119 | SurfaceParams::MaxPixelFormat> |
| 115 | gl_to_morton_fns = { | 120 | gl_to_morton_fns = { |
| 116 | MortonCopy<false, PixelFormat::ABGR8>, | 121 | MortonCopy<false, PixelFormat::ABGR8>, |
| @@ -219,9 +224,9 @@ SurfaceParams SurfaceParams::FromInterval(SurfaceInterval interval) const { | |||
| 219 | SurfaceParams params = *this; | 224 | SurfaceParams params = *this; |
| 220 | const u32 tiled_size = is_tiled ? 8 : 1; | 225 | const u32 tiled_size = is_tiled ? 8 : 1; |
| 221 | const u64 stride_tiled_bytes = BytesInPixels(stride * tiled_size); | 226 | const u64 stride_tiled_bytes = BytesInPixels(stride * tiled_size); |
| 222 | VAddr aligned_start = | 227 | Tegra::GPUVAddr aligned_start = |
| 223 | addr + Common::AlignDown(boost::icl::first(interval) - addr, stride_tiled_bytes); | 228 | addr + Common::AlignDown(boost::icl::first(interval) - addr, stride_tiled_bytes); |
| 224 | VAddr aligned_end = | 229 | Tegra::GPUVAddr aligned_end = |
| 225 | addr + Common::AlignUp(boost::icl::last_next(interval) - addr, stride_tiled_bytes); | 230 | addr + Common::AlignUp(boost::icl::last_next(interval) - addr, stride_tiled_bytes); |
| 226 | 231 | ||
| 227 | if (aligned_end - aligned_start > stride_tiled_bytes) { | 232 | if (aligned_end - aligned_start > stride_tiled_bytes) { |
| @@ -342,6 +347,13 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const { | |||
| 342 | return FromInterval(texcopy_params.GetInterval()).GetInterval() == texcopy_params.GetInterval(); | 347 | return FromInterval(texcopy_params.GetInterval()).GetInterval() == texcopy_params.GetInterval(); |
| 343 | } | 348 | } |
| 344 | 349 | ||
| 350 | VAddr SurfaceParams::GetCpuAddr() const { | ||
| 351 | // When this function is used, only cpu_addr or (GPU) addr should be set, not both | ||
| 352 | ASSERT(!(cpu_addr && addr)); | ||
| 353 | const auto& gpu = Core::System::GetInstance().GPU(); | ||
| 354 | return cpu_addr.get_value_or(*gpu.memory_manager->GpuToCpuAddress(addr)); | ||
| 355 | } | ||
| 356 | |||
| 345 | bool CachedSurface::CanFill(const SurfaceParams& dest_surface, | 357 | bool CachedSurface::CanFill(const SurfaceParams& dest_surface, |
| 346 | SurfaceInterval fill_interval) const { | 358 | SurfaceInterval fill_interval) const { |
| 347 | if (type == SurfaceType::Fill && IsRegionValid(fill_interval) && | 359 | if (type == SurfaceType::Fill && IsRegionValid(fill_interval) && |
| @@ -456,10 +468,10 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac | |||
| 456 | } | 468 | } |
| 457 | 469 | ||
| 458 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); | 470 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); |
| 459 | void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) { | 471 | void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr load_end) { |
| 460 | ASSERT(type != SurfaceType::Fill); | 472 | ASSERT(type != SurfaceType::Fill); |
| 461 | 473 | ||
| 462 | u8* const texture_src_data = Memory::GetPointer(addr); | 474 | u8* const texture_src_data = Memory::GetPointer(GetCpuAddr()); |
| 463 | if (texture_src_data == nullptr) | 475 | if (texture_src_data == nullptr) |
| 464 | return; | 476 | return; |
| 465 | 477 | ||
| @@ -485,8 +497,8 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) { | |||
| 485 | } | 497 | } |
| 486 | 498 | ||
| 487 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); | 499 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); |
| 488 | void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) { | 500 | void CachedSurface::FlushGLBuffer(Tegra::GPUVAddr flush_start, Tegra::GPUVAddr flush_end) { |
| 489 | u8* const dst_buffer = Memory::GetPointer(addr); | 501 | u8* const dst_buffer = Memory::GetPointer(GetCpuAddr()); |
| 490 | if (dst_buffer == nullptr) | 502 | if (dst_buffer == nullptr) |
| 491 | return; | 503 | return; |
| 492 | 504 | ||
| @@ -1028,7 +1040,7 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu | |||
| 1028 | auto& gpu = Core::System::GetInstance().GPU(); | 1040 | auto& gpu = Core::System::GetInstance().GPU(); |
| 1029 | 1041 | ||
| 1030 | SurfaceParams params; | 1042 | SurfaceParams params; |
| 1031 | params.addr = *gpu.memory_manager->GpuToCpuAddress(config.tic.Address()); | 1043 | params.addr = config.tic.Address(); |
| 1032 | params.width = config.tic.Width(); | 1044 | params.width = config.tic.Width(); |
| 1033 | params.height = config.tic.Height(); | 1045 | params.height = config.tic.Height(); |
| 1034 | params.is_tiled = config.tic.IsTiled(); | 1046 | params.is_tiled = config.tic.IsTiled(); |
| @@ -1045,7 +1057,7 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu | |||
| 1045 | params.block_height = config.tic.BlockHeight(); | 1057 | params.block_height = config.tic.BlockHeight(); |
| 1046 | } else { | 1058 | } else { |
| 1047 | // Use the texture-provided stride value if the texture isn't tiled. | 1059 | // Use the texture-provided stride value if the texture isn't tiled. |
| 1048 | params.stride = params.PixelsInBytes(config.tic.Pitch()); | 1060 | params.stride = static_cast<u32>(params.PixelsInBytes(config.tic.Pitch())); |
| 1049 | } | 1061 | } |
| 1050 | 1062 | ||
| 1051 | params.UpdateParams(); | 1063 | params.UpdateParams(); |
| @@ -1073,7 +1085,6 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu | |||
| 1073 | SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | 1085 | SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( |
| 1074 | bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) { | 1086 | bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) { |
| 1075 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; | 1087 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; |
| 1076 | const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; | ||
| 1077 | const auto& config = regs.rt[0]; | 1088 | const auto& config = regs.rt[0]; |
| 1078 | 1089 | ||
| 1079 | // TODO(bunnei): This is hard corded to use just the first render buffer | 1090 | // TODO(bunnei): This is hard corded to use just the first render buffer |
| @@ -1106,7 +1117,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
| 1106 | color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; | 1117 | color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; |
| 1107 | SurfaceParams depth_params = color_params; | 1118 | SurfaceParams depth_params = color_params; |
| 1108 | 1119 | ||
| 1109 | color_params.addr = *memory_manager->GpuToCpuAddress(config.Address()); | 1120 | color_params.addr = config.Address(); |
| 1110 | color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); | 1121 | color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); |
| 1111 | color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); | 1122 | color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); |
| 1112 | color_params.UpdateParams(); | 1123 | color_params.UpdateParams(); |
| @@ -1222,7 +1233,8 @@ void RasterizerCacheOpenGL::DuplicateSurface(const Surface& src_surface, | |||
| 1222 | } | 1233 | } |
| 1223 | } | 1234 | } |
| 1224 | 1235 | ||
| 1225 | void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr, u64 size) { | 1236 | void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, Tegra::GPUVAddr addr, |
| 1237 | u64 size) { | ||
| 1226 | if (size == 0) | 1238 | if (size == 0) |
| 1227 | return; | 1239 | return; |
| 1228 | 1240 | ||
| @@ -1261,7 +1273,7 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr, | |||
| 1261 | } | 1273 | } |
| 1262 | } | 1274 | } |
| 1263 | 1275 | ||
| 1264 | void RasterizerCacheOpenGL::FlushRegion(VAddr addr, u64 size, Surface flush_surface) { | 1276 | void RasterizerCacheOpenGL::FlushRegion(Tegra::GPUVAddr addr, u64 size, Surface flush_surface) { |
| 1265 | if (size == 0) | 1277 | if (size == 0) |
| 1266 | return; | 1278 | return; |
| 1267 | 1279 | ||
| @@ -1297,7 +1309,8 @@ void RasterizerCacheOpenGL::FlushAll() { | |||
| 1297 | FlushRegion(0, Kernel::VMManager::MAX_ADDRESS); | 1309 | FlushRegion(0, Kernel::VMManager::MAX_ADDRESS); |
| 1298 | } | 1310 | } |
| 1299 | 1311 | ||
| 1300 | void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface& region_owner) { | 1312 | void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, u64 size, |
| 1313 | const Surface& region_owner) { | ||
| 1301 | if (size == 0) | 1314 | if (size == 0) |
| 1302 | return; | 1315 | return; |
| 1303 | 1316 | ||
| @@ -1390,7 +1403,7 @@ void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { | |||
| 1390 | surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); | 1403 | surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); |
| 1391 | } | 1404 | } |
| 1392 | 1405 | ||
| 1393 | void RasterizerCacheOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { | 1406 | void RasterizerCacheOpenGL::UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) { |
| 1394 | const u64 num_pages = | 1407 | const u64 num_pages = |
| 1395 | ((addr + size - 1) >> Memory::PAGE_BITS) - (addr >> Memory::PAGE_BITS) + 1; | 1408 | ((addr + size - 1) >> Memory::PAGE_BITS) - (addr >> Memory::PAGE_BITS) + 1; |
| 1396 | const u64 page_start = addr >> Memory::PAGE_BITS; | 1409 | const u64 page_start = addr >> Memory::PAGE_BITS; |
| @@ -1406,8 +1419,10 @@ void RasterizerCacheOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int del | |||
| 1406 | const auto interval = pair.first & pages_interval; | 1419 | const auto interval = pair.first & pages_interval; |
| 1407 | const int count = pair.second; | 1420 | const int count = pair.second; |
| 1408 | 1421 | ||
| 1409 | const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS; | 1422 | const Tegra::GPUVAddr interval_start_addr = boost::icl::first(interval) |
| 1410 | const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS; | 1423 | << Memory::PAGE_BITS; |
| 1424 | const Tegra::GPUVAddr interval_end_addr = boost::icl::last_next(interval) | ||
| 1425 | << Memory::PAGE_BITS; | ||
| 1411 | const u64 interval_size = interval_end_addr - interval_start_addr; | 1426 | const u64 interval_size = interval_end_addr - interval_start_addr; |
| 1412 | 1427 | ||
| 1413 | if (delta > 0 && count == delta) | 1428 | if (delta > 0 && count == delta) |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index bf0fabb29..5f77f4e61 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -17,12 +17,14 @@ | |||
| 17 | #ifdef __GNUC__ | 17 | #ifdef __GNUC__ |
| 18 | #pragma GCC diagnostic pop | 18 | #pragma GCC diagnostic pop |
| 19 | #endif | 19 | #endif |
| 20 | #include <boost/optional.hpp> | ||
| 20 | #include <glad/glad.h> | 21 | #include <glad/glad.h> |
| 21 | #include "common/assert.h" | 22 | #include "common/assert.h" |
| 22 | #include "common/common_funcs.h" | 23 | #include "common/common_funcs.h" |
| 23 | #include "common/common_types.h" | 24 | #include "common/common_types.h" |
| 24 | #include "common/math_util.h" | 25 | #include "common/math_util.h" |
| 25 | #include "video_core/gpu.h" | 26 | #include "video_core/gpu.h" |
| 27 | #include "video_core/memory_manager.h" | ||
| 26 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 28 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 27 | #include "video_core/textures/texture.h" | 29 | #include "video_core/textures/texture.h" |
| 28 | 30 | ||
| @@ -30,9 +32,9 @@ struct CachedSurface; | |||
| 30 | using Surface = std::shared_ptr<CachedSurface>; | 32 | using Surface = std::shared_ptr<CachedSurface>; |
| 31 | using SurfaceSet = std::set<Surface>; | 33 | using SurfaceSet = std::set<Surface>; |
| 32 | 34 | ||
| 33 | using SurfaceRegions = boost::icl::interval_set<VAddr>; | 35 | using SurfaceRegions = boost::icl::interval_set<Tegra::GPUVAddr>; |
| 34 | using SurfaceMap = boost::icl::interval_map<VAddr, Surface>; | 36 | using SurfaceMap = boost::icl::interval_map<Tegra::GPUVAddr, Surface>; |
| 35 | using SurfaceCache = boost::icl::interval_map<VAddr, SurfaceSet>; | 37 | using SurfaceCache = boost::icl::interval_map<Tegra::GPUVAddr, SurfaceSet>; |
| 36 | 38 | ||
| 37 | using SurfaceInterval = SurfaceCache::interval_type; | 39 | using SurfaceInterval = SurfaceCache::interval_type; |
| 38 | static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() && | 40 | static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() && |
| @@ -277,6 +279,8 @@ struct SurfaceParams { | |||
| 277 | return pixels * GetFormatBpp(pixel_format) / CHAR_BIT; | 279 | return pixels * GetFormatBpp(pixel_format) / CHAR_BIT; |
| 278 | } | 280 | } |
| 279 | 281 | ||
| 282 | VAddr GetCpuAddr() const; | ||
| 283 | |||
| 280 | bool ExactMatch(const SurfaceParams& other_surface) const; | 284 | bool ExactMatch(const SurfaceParams& other_surface) const; |
| 281 | bool CanSubRect(const SurfaceParams& sub_surface) const; | 285 | bool CanSubRect(const SurfaceParams& sub_surface) const; |
| 282 | bool CanExpand(const SurfaceParams& expanded_surface) const; | 286 | bool CanExpand(const SurfaceParams& expanded_surface) const; |
| @@ -285,8 +289,9 @@ struct SurfaceParams { | |||
| 285 | MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const; | 289 | MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const; |
| 286 | MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const; | 290 | MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const; |
| 287 | 291 | ||
| 288 | VAddr addr = 0; | 292 | Tegra::GPUVAddr addr = 0; |
| 289 | VAddr end = 0; | 293 | Tegra::GPUVAddr end = 0; |
| 294 | boost::optional<VAddr> cpu_addr; | ||
| 290 | u64 size = 0; | 295 | u64 size = 0; |
| 291 | 296 | ||
| 292 | u32 width = 0; | 297 | u32 width = 0; |
| @@ -332,8 +337,8 @@ struct CachedSurface : SurfaceParams { | |||
| 332 | size_t gl_buffer_size = 0; | 337 | size_t gl_buffer_size = 0; |
| 333 | 338 | ||
| 334 | // Read/Write data in Switch memory to/from gl_buffer | 339 | // Read/Write data in Switch memory to/from gl_buffer |
| 335 | void LoadGLBuffer(VAddr load_start, VAddr load_end); | 340 | void LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr load_end); |
| 336 | void FlushGLBuffer(VAddr flush_start, VAddr flush_end); | 341 | void FlushGLBuffer(Tegra::GPUVAddr flush_start, Tegra::GPUVAddr flush_end); |
| 337 | 342 | ||
| 338 | // Upload/Download data in gl_buffer in/to this surface's texture | 343 | // Upload/Download data in gl_buffer in/to this surface's texture |
| 339 | void UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, | 344 | void UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, |
| @@ -381,10 +386,10 @@ public: | |||
| 381 | SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params); | 386 | SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params); |
| 382 | 387 | ||
| 383 | /// Write any cached resources overlapping the region back to memory (if dirty) | 388 | /// Write any cached resources overlapping the region back to memory (if dirty) |
| 384 | void FlushRegion(VAddr addr, u64 size, Surface flush_surface = nullptr); | 389 | void FlushRegion(Tegra::GPUVAddr addr, u64 size, Surface flush_surface = nullptr); |
| 385 | 390 | ||
| 386 | /// Mark region as being invalidated by region_owner (nullptr if Switch memory) | 391 | /// Mark region as being invalidated by region_owner (nullptr if Switch memory) |
| 387 | void InvalidateRegion(VAddr addr, u64 size, const Surface& region_owner); | 392 | void InvalidateRegion(Tegra::GPUVAddr addr, u64 size, const Surface& region_owner); |
| 388 | 393 | ||
| 389 | /// Flush all cached resources tracked by this cache manager | 394 | /// Flush all cached resources tracked by this cache manager |
| 390 | void FlushAll(); | 395 | void FlushAll(); |
| @@ -393,7 +398,7 @@ private: | |||
| 393 | void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface); | 398 | void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface); |
| 394 | 399 | ||
| 395 | /// Update surface's texture for given region when necessary | 400 | /// Update surface's texture for given region when necessary |
| 396 | void ValidateSurface(const Surface& surface, VAddr addr, u64 size); | 401 | void ValidateSurface(const Surface& surface, Tegra::GPUVAddr addr, u64 size); |
| 397 | 402 | ||
| 398 | /// Create a new surface | 403 | /// Create a new surface |
| 399 | Surface CreateSurface(const SurfaceParams& params); | 404 | Surface CreateSurface(const SurfaceParams& params); |
| @@ -405,7 +410,7 @@ private: | |||
| 405 | void UnregisterSurface(const Surface& surface); | 410 | void UnregisterSurface(const Surface& surface); |
| 406 | 411 | ||
| 407 | /// Increase/decrease the number of surface in pages touching the specified region | 412 | /// Increase/decrease the number of surface in pages touching the specified region |
| 408 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta); | 413 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); |
| 409 | 414 | ||
| 410 | SurfaceCache surface_cache; | 415 | SurfaceCache surface_cache; |
| 411 | PageMap cached_pages; | 416 | PageMap cached_pages; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index baff2c7af..a266e21cf 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -152,7 +152,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf | |||
| 152 | screen_info.display_texture = screen_info.texture.resource.handle; | 152 | screen_info.display_texture = screen_info.texture.resource.handle; |
| 153 | screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); | 153 | screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); |
| 154 | 154 | ||
| 155 | Rasterizer()->FlushRegion(framebuffer_addr, size_in_bytes); | 155 | Memory::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes, |
| 156 | Memory::FlushMode::Flush); | ||
| 156 | 157 | ||
| 157 | VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4, | 158 | VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4, |
| 158 | Memory::GetPointer(framebuffer_addr), | 159 | Memory::GetPointer(framebuffer_addr), |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index e0509f0ce..9c3ae875c 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/memory.h" | ||
| 7 | #include "video_core/textures/decoders.h" | 8 | #include "video_core/textures/decoders.h" |
| 8 | #include "video_core/textures/texture.h" | 9 | #include "video_core/textures/texture.h" |
| 9 | 10 | ||