video_core: Use interval map for cached_pages
* Also eliminate g_memory in hardware renderers
This commit is contained in:
@@ -88,98 +88,6 @@ void RasterizerAccelerated::AddTriangle(const Pica::Shader::OutputVertex& v0,
|
||||
vertex_batch.emplace_back(v2, AreQuaternionsOpposite(v0.quat, v2.quat));
|
||||
}
|
||||
|
||||
void RasterizerAccelerated::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
|
||||
const u32 page_start = addr >> Memory::CITRA_PAGE_BITS;
|
||||
const u32 page_end = ((addr + size - 1) >> Memory::CITRA_PAGE_BITS) + 1;
|
||||
|
||||
u32 uncache_start_addr = 0;
|
||||
u32 cache_start_addr = 0;
|
||||
u32 uncache_bytes = 0;
|
||||
u32 cache_bytes = 0;
|
||||
|
||||
for (u32 page = page_start; page != page_end; page++) {
|
||||
auto& count = cached_pages.at(page);
|
||||
|
||||
// Ensure no overflow happens
|
||||
if (delta > 0) {
|
||||
ASSERT_MSG(count < std::numeric_limits<u16>::max(), "Count will overflow!");
|
||||
} else if (delta < 0) {
|
||||
ASSERT_MSG(count > 0, "Count will underflow!");
|
||||
} else {
|
||||
ASSERT_MSG(false, "Delta must be non-zero!");
|
||||
}
|
||||
|
||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||
count += delta;
|
||||
|
||||
// Assume delta is either -1 or 1
|
||||
if (count == 0) {
|
||||
if (uncache_bytes == 0) {
|
||||
uncache_start_addr = page << Memory::CITRA_PAGE_BITS;
|
||||
}
|
||||
|
||||
uncache_bytes += Memory::CITRA_PAGE_SIZE;
|
||||
} else if (uncache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes,
|
||||
false);
|
||||
uncache_bytes = 0;
|
||||
}
|
||||
|
||||
if (count == 1 && delta > 0) {
|
||||
if (cache_bytes == 0) {
|
||||
cache_start_addr = page << Memory::CITRA_PAGE_BITS;
|
||||
}
|
||||
|
||||
cache_bytes += Memory::CITRA_PAGE_SIZE;
|
||||
} else if (cache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes, true);
|
||||
|
||||
cache_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (uncache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, false);
|
||||
}
|
||||
|
||||
if (cache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes, true);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerAccelerated::ClearAll(bool flush) {
|
||||
// Force flush all surfaces from the cache
|
||||
if (flush) {
|
||||
FlushRegion(0x0, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
u32 uncache_start_addr = 0;
|
||||
u32 uncache_bytes = 0;
|
||||
|
||||
for (u32 page = 0; page != cached_pages.size(); page++) {
|
||||
auto& count = cached_pages.at(page);
|
||||
|
||||
// Assume delta is either -1 or 1
|
||||
if (count != 0) {
|
||||
if (uncache_bytes == 0) {
|
||||
uncache_start_addr = page << Memory::CITRA_PAGE_BITS;
|
||||
}
|
||||
|
||||
uncache_bytes += Memory::CITRA_PAGE_SIZE;
|
||||
} else if (uncache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes,
|
||||
false);
|
||||
uncache_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (uncache_bytes > 0) {
|
||||
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, false);
|
||||
}
|
||||
|
||||
cached_pages = {};
|
||||
}
|
||||
|
||||
RasterizerAccelerated::VertexArrayInfo RasterizerAccelerated::AnalyzeVertexArray(
|
||||
bool is_indexed, u32 stride_alignment) {
|
||||
const auto& regs = Pica::g_state.regs;
|
||||
|
@@ -18,18 +18,13 @@ public:
|
||||
|
||||
void AddTriangle(const Pica::Shader::OutputVertex& v0, const Pica::Shader::OutputVertex& v1,
|
||||
const Pica::Shader::OutputVertex& v2) override;
|
||||
|
||||
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) override;
|
||||
void NotifyPicaRegisterChanged(u32 id) override;
|
||||
void ClearAll(bool flush) override;
|
||||
|
||||
/// Syncs entire status to match PICA registers
|
||||
void SyncEntireState() override;
|
||||
|
||||
protected:
|
||||
/// Sync fixed-function pipeline state
|
||||
virtual void SyncFixedState() = 0;
|
||||
|
||||
protected:
|
||||
/// Notifies that a fixed function PICA register changed to the video backend
|
||||
virtual void NotifyFixedFunctionPicaRegisterChanged(u32 id) = 0;
|
||||
|
||||
@@ -137,7 +132,6 @@ protected:
|
||||
VertexArrayInfo AnalyzeVertexArray(bool is_indexed, u32 stride_alignment = 1);
|
||||
|
||||
protected:
|
||||
std::array<u16, 0x30000> cached_pages{};
|
||||
std::vector<HardwareVertex> vertex_batch;
|
||||
bool shader_dirty = true;
|
||||
|
||||
|
@@ -12,8 +12,8 @@
|
||||
#include "common/alignment.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/memory.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/rasterizer_accelerated.h"
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_params.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
inline auto RangeFromInterval(auto& map, SurfaceInterval interval) {
|
||||
inline auto RangeFromInterval(auto& map, const auto& interval) {
|
||||
return boost::make_iterator_range(map.equal_range(interval));
|
||||
}
|
||||
|
||||
@@ -70,9 +70,10 @@ private:
|
||||
|
||||
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
|
||||
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
|
||||
using PageMap = boost::icl::interval_map<u32, int>;
|
||||
|
||||
public:
|
||||
RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer, TextureRuntime& runtime);
|
||||
RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime);
|
||||
~RasterizerCache() = default;
|
||||
|
||||
/// Get the best surface match (and its match type) for the given flags
|
||||
@@ -124,6 +125,9 @@ public:
|
||||
/// Flush all cached resources tracked by this cache manager
|
||||
void FlushAll();
|
||||
|
||||
/// Clear all cached resources tracked by this cache manager
|
||||
void ClearAll(bool flush);
|
||||
|
||||
private:
|
||||
void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
|
||||
|
||||
@@ -159,23 +163,24 @@ private:
|
||||
/// Remove surface from the cache
|
||||
void UnregisterSurface(const Surface& surface);
|
||||
|
||||
/// Increase/decrease the number of surface in pages touching the specified region
|
||||
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
|
||||
|
||||
private:
|
||||
VideoCore::RasterizerAccelerated& rasterizer;
|
||||
Memory::MemorySystem& memory;
|
||||
TextureRuntime& runtime;
|
||||
SurfaceCache surface_cache;
|
||||
PageMap cached_pages;
|
||||
SurfaceMap dirty_regions;
|
||||
SurfaceSet remove_surfaces;
|
||||
u16 resolution_scale_factor;
|
||||
std::vector<std::function<void()>> download_queue;
|
||||
std::vector<u8> staging_buffer;
|
||||
std::unordered_map<TextureCubeConfig, Surface> texture_cube_cache;
|
||||
std::recursive_mutex mutex;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
RasterizerCache<T>::RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer,
|
||||
TextureRuntime& runtime)
|
||||
: rasterizer{rasterizer}, runtime{runtime} {
|
||||
RasterizerCache<T>::RasterizerCache(Memory::MemorySystem& memory_, TextureRuntime& runtime_)
|
||||
: memory{memory_}, runtime{runtime_} {
|
||||
resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
|
||||
}
|
||||
|
||||
@@ -910,7 +915,7 @@ void RasterizerCache<T>::UploadSurface(const Surface& surface, SurfaceInterval i
|
||||
|
||||
const auto staging = runtime.FindStaging(
|
||||
load_info.width * load_info.height * surface->GetInternalBytesPerPixel(), true);
|
||||
MemoryRef source_ptr = VideoCore::g_memory->GetPhysicalRef(load_info.addr);
|
||||
MemoryRef source_ptr = memory.GetPhysicalRef(load_info.addr);
|
||||
if (!source_ptr) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
@@ -944,7 +949,7 @@ void RasterizerCache<T>::DownloadSurface(const Surface& surface, SurfaceInterval
|
||||
|
||||
surface->Download(download, staging);
|
||||
|
||||
MemoryRef dest_ptr = VideoCore::g_memory->GetPhysicalRef(flush_start);
|
||||
MemoryRef dest_ptr = memory.GetPhysicalRef(flush_start);
|
||||
if (!dest_ptr) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
@@ -964,7 +969,7 @@ void RasterizerCache<T>::DownloadFillSurface(const Surface& surface, SurfaceInte
|
||||
const u32 flush_end = boost::icl::last_next(interval);
|
||||
ASSERT(flush_start >= surface->addr && flush_end <= surface->end);
|
||||
|
||||
MemoryRef dest_ptr = VideoCore::g_memory->GetPhysicalRef(flush_start);
|
||||
MemoryRef dest_ptr = memory.GetPhysicalRef(flush_start);
|
||||
if (!dest_ptr) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
@@ -1062,9 +1067,32 @@ bool RasterizerCache<T>::ValidateByReinterpretation(const Surface& surface, Surf
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::FlushRegion(PAddr addr, u32 size, Surface flush_surface) {
|
||||
std::lock_guard lock{mutex};
|
||||
void RasterizerCache<T>::ClearAll(bool flush) {
|
||||
const auto flush_interval = PageMap::interval_type::right_open(0x0, 0xFFFFFFFF);
|
||||
// Force flush all surfaces from the cache
|
||||
if (flush) {
|
||||
FlushRegion(0x0, 0xFFFFFFFF);
|
||||
}
|
||||
// Unmark all of the marked pages
|
||||
for (auto& pair : RangeFromInterval(cached_pages, flush_interval)) {
|
||||
const auto interval = pair.first & flush_interval;
|
||||
|
||||
const PAddr interval_start_addr = boost::icl::first(interval) << Memory::CITRA_PAGE_BITS;
|
||||
const PAddr interval_end_addr = boost::icl::last_next(interval) << Memory::CITRA_PAGE_BITS;
|
||||
const u32 interval_size = interval_end_addr - interval_start_addr;
|
||||
|
||||
memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
|
||||
}
|
||||
|
||||
// Remove the whole cache without really looking at it.
|
||||
cached_pages -= flush_interval;
|
||||
dirty_regions -= SurfaceInterval(0x0, 0xFFFFFFFF);
|
||||
surface_cache -= SurfaceInterval(0x0, 0xFFFFFFFF);
|
||||
remove_surfaces.clear();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::FlushRegion(PAddr addr, u32 size, Surface flush_surface) {
|
||||
if (size == 0) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
@@ -1116,8 +1144,6 @@ void RasterizerCache<T>::FlushAll() {
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::InvalidateRegion(PAddr addr, u32 size, const Surface& region_owner) {
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
if (size == 0) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
@@ -1189,28 +1215,60 @@ auto RasterizerCache<T>::CreateSurface(SurfaceParams& params) -> Surface {
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::RegisterSurface(const Surface& surface) {
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
if (surface->registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
surface->registered = true;
|
||||
surface_cache.add({surface->GetInterval(), SurfaceSet{surface}});
|
||||
rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, 1);
|
||||
UpdatePagesCachedCount(surface->addr, surface->size, 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::UnregisterSurface(const Surface& surface) {
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
if (!surface->registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
surface->registered = false;
|
||||
rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
||||
UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
||||
surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void RasterizerCache<T>::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
|
||||
const u32 num_pages =
|
||||
((addr + size - 1) >> Memory::CITRA_PAGE_BITS) - (addr >> Memory::CITRA_PAGE_BITS) + 1;
|
||||
const u32 page_start = addr >> Memory::CITRA_PAGE_BITS;
|
||||
const u32 page_end = page_start + num_pages;
|
||||
|
||||
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to
|
||||
// subtract after iterating
|
||||
const auto pages_interval = PageMap::interval_type::right_open(page_start, page_end);
|
||||
if (delta > 0) {
|
||||
cached_pages.add({pages_interval, delta});
|
||||
}
|
||||
|
||||
for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
|
||||
const auto interval = pair.first & pages_interval;
|
||||
const int count = pair.second;
|
||||
|
||||
const PAddr interval_start_addr = boost::icl::first(interval) << Memory::CITRA_PAGE_BITS;
|
||||
const PAddr interval_end_addr = boost::icl::last_next(interval) << Memory::CITRA_PAGE_BITS;
|
||||
const u32 interval_size = interval_end_addr - interval_start_addr;
|
||||
|
||||
if (delta > 0 && count == delta) {
|
||||
memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
|
||||
} else if (delta < 0 && count == -delta) {
|
||||
memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
|
||||
} else {
|
||||
ASSERT(count >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (delta < 0) {
|
||||
cached_pages.add({pages_interval, delta});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace VideoCore
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include "video_core/renderer_opengl/gl_driver.h"
|
||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||
#include "video_core/renderer_opengl/gl_vars.h"
|
||||
#include "video_core/renderer_opengl/pica_to_gl.h"
|
||||
#include "video_core/renderer_opengl/renderer_opengl.h"
|
||||
#include "video_core/video_core.h"
|
||||
@@ -25,8 +24,9 @@ constexpr std::size_t INDEX_BUFFER_SIZE = 1 * 1024 * 1024;
|
||||
constexpr std::size_t UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024;
|
||||
constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024;
|
||||
|
||||
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver)
|
||||
: driver{driver}, runtime{driver}, res_cache{*this, runtime},
|
||||
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window,
|
||||
Driver& driver_)
|
||||
: memory{memory_}, driver{driver_}, runtime{driver}, res_cache{memory, runtime},
|
||||
shader_program_manager{emu_window, driver, !driver.IsOpenGLES()},
|
||||
vertex_buffer{GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE}, uniform_buffer{GL_UNIFORM_BUFFER,
|
||||
UNIFORM_BUFFER_SIZE},
|
||||
@@ -210,7 +210,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
|
||||
u32 data_size = loader.byte_count * vertex_num;
|
||||
|
||||
res_cache.FlushRegion(data_addr, data_size, nullptr);
|
||||
std::memcpy(array_ptr, VideoCore::g_memory->GetPhysicalPointer(data_addr), data_size);
|
||||
std::memcpy(array_ptr, memory.GetPhysicalPointer(data_addr), data_size);
|
||||
|
||||
array_ptr += data_size;
|
||||
buffer_offset += data_size;
|
||||
@@ -326,9 +326,9 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const u8* index_data = VideoCore::g_memory->GetPhysicalPointer(
|
||||
regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
||||
regs.pipeline.index_array.offset);
|
||||
const u8* index_data =
|
||||
memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
||||
regs.pipeline.index_array.offset);
|
||||
std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4);
|
||||
std::memcpy(buffer_ptr, index_data, index_buffer_size);
|
||||
index_buffer.Unmap(index_buffer_size);
|
||||
@@ -772,6 +772,10 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(PAddr addr, u32 size) {
|
||||
res_cache.InvalidateRegion(addr, size, nullptr);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::ClearAll(bool flush) {
|
||||
res_cache.ClearAll(flush);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
|
||||
bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) {
|
||||
MICROPROFILE_SCOPE(OpenGL_Blits);
|
||||
|
@@ -11,6 +11,10 @@
|
||||
#include "video_core/renderer_opengl/gl_stream_buffer.h"
|
||||
#include "video_core/renderer_opengl/gl_texture_runtime.h"
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
@@ -24,7 +28,8 @@ class ShaderProgramManager;
|
||||
|
||||
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
|
||||
public:
|
||||
explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver);
|
||||
explicit RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
|
||||
Driver& driver);
|
||||
~RasterizerOpenGL() override;
|
||||
|
||||
void LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
@@ -35,6 +40,7 @@ public:
|
||||
void FlushRegion(PAddr addr, u32 size) override;
|
||||
void InvalidateRegion(PAddr addr, u32 size) override;
|
||||
void FlushAndInvalidateRegion(PAddr addr, u32 size) override;
|
||||
void ClearAll(bool flush) override;
|
||||
bool AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) override;
|
||||
bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override;
|
||||
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override;
|
||||
@@ -132,6 +138,7 @@ private:
|
||||
bool SetupGeometryShader();
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Driver& driver;
|
||||
OpenGLState state;
|
||||
TextureRuntime runtime;
|
||||
|
@@ -273,10 +273,11 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
|
||||
return matrix;
|
||||
}
|
||||
|
||||
RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window)
|
||||
: RendererBase{window, secondary_window}, driver{Settings::values.graphics_api.GetValue() ==
|
||||
Settings::GraphicsAPI::OpenGLES,
|
||||
Settings::values.renderer_debug.GetValue()},
|
||||
RendererOpenGL::RendererOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window)
|
||||
: RendererBase{window, secondary_window}, memory{memory_},
|
||||
driver{Settings::values.graphics_api.GetValue() == Settings::GraphicsAPI::OpenGLES,
|
||||
Settings::values.renderer_debug.GetValue()},
|
||||
frame_dumper(Core::System::GetInstance().VideoDumper(), window) {
|
||||
window.mailbox = std::make_unique<OGLTextureMailbox>();
|
||||
if (secondary_window) {
|
||||
@@ -294,7 +295,7 @@ VideoCore::ResultStatus RendererOpenGL::Init() {
|
||||
}
|
||||
|
||||
InitOpenGLObjects();
|
||||
rasterizer = std::make_unique<RasterizerOpenGL>(render_window, driver);
|
||||
rasterizer = std::make_unique<RasterizerOpenGL>(memory, render_window, driver);
|
||||
|
||||
return VideoCore::ResultStatus::Success;
|
||||
}
|
||||
@@ -495,8 +496,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram
|
||||
screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
|
||||
|
||||
Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height);
|
||||
|
||||
const u8* framebuffer_data = VideoCore::g_memory->GetPhysicalPointer(framebuffer_addr);
|
||||
const u8* framebuffer_data = memory.GetPhysicalPointer(framebuffer_addr);
|
||||
|
||||
state.texture_units[0].texture_2d = screen_info.texture.resource.handle;
|
||||
state.Apply();
|
||||
|
@@ -16,6 +16,10 @@ namespace Layout {
|
||||
struct FramebufferLayout;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace Frontend {
|
||||
|
||||
struct Frame {
|
||||
@@ -57,7 +61,8 @@ class RasterizerOpenGL;
|
||||
|
||||
class RendererOpenGL : public RendererBase {
|
||||
public:
|
||||
explicit RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window);
|
||||
explicit RendererOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window);
|
||||
~RendererOpenGL() override;
|
||||
|
||||
VideoCore::ResultStatus Init() override;
|
||||
@@ -116,6 +121,7 @@ private:
|
||||
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Driver driver;
|
||||
OpenGLState state;
|
||||
std::unique_ptr<RasterizerOpenGL> rasterizer;
|
||||
|
@@ -100,8 +100,9 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
RendererVulkan::RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window)
|
||||
: RendererBase{window, secondary_window},
|
||||
RendererVulkan::RendererVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window)
|
||||
: RendererBase{window, secondary_window}, memory{memory_},
|
||||
telemetry_session{Core::System::GetInstance().TelemetrySession()},
|
||||
instance{window, Settings::values.physical_device.GetValue()}, scheduler{instance,
|
||||
renderpass_cache},
|
||||
@@ -110,7 +111,8 @@ RendererVulkan::RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow*
|
||||
renderpass_cache},
|
||||
vertex_buffer{instance, scheduler, vk::BufferUsageFlagBits::eVertexBuffer,
|
||||
VERTEX_BUFFER_SIZE},
|
||||
rasterizer{render_window, instance, scheduler, desc_manager, runtime, renderpass_cache} {
|
||||
rasterizer{memory, render_window, instance, scheduler,
|
||||
desc_manager, runtime, renderpass_cache} {
|
||||
Report();
|
||||
window.mailbox = std::make_unique<TextureMailbox>(instance, swapchain, renderpass_cache);
|
||||
}
|
||||
|
@@ -23,12 +23,19 @@ namespace Core {
|
||||
class TelemetrySession;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace Layout {
|
||||
struct FramebufferLayout;
|
||||
}
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
/**
|
||||
* Structure used for storing information about the textures for each 3DS screen
|
||||
**/
|
||||
struct TextureInfo {
|
||||
u32 width;
|
||||
u32 height;
|
||||
@@ -38,6 +45,9 @@ struct TextureInfo {
|
||||
VmaAllocation allocation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure used for storing information about the display target for each 3DS screen
|
||||
**/
|
||||
struct ScreenInfo {
|
||||
TextureInfo texture;
|
||||
Common::Rectangle<f32> texcoords;
|
||||
@@ -50,7 +60,8 @@ class RendererVulkan : public RendererBase {
|
||||
static constexpr std::size_t PRESENT_PIPELINES = 3;
|
||||
|
||||
public:
|
||||
explicit RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window);
|
||||
explicit RendererVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window);
|
||||
~RendererVulkan() override;
|
||||
|
||||
VideoCore::ResultStatus Init() override;
|
||||
@@ -111,6 +122,7 @@ private:
|
||||
void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Core::TelemetrySession& telemetry_session;
|
||||
|
||||
Instance instance;
|
||||
|
@@ -57,11 +57,12 @@ struct DrawParams {
|
||||
return std::min(max_size, TEXTURE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instance& instance,
|
||||
Scheduler& scheduler, DescriptorManager& desc_manager,
|
||||
TextureRuntime& runtime, RenderpassCache& renderpass_cache)
|
||||
: instance{instance}, scheduler{scheduler}, runtime{runtime},
|
||||
renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{*this, runtime},
|
||||
RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window,
|
||||
const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorManager& desc_manager, TextureRuntime& runtime,
|
||||
RenderpassCache& renderpass_cache)
|
||||
: memory{memory_}, instance{instance}, scheduler{scheduler}, runtime{runtime},
|
||||
renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{memory, runtime},
|
||||
pipeline_cache{instance, scheduler, renderpass_cache, desc_manager},
|
||||
null_surface{NULL_PARAMS, vk::Format::eR8G8B8A8Unorm, NULL_USAGE,
|
||||
vk::ImageAspectFlagBits::eColor, runtime},
|
||||
@@ -235,7 +236,7 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
|
||||
const u32 data_size = loader.byte_count * vertex_num;
|
||||
res_cache.FlushRegion(data_addr, data_size);
|
||||
|
||||
const u8* src_ptr = VideoCore::g_memory->GetPhysicalPointer(data_addr);
|
||||
const u8* src_ptr = memory.GetPhysicalPointer(data_addr);
|
||||
u8* dst_ptr = array_ptr + buffer_offset;
|
||||
|
||||
// Align stride up if required by Vulkan implementation.
|
||||
@@ -270,6 +271,9 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
|
||||
// Bind the generated bindings
|
||||
scheduler.Record([this, binding_count = layout.binding_count,
|
||||
vertex_offsets = binding_offsets](vk::CommandBuffer cmdbuf) {
|
||||
for (auto& offset : vertex_offsets) {
|
||||
ASSERT_MSG(offset != 0x8000000, "Bad offset");
|
||||
}
|
||||
cmdbuf.bindVertexBuffers(0, binding_count, vertex_buffers.data(), vertex_offsets.data());
|
||||
});
|
||||
}
|
||||
@@ -425,9 +429,9 @@ void RasterizerVulkan::SetupIndexArray() {
|
||||
const vk::IndexType index_type = native_u8 ? vk::IndexType::eUint8EXT : vk::IndexType::eUint16;
|
||||
const u32 index_buffer_size = regs.pipeline.num_vertices * (native_u8 ? 1 : 2);
|
||||
|
||||
const u8* index_data = VideoCore::g_memory->GetPhysicalPointer(
|
||||
regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
||||
regs.pipeline.index_array.offset);
|
||||
const u8* index_data =
|
||||
memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
||||
regs.pipeline.index_array.offset);
|
||||
|
||||
auto [index_ptr, index_offset, _] = stream_buffer.Map(index_buffer_size, 2);
|
||||
if (index_u8 && !native_u8) {
|
||||
@@ -852,6 +856,10 @@ void RasterizerVulkan::FlushAndInvalidateRegion(PAddr addr, u32 size) {
|
||||
res_cache.InvalidateRegion(addr, size, nullptr);
|
||||
}
|
||||
|
||||
void RasterizerVulkan::ClearAll(bool flush) {
|
||||
res_cache.ClearAll(flush);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(Vulkan_Blits, "Vulkan", "Blits", MP_RGB(100, 100, 255));
|
||||
bool RasterizerVulkan::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) {
|
||||
MICROPROFILE_SCOPE(Vulkan_Blits);
|
||||
|
@@ -15,6 +15,10 @@ namespace Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
struct ScreenInfo;
|
||||
@@ -58,9 +62,10 @@ class RasterizerVulkan : public VideoCore::RasterizerAccelerated {
|
||||
friend class RendererVulkan;
|
||||
|
||||
public:
|
||||
explicit RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instance& instance,
|
||||
Scheduler& scheduler, DescriptorManager& desc_manager,
|
||||
TextureRuntime& runtime, RenderpassCache& renderpass_cache);
|
||||
explicit RasterizerVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
|
||||
const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorManager& desc_manager, TextureRuntime& runtime,
|
||||
RenderpassCache& renderpass_cache);
|
||||
~RasterizerVulkan() override;
|
||||
|
||||
void LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
@@ -71,6 +76,7 @@ public:
|
||||
void FlushRegion(PAddr addr, u32 size) override;
|
||||
void InvalidateRegion(PAddr addr, u32 size) override;
|
||||
void FlushAndInvalidateRegion(PAddr addr, u32 size) override;
|
||||
void ClearAll(bool flush) override;
|
||||
bool AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) override;
|
||||
bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override;
|
||||
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override;
|
||||
@@ -151,6 +157,7 @@ private:
|
||||
vk::Sampler CreateSampler(const SamplerInfo& info);
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
TextureRuntime& runtime;
|
||||
|
@@ -40,10 +40,10 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar
|
||||
case Settings::GraphicsAPI::OpenGL:
|
||||
case Settings::GraphicsAPI::OpenGLES:
|
||||
OpenGL::GLES = graphics_api == Settings::GraphicsAPI::OpenGLES;
|
||||
g_renderer = std::make_unique<OpenGL::RendererOpenGL>(emu_window, secondary_window);
|
||||
g_renderer = std::make_unique<OpenGL::RendererOpenGL>(memory, emu_window, secondary_window);
|
||||
break;
|
||||
case Settings::GraphicsAPI::Vulkan:
|
||||
g_renderer = std::make_unique<Vulkan::RendererVulkan>(emu_window, secondary_window);
|
||||
g_renderer = std::make_unique<Vulkan::RendererVulkan>(memory, emu_window, secondary_window);
|
||||
break;
|
||||
default:
|
||||
LOG_CRITICAL(Render, "Invalid graphics API enum value {}", graphics_api);
|
||||
|
Reference in New Issue
Block a user