summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-02-08 19:40:32 -0400
committerGravatar FernandoS272019-02-27 21:58:39 -0400
commit44ea2810e422c6b53e56b26fc8aa918c48b80c8b (patch)
tree5524e8379eed1bda7016bcff05d268991ddc4ae9 /src
parentrasterizer_cache_gl: Notify on framebuffer change (diff)
downloadyuzu-44ea2810e422c6b53e56b26fc8aa918c48b80c8b.tar.gz
yuzu-44ea2810e422c6b53e56b26fc8aa918c48b80c8b.tar.xz
yuzu-44ea2810e422c6b53e56b26fc8aa918c48b80c8b.zip
rasterizer_cache: mark reinterpreted surfaces and add ability to reload marked surfaces on next use.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h73
2 files changed, 78 insertions, 0 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 2d2bbd6ac..fe81ff227 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -1007,6 +1007,8 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
1007 if (surface) { 1007 if (surface) {
1008 if (surface->GetSurfaceParams().IsCompatibleSurface(params)) { 1008 if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
1009 // Use the cached surface as-is 1009 // Use the cached surface as-is
1010 if (surface->MustReload())
1011 LoadSurface(surface);
1010 return surface; 1012 return surface;
1011 } else if (preserve_contents) { 1013 } else if (preserve_contents) {
1012 // If surface parameters changed and we care about keeping the previous data, recreate 1014 // If surface parameters changed and we care about keeping the previous data, recreate
@@ -1014,6 +1016,9 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
1014 Surface new_surface{RecreateSurface(surface, params)}; 1016 Surface new_surface{RecreateSurface(surface, params)};
1015 Unregister(surface); 1017 Unregister(surface);
1016 Register(new_surface); 1018 Register(new_surface);
1019 if (new_surface->IsUploaded()) {
1020 RegisterReinterpretSurface(new_surface);
1021 }
1017 return new_surface; 1022 return new_surface;
1018 } else { 1023 } else {
1019 // Delete the old surface before creating a new one to prevent collisions. 1024 // Delete the old surface before creating a new one to prevent collisions.
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index cc27fefb5..0b4d720e2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -347,6 +347,10 @@ public:
347 return cached_size_in_bytes; 347 return cached_size_in_bytes;
348 } 348 }
349 349
350 std::size_t GetMemorySize() const {
351 return memory_size;
352 }
353
350 void Flush() override { 354 void Flush() override {
351 FlushGLBuffer(); 355 FlushGLBuffer();
352 } 356 }
@@ -396,6 +400,26 @@ public:
396 Tegra::Texture::SwizzleSource swizzle_z, 400 Tegra::Texture::SwizzleSource swizzle_z,
397 Tegra::Texture::SwizzleSource swizzle_w); 401 Tegra::Texture::SwizzleSource swizzle_w);
398 402
403 void MarkReinterpreted() {
404 reinterpreted = true;
405 }
406
407 bool IsReinterpreted() {
408 return reinterpreted;
409 }
410
411 void MarkForReload(bool reload) {
412 must_reload = reload;
413 }
414
415 bool MustReload() {
416 return must_reload;
417 }
418
419 bool IsUploaded() {
420 return params.identity == SurfaceParams::SurfaceClass::Uploaded;
421 }
422
399private: 423private:
400 void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); 424 void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
401 425
@@ -409,6 +433,9 @@ private:
409 GLenum gl_internal_format{}; 433 GLenum gl_internal_format{};
410 std::size_t cached_size_in_bytes{}; 434 std::size_t cached_size_in_bytes{};
411 std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; 435 std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
436 std::size_t memory_size;
437 bool reinterpreted = false;
438 bool must_reload = false;
412}; 439};
413 440
414class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { 441class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
@@ -469,6 +496,9 @@ private:
469 OGLFramebuffer read_framebuffer; 496 OGLFramebuffer read_framebuffer;
470 OGLFramebuffer draw_framebuffer; 497 OGLFramebuffer draw_framebuffer;
471 498
499 bool run_texception_pass = false;
500 bool texception = false;
501
472 /// Use a Pixel Buffer Object to download the previous texture and then upload it to the new one 502 /// Use a Pixel Buffer Object to download the previous texture and then upload it to the new one
473 /// using the new format. 503 /// using the new format.
474 OGLBuffer copy_pbo; 504 OGLBuffer copy_pbo;
@@ -476,6 +506,49 @@ private:
476 std::array<Surface, Maxwell::NumRenderTargets> last_color_buffers; 506 std::array<Surface, Maxwell::NumRenderTargets> last_color_buffers;
477 std::array<Surface, Maxwell::NumRenderTargets> current_color_buffers; 507 std::array<Surface, Maxwell::NumRenderTargets> current_color_buffers;
478 Surface last_depth_buffer; 508 Surface last_depth_buffer;
509
510 using SurfaceIntervalCache = boost::icl::interval_map<VAddr, Surface>;
511 using SurfaceInterval = typename IntervalCache::interval_type;
512
513 static auto GetReinterpretInterval(const Surface& object) {
514 return SurfaceInterval::right_open(object->GetAddr() + 1,
515 object->GetAddr() + object->GetMemorySize() - 1);
516 }
517
518 // Reinterpreted surfaces are very fragil as the game may keep rendering into them.
519 SurfaceIntervalCache reinterpreted_surfaces;
520
521 void RegisterReinterpretSurface(Surface r_surface) {
522 auto interval = GetReinterpretInterval(r_surface);
523 reinterpreted_surfaces.insert({interval, r_surface});
524 r_surface->MarkReinterpreted();
525 run_texception_pass = true;
526 }
527
528 Surface CollideOnReinterpretedSurface(VAddr addr) const {
529 const SurfaceInterval interval{addr};
530 for (auto& pair :
531 boost::make_iterator_range(reinterpreted_surfaces.equal_range(interval))) {
532 return pair.second;
533 }
534 return nullptr;
535 }
536
537protected:
538 void Register(const Surface& object) {
539 RasterizerCache<Surface>::Register(object);
540 }
541
542 /// Unregisters an object from the cache
543 void Unregister(const Surface& object) {
544 const auto& params = object->GetSurfaceParams();
545 if (object->IsReinterpreted()) {
546 auto interval = GetReinterpretInterval(object);
547 reinterpreted_surfaces.erase(interval);
548 }
549 RasterizerCache<Surface>::Unregister(object);
550 }
551
479}; 552};
480 553
481} // namespace OpenGL 554} // namespace OpenGL