Compare commits

..

8 Commits

Author SHA1 Message Date
ReinUsesLisp
d1ba243c9e gl_framebuffer_cache: Implement framebuffer cache texture invalidation 2019-04-02 20:49:44 -03:00
ReinUsesLisp
2b22077aa4 gl_framebuffer_cache: Move framebuffer cache to its own file and use hashed map 2019-04-02 20:47:28 -03:00
bunnei
57279e1981 Merge pull request #2313 from lioncash/reslimit
kernel/resource_limit: Remove the name member from resource limits
2019-04-02 16:03:54 -04:00
Mat M
628153cccd Merge pull request #2316 from ReinUsesLisp/fixup-process
process: Fix up compilation
2019-04-02 00:46:00 -04:00
ReinUsesLisp
592a24ae53 process: Fix up compilation 2019-04-02 01:44:32 -03:00
bunnei
29df6bbbd3 Merge pull request #2281 from lioncash/memory
kernel/codeset: Make CodeSet's memory data member a regular std::vector
2019-04-01 22:20:05 -04:00
Lioncash
d09e98f566 kernel/resource_limit: Remove the name member from resource limits
This doesn't really provide any benefit to the resource limit interface.
There's no way for callers to any of the service functions for resource
limits to provide a custom name, so all created instances of resource
limits other than the system resource limit would have a name of
"Unknown".

The system resource limit itself is already trivially identifiable from
its limit values, so there's no real need to take up space in the object to
identify one object meaningfully out of N total objects.
2019-04-01 16:49:28 -04:00
Lioncash
c0a01f3adc kernel/codeset: Make CodeSet's memory data member a regular std::vector
The use of a shared_ptr is an implementation detail of the VMManager
itself when mapping memory. Because of that, we shouldn't require all
users of the CodeSet to have to allocate the shared_ptr ahead of time.
It's intended that CodeSet simply pass in the required direct data, and
that the memory manager takes care of it from that point on.

This means we just do the shared pointer allocation in a single place,
when loading modules, as opposed to in each loader.
2019-03-22 18:43:46 -04:00
28 changed files with 264 additions and 120 deletions

View File

@@ -5,7 +5,6 @@
#pragma once
#include <cstddef>
#include <memory>
#include <vector>
#include "common/common_types.h"
@@ -78,7 +77,7 @@ struct CodeSet final {
}
/// The overall data that backs this code set.
std::shared_ptr<std::vector<u8>> memory;
std::vector<u8> memory;
/// The segments that comprise this code set.
std::array<Segment, 3> segments;

View File

@@ -115,7 +115,7 @@ struct KernelCore::Impl {
// Creates the default system resource limit
void InitializeSystemResourceLimit(KernelCore& kernel) {
system_resource_limit = ResourceLimit::Create(kernel, "System");
system_resource_limit = ResourceLimit::Create(kernel);
// If setting the default system values fails, then something seriously wrong has occurred.
ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x200000000)

View File

@@ -218,11 +218,13 @@ void Process::FreeTLSSlot(VAddr tls_address) {
}
void Process::LoadModule(CodeSet module_, VAddr base_addr) {
const auto memory = std::make_shared<std::vector<u8>>(std::move(module_.memory));
const auto MapSegment = [&](const CodeSet::Segment& segment, VMAPermission permissions,
MemoryState memory_state) {
const auto vma = vm_manager
.MapMemoryBlock(segment.addr + base_addr, module_.memory,
segment.offset, segment.size, memory_state)
.MapMemoryBlock(segment.addr + base_addr, memory, segment.offset,
segment.size, memory_state)
.Unwrap();
vm_manager.Reprotect(vma, permissions);
};
@@ -232,7 +234,7 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
MapSegment(module_.RODataSegment(), VMAPermission::Read, MemoryState::CodeData);
MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData);
code_memory_size += module_.memory->size();
code_memory_size += module_.memory.size();
// Clear instruction cache in CPU JIT
system.InvalidateCpuInstructionCaches();
@@ -247,7 +249,7 @@ void Process::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "Object unavailable!");
}
bool Process::ShouldWait(const Thread* thread) const {
bool Process::ShouldWait(Thread* thread) const {
return !is_signaled;
}

View File

@@ -237,7 +237,7 @@ private:
~Process() override;
/// Checks if the specified thread should wait until this process is available.
bool ShouldWait(const Thread* thread) const override;
bool ShouldWait(Thread* thread) const override;
/// Acquires/locks this process for the specified thread if it's available.
void Acquire(Thread* thread) override;

View File

@@ -14,7 +14,7 @@ namespace Kernel {
ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {}
ReadableEvent::~ReadableEvent() = default;
bool ReadableEvent::ShouldWait(const Thread* thread) const {
bool ReadableEvent::ShouldWait(Thread* thread) const {
return !signaled;
}

View File

@@ -36,7 +36,7 @@ public:
return HANDLE_TYPE;
}
bool ShouldWait(const Thread* thread) const override;
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
/// Unconditionally clears the readable event's state.

View File

@@ -16,11 +16,8 @@ constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
ResourceLimit::~ResourceLimit() = default;
SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel, std::string name) {
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
resource_limit->name = std::move(name);
return resource_limit;
SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) {
return new ResourceLimit(kernel);
}
s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {

View File

@@ -31,16 +31,14 @@ constexpr bool IsValidResourceType(ResourceType type) {
class ResourceLimit final : public Object {
public:
/**
* Creates a resource limit object.
*/
static SharedPtr<ResourceLimit> Create(KernelCore& kernel, std::string name = "Unknown");
/// Creates a resource limit object.
static SharedPtr<ResourceLimit> Create(KernelCore& kernel);
std::string GetTypeName() const override {
return "ResourceLimit";
}
std::string GetName() const override {
return name;
return GetTypeName();
}
static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
@@ -95,9 +93,6 @@ private:
ResourceArray limits{};
/// Current resource limit values.
ResourceArray values{};
/// Name of resource limit object.
std::string name;
};
} // namespace Kernel

View File

@@ -30,7 +30,7 @@ void ServerPort::AppendPendingSession(SharedPtr<ServerSession> pending_session)
pending_sessions.push_back(std::move(pending_session));
}
bool ServerPort::ShouldWait(const Thread* thread) const {
bool ServerPort::ShouldWait(Thread* thread) const {
// If there are no pending sessions, we wait until a new one is added.
return pending_sessions.empty();
}

View File

@@ -75,7 +75,7 @@ public:
/// waiting to be accepted by this port.
void AppendPendingSession(SharedPtr<ServerSession> pending_session);
bool ShouldWait(const Thread* thread) const override;
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
private:

View File

@@ -46,7 +46,7 @@ ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelCore& kernel, st
return MakeResult(std::move(server_session));
}
bool ServerSession::ShouldWait(const Thread* thread) const {
bool ServerSession::ShouldWait(Thread* thread) const {
// Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
if (parent->client == nullptr)
return false;

View File

@@ -82,7 +82,7 @@ public:
*/
ResultCode HandleSyncRequest(SharedPtr<Thread> thread);
bool ShouldWait(const Thread* thread) const override;
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;

View File

@@ -28,7 +28,7 @@
namespace Kernel {
bool Thread::ShouldWait(const Thread* thread) const {
bool Thread::ShouldWait(Thread* thread) const {
return status != ThreadStatus::Dead;
}
@@ -229,16 +229,16 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
context.cpu_registers[1] = output;
}
s32 Thread::GetWaitObjectIndex(const WaitObject* object) const {
s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything");
const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1);
}
VAddr Thread::GetCommandBufferAddress() const {
// Offset from the start of TLS at which the IPC command buffer begins.
constexpr u64 command_header_offset = 0x80;
return GetTLSAddress() + command_header_offset;
static constexpr int CommandHeaderOffset = 0x80;
return GetTLSAddress() + CommandHeaderOffset;
}
void Thread::SetStatus(ThreadStatus new_status) {
@@ -367,7 +367,7 @@ void Thread::ChangeScheduler() {
system.CpuCore(processor_id).PrepareReschedule();
}
bool Thread::AllWaitObjectsReady() const {
bool Thread::AllWaitObjectsReady() {
return std::none_of(
wait_objects.begin(), wait_objects.end(),
[this](const SharedPtr<WaitObject>& object) { return object->ShouldWait(this); });

View File

@@ -111,7 +111,7 @@ public:
return HANDLE_TYPE;
}
bool ShouldWait(const Thread* thread) const override;
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
/**
@@ -205,7 +205,7 @@ public:
* object in the list.
* @param object Object to query the index of.
*/
s32 GetWaitObjectIndex(const WaitObject* object) const;
s32 GetWaitObjectIndex(WaitObject* object) const;
/**
* Stops a thread, invalidating it from further use
@@ -299,7 +299,7 @@ public:
}
/// Determines whether all the objects this thread is waiting on are ready.
bool AllWaitObjectsReady() const;
bool AllWaitObjectsReady();
const MutexWaitingThreads& GetMutexWaitingThreads() const {
return wait_mutex_threads;

View File

@@ -24,7 +24,7 @@ public:
* @param thread The thread about which we're deciding.
* @return True if the current thread should wait due to this object being unavailable
*/
virtual bool ShouldWait(const Thread* thread) const = 0;
virtual bool ShouldWait(Thread* thread) const = 0;
/// Acquire/lock the object for the specified thread if it is available
virtual void Acquire(Thread* thread) = 0;

View File

@@ -341,7 +341,7 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
}
codeset.entrypoint = base_addr + header->e_entry;
codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image));
codeset.memory = std::move(program_image);
LOG_DEBUG(Loader, "Done loading.");

View File

@@ -187,7 +187,7 @@ static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data,
program_image.resize(static_cast<u32>(program_image.size()) + bss_size);
// Load codeset for current process
codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image));
codeset.memory = std::move(program_image);
process.LoadModule(std::move(codeset), load_base);
// Register module with GDBStub

View File

@@ -161,7 +161,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
}
// Load codeset for current process
codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image));
codeset.memory = std::move(program_image);
process.LoadModule(std::move(codeset), load_base);
// Register module with GDBStub

View File

@@ -36,6 +36,8 @@ add_library(video_core STATIC
renderer_base.h
renderer_opengl/gl_buffer_cache.cpp
renderer_opengl/gl_buffer_cache.h
renderer_opengl/gl_framebuffer_cache.cpp
renderer_opengl/gl_framebuffer_cache.h
renderer_opengl/gl_global_cache.cpp
renderer_opengl/gl_global_cache.h
renderer_opengl/gl_primitive_assembler.cpp

View File

@@ -0,0 +1,97 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <tuple>
#include "common/cityhash.h"
#include "common/scope_exit.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_state.h"
namespace OpenGL {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
std::size_t FramebufferCacheKey::Hash() const {
static_assert(sizeof(*this) % sizeof(u64) == 0, "Unaligned struct");
return static_cast<std::size_t>(
Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this)));
}
bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const {
return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count,
zeta) == std::tie(rhs.is_single_buffer, rhs.stencil_enable,
rhs.color_attachments, rhs.colors, rhs.colors_count,
rhs.zeta);
}
FramebufferCacheOpenGLImpl::FramebufferCacheOpenGLImpl() = default;
FramebufferCacheOpenGLImpl::~FramebufferCacheOpenGLImpl() = default;
GLuint FramebufferCacheOpenGLImpl::GetFramebuffer(const FramebufferCacheKey& key) {
const auto [entry, is_cache_miss] = cache.try_emplace(key);
auto& framebuffer{entry->second};
if (is_cache_miss) {
framebuffer = CreateFramebuffer(key);
}
return framebuffer.handle;
}
void FramebufferCacheOpenGLImpl::InvalidateTexture(GLuint texture) {
for (auto it = cache.begin(); it != cache.end();) {
it = TryTextureInvalidation(texture, it);
}
}
OGLFramebuffer FramebufferCacheOpenGLImpl::CreateFramebuffer(const FramebufferCacheKey& key) {
OGLFramebuffer framebuffer;
framebuffer.Create();
// TODO(Rodrigo): Use DSA here after Nvidia fixes their framebuffer DSA bugs.
local_state.draw.draw_framebuffer = framebuffer.handle;
local_state.ApplyFramebufferState();
if (key.is_single_buffer) {
if (key.color_attachments[0] != GL_NONE) {
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, key.color_attachments[0], key.colors[0], 0);
}
glDrawBuffer(key.color_attachments[0]);
} else {
for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
if (key.colors[index]) {
glFramebufferTexture(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
key.colors[index], 0);
}
}
glDrawBuffers(key.colors_count, key.color_attachments.data());
}
if (key.zeta) {
const GLenum zeta_attachment =
key.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, zeta_attachment, key.zeta, 0);
}
return framebuffer;
}
FramebufferCacheOpenGLImpl::CacheType::iterator FramebufferCacheOpenGLImpl::TryTextureInvalidation(
GLuint texture, CacheType::iterator it) {
const auto& [key, framebuffer] = *it;
const std::size_t count = key.is_single_buffer ? 1 : static_cast<std::size_t>(key.colors_count);
for (std::size_t i = 0; i < count; ++i) {
if (texture == key.colors[i]) {
return cache.erase(it);
}
}
if (texture == key.zeta) {
return cache.erase(it);
}
return ++it;
}
} // namespace OpenGL

View File

@@ -0,0 +1,82 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <cstddef>
#include <memory>
#include <unordered_map>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
namespace OpenGL {
class FramebufferCacheOpenGLImpl;
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
struct alignas(sizeof(u64)) FramebufferCacheKey {
bool is_single_buffer = false;
bool stencil_enable = false;
std::array<GLenum, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_attachments{};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
u32 colors_count = 0;
GLuint zeta = 0;
std::size_t Hash() const;
bool operator==(const FramebufferCacheKey& rhs) const;
bool operator!=(const FramebufferCacheKey& rhs) const {
return !operator==(rhs);
}
};
} // namespace OpenGL
namespace std {
template <>
struct hash<OpenGL::FramebufferCacheKey> {
std::size_t operator()(const OpenGL::FramebufferCacheKey& k) const noexcept {
return k.Hash();
}
};
} // namespace std
namespace OpenGL {
class FramebufferCacheOpenGLImpl {
public:
FramebufferCacheOpenGLImpl();
~FramebufferCacheOpenGLImpl();
/// Returns and caches a framebuffer with the passed arguments.
GLuint GetFramebuffer(const FramebufferCacheKey& key);
/// Invalidates a texture inside the cache.
void InvalidateTexture(GLuint texture);
private:
using CacheType = std::unordered_map<FramebufferCacheKey, OGLFramebuffer>;
/// Returns a new framebuffer from the passed arguments.
OGLFramebuffer CreateFramebuffer(const FramebufferCacheKey& key);
/// Attempts to destroy the framebuffer cache entry in `it` and returns the next one.
CacheType::iterator TryTextureInvalidation(GLuint texture, CacheType::iterator it);
OpenGLState local_state;
CacheType cache;
};
} // namespace OpenGL

View File

@@ -80,29 +80,11 @@ struct DrawParameters {
}
};
struct FramebufferCacheKey {
bool is_single_buffer = false;
bool stencil_enable = false;
std::array<GLenum, Maxwell::NumRenderTargets> color_attachments{};
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
u32 colors_count = 0;
GLuint zeta = 0;
auto Tie() const {
return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count,
zeta);
}
bool operator<(const FramebufferCacheKey& rhs) const {
return Tie() < rhs.Tie();
}
};
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
: framebuffer_cache{std::make_shared<FramebufferCacheOpenGLImpl>()},
res_cache{*this, framebuffer_cache}, shader_cache{*this, system},
global_cache{*this}, system{system}, screen_info{info},
buffer_cache(*this, STREAM_BUFFER_SIZE) {
// Create sampler objects
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
@@ -373,44 +355,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
gpu.dirty_flags.shaders = false;
}
void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey,
OpenGLState& current_state) {
const auto [entry, is_cache_miss] = framebuffer_cache.try_emplace(fbkey);
auto& framebuffer = entry->second;
if (is_cache_miss)
framebuffer.Create();
current_state.draw.draw_framebuffer = framebuffer.handle;
current_state.ApplyFramebufferState();
if (!is_cache_miss)
return;
if (fbkey.is_single_buffer) {
if (fbkey.color_attachments[0] != GL_NONE) {
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, fbkey.color_attachments[0], fbkey.colors[0],
0);
}
glDrawBuffer(fbkey.color_attachments[0]);
} else {
for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
if (fbkey.colors[index]) {
glFramebufferTexture(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
fbkey.colors[index], 0);
}
}
glDrawBuffers(fbkey.colors_count, fbkey.color_attachments.data());
}
if (fbkey.zeta) {
GLenum zeta_attachment =
fbkey.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, zeta_attachment, fbkey.zeta, 0);
}
}
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
const auto& regs = system.GPU().Maxwell3D().regs;
@@ -570,7 +514,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
}
SetupCachedFramebuffer(fbkey, current_state);
current_state.draw.draw_framebuffer = framebuffer_cache->GetFramebuffer(fbkey);
SyncViewport(current_state);
return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};

View File

@@ -24,6 +24,7 @@
#include "video_core/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_global_cache.h"
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
@@ -46,7 +47,6 @@ namespace OpenGL {
struct ScreenInfo;
struct DrawParameters;
struct FramebufferCacheKey;
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
@@ -209,6 +209,7 @@ private:
OpenGLState state;
FramebufferCacheOpenGL framebuffer_cache;
RasterizerCacheOpenGL res_cache;
ShaderCacheOpenGL shader_cache;
GlobalRegionCacheOpenGL global_cache;
@@ -223,7 +224,6 @@ private:
OGLVertexArray>
vertex_array_cache;
std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache;
FramebufferConfigState current_framebuffer_config_state;
std::pair<bool, bool> current_depth_stencil_usage{};
@@ -247,8 +247,6 @@ private:
void SetupShaders(GLenum primitive_mode);
void SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, OpenGLState& current_state);
enum class AccelDraw { Disabled, Arrays, Indexed };
AccelDraw accelerate_draw = AccelDraw::Disabled;

View File

@@ -561,8 +561,9 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
dst_surface->MarkAsModified(true, *this);
}
CachedSurface::CachedSurface(const SurfaceParams& params)
: RasterizerCacheObject{params.host_ptr}, params{params},
CachedSurface::CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_)
: RasterizerCacheObject{params.host_ptr}, framebuffer_cache{std::move(framebuffer_cache_)},
texture{framebuffer_cache}, discrepant_view{framebuffer_cache}, params{params},
gl_target{SurfaceTargetToGL(params.target)}, cached_size_in_bytes{params.size_in_bytes} {
const auto optional_cpu_addr{
@@ -611,6 +612,8 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.gpu_addr, params.IdentityString());
}
CachedSurface::~CachedSurface() = default;
MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64));
void CachedSurface::LoadGLBuffer() {
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
@@ -852,8 +855,9 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
}
}
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer)
: RasterizerCache{rasterizer} {
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
FramebufferCacheOpenGL framebuffer_cache)
: RasterizerCache{rasterizer}, framebuffer_cache{std::move(framebuffer_cache)} {
read_framebuffer.Create();
draw_framebuffer.Create();
copy_pbo.Create();
@@ -961,7 +965,7 @@ Surface RasterizerCacheOpenGL::GetUncachedSurface(const SurfaceParams& params) {
Surface surface{TryGetReservedSurface(params)};
if (!surface) {
// No reserved surface available, create a new one and reserve it
surface = std::make_shared<CachedSurface>(params);
surface = std::make_shared<CachedSurface>(params, framebuffer_cache);
ReserveSurface(surface);
}
return surface;

View File

@@ -18,6 +18,7 @@
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/surface.h"
@@ -350,7 +351,8 @@ class RasterizerOpenGL;
class CachedSurface final : public RasterizerCacheObject {
public:
explicit CachedSurface(const SurfaceParams& params);
explicit CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_);
~CachedSurface();
VAddr GetCpuAddr() const override {
return cpu_addr;
@@ -426,6 +428,7 @@ private:
void EnsureTextureDiscrepantView();
FramebufferCacheOpenGL framebuffer_cache;
OGLTexture texture;
OGLTexture discrepant_view;
std::vector<std::vector<u8>> gl_buffer;
@@ -434,7 +437,7 @@ private:
GLenum gl_internal_format{};
std::size_t cached_size_in_bytes{};
std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
std::size_t memory_size;
std::size_t memory_size{};
bool reinterpreted = false;
bool must_reload = false;
VAddr cpu_addr{};
@@ -442,7 +445,8 @@ private:
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
public:
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer);
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
FramebufferCacheOpenGL framebuffer_cache);
/// Get a surface based on the texture configuration
Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config,
@@ -499,6 +503,8 @@ private:
/// destroyed when used with different surface parameters.
std::unordered_map<SurfaceReserveKey, Surface> surface_reserve;
FramebufferCacheOpenGL framebuffer_cache;
OGLFramebuffer read_framebuffer;
OGLFramebuffer draw_framebuffer;

View File

@@ -6,6 +6,7 @@
#include <glad/glad.h>
#include "common/common_types.h"
#include "common/microprofile.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_state.h"
@@ -15,6 +16,16 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R
namespace OpenGL {
OGLTexture::OGLTexture(FramebufferCacheOpenGL framebuffer_cache)
: framebuffer_cache{std::move(framebuffer_cache)} {}
OGLTexture::OGLTexture(OGLTexture&& o) noexcept
: handle{std::exchange(o.handle, 0)}, framebuffer_cache{std::move(o.framebuffer_cache)} {}
OGLTexture::~OGLTexture() {
Release();
}
void OGLTexture::Create(GLenum target) {
if (handle != 0)
return;
@@ -28,6 +39,9 @@ void OGLTexture::Release() {
return;
MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
if (framebuffer_cache) {
framebuffer_cache->InvalidateTexture(handle);
}
glDeleteTextures(1, &handle);
OpenGLState::GetCurState().UnbindTexture(handle).Apply();
handle = 0;

View File

@@ -4,6 +4,7 @@
#pragma once
#include <memory>
#include <utility>
#include <glad/glad.h>
#include "common/common_types.h"
@@ -11,15 +12,15 @@
namespace OpenGL {
class FramebufferCacheOpenGLImpl;
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
class OGLTexture : private NonCopyable {
public:
OGLTexture() = default;
explicit OGLTexture(FramebufferCacheOpenGL framebuffer_cache);
OGLTexture(OGLTexture&& o) noexcept;
OGLTexture(OGLTexture&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
~OGLTexture() {
Release();
}
~OGLTexture();
OGLTexture& operator=(OGLTexture&& o) noexcept {
Release();
@@ -34,6 +35,9 @@ public:
void Release();
GLuint handle = 0;
private:
FramebufferCacheOpenGL framebuffer_cache;
};
class OGLSampler : private NonCopyable {

View File

@@ -28,7 +28,7 @@ namespace OpenGL {
/// Structure used for storing information about the textures for the Switch screen
struct TextureInfo {
OGLTexture resource;
OGLTexture resource{nullptr};
GLsizei width;
GLsizei height;
GLenum gl_format;