video_core: Use interval map for cached_pages

* Also eliminate g_memory in hardware renderers
This commit is contained in:
GPUCode
2023-02-04 12:57:57 +02:00
parent 938ec204f5
commit fd9525acc2
12 changed files with 161 additions and 155 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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,8 +326,8 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) {
return false;
}
const u8* index_data = VideoCore::g_memory->GetPhysicalPointer(
regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
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);
@@ -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);

View File

@@ -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;

View File

@@ -273,9 +273,10 @@ 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,
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>();
@@ -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();

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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,8 +429,8 @@ 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() +
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);
@@ -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);

View File

@@ -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;

View File

@@ -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);