Miscallenious fixes to gl backend and qt frontend (#6834)

* renderer_gl: Make rasterizer normal class member

* It doesn't need to be heap allocated anymore

* gl_rasterizer: Remove default_texture

* It's unused

* gl_rasterizer: General cleanup

* gl_rasterizer: Lower case lambdas

* Match style with review comments from vulkan backend

* rasterizer_cache: Prevent memory leak

* Since the switch from shared_ptr these surfaces were no longer being destroyed properly. Use our garbage collector for that purpose to destroy it safely for both backends

* rasterizer_cache: Make temp copy of old surface

* The custom surface would override the memory region of the old region resulting in garbage data, this ensures the custom surface is constructed correctly

* citra_qt: Manually create dialog tabs

* Allows for custom constructors which is very useful. While at it, global state is now eliminated from configuration

* citra_qt: Eliminate global system usage

* core: Remove global system usage in memory and HIO

* citra_qt: Use qOverload

* tests: Run clang format

* gl_texture_runtime: Fix surface scaling
This commit is contained in:
GPUCode
2023-08-02 01:40:39 +03:00
committed by GitHub
parent 970f2284d8
commit 88ea66053e
73 changed files with 594 additions and 555 deletions

View File

@@ -503,26 +503,27 @@ SurfaceId RasterizerCache<T>::GetTextureSurface(const Pica::Texture::TextureInfo
const u32 min_width = info.width >> max_level;
const u32 min_height = info.height >> max_level;
if (min_width % 8 != 0 || min_height % 8 != 0) {
if (min_width % 4 == 0 && min_height % 4 == 0) {
const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
Surface& src_surface = slot_surfaces[src_surface_id];
params.res_scale = src_surface.res_scale;
SurfaceId tmp_surface_id = CreateSurface(params);
Surface& tmp_surface = slot_surfaces[tmp_surface_id];
const TextureBlit blit = {
.src_level = src_surface.LevelOf(params.addr),
.dst_level = 0,
.src_rect = rect,
.dst_rect = tmp_surface.GetScaledRect(),
};
runtime.BlitTextures(src_surface, tmp_surface, blit);
return tmp_surface_id;
if (min_width % 4 != 0 || min_height % 4 != 0) {
LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width,
min_height);
return NULL_SURFACE_ID;
}
const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
Surface& src_surface = slot_surfaces[src_surface_id];
LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, min_height);
return NULL_SURFACE_ID;
params.res_scale = src_surface.res_scale;
SurfaceId tmp_surface_id = CreateSurface(params);
Surface& tmp_surface = slot_surfaces[tmp_surface_id];
sentenced.emplace_back(tmp_surface_id, frame_tick);
const TextureBlit blit = {
.src_level = src_surface.LevelOf(params.addr),
.dst_level = 0,
.src_rect = rect,
.dst_rect = tmp_surface.GetScaledRect(),
};
runtime.BlitTextures(src_surface, tmp_surface, blit);
return tmp_surface_id;
}
if (info.width != (min_width << max_level) || info.height != (min_height << max_level)) {
LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) does not support required mipmap level ({})",
@@ -1054,8 +1055,9 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv
ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom),
"Surface is not suitable for custom upload, aborting!");
if (!surface.IsCustom()) {
const SurfaceBase old_surface{surface};
const SurfaceId old_id =
slot_surfaces.swap_and_insert(surface_id, runtime, surface, material);
slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material);
sentenced.emplace_back(old_id, frame_tick);
}
surface.UploadCustom(material, level);

View File

@@ -105,7 +105,7 @@ SurfaceInterval SurfaceBase::GetCopyableInterval(const SurfaceParams& params) co
return result;
}
Extent SurfaceBase::RealExtent(bool scaled) {
Extent SurfaceBase::RealExtent(bool scaled) const {
const bool is_custom = IsCustom();
u32 real_width = width;
u32 real_height = height;

View File

@@ -41,7 +41,7 @@ public:
ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format);
/// Returns the internal surface extent.
Extent RealExtent(bool scaled = true);
Extent RealExtent(bool scaled = true) const;
/// Returns true if the surface contains a custom material with a normal map.
bool HasNormalMap() const noexcept;

View File

@@ -73,12 +73,12 @@ public:
return height * res_scale;
}
[[nodiscard]] Common::Rectangle<u32> GetRect() const noexcept {
return {0, height, width, 0};
[[nodiscard]] Common::Rectangle<u32> GetRect(u32 level = 0) const noexcept {
return {0, height >> level, width >> level, 0};
}
[[nodiscard]] Common::Rectangle<u32> GetScaledRect() const noexcept {
return {0, GetScaledHeight(), GetScaledWidth(), 0};
[[nodiscard]] Common::Rectangle<u32> GetScaledRect(u32 level = 0) const noexcept {
return {0, GetScaledHeight() >> level, GetScaledWidth() >> level, 0};
}
[[nodiscard]] u32 PixelsInBytes(u32 size) const noexcept {

View File

@@ -9,10 +9,6 @@
#include "common/common_types.h"
#include "core/hw/gpu.h"
namespace OpenGL {
struct ScreenInfo;
}
namespace Pica::Shader {
struct OutputVertex;
} // namespace Pica::Shader
@@ -76,14 +72,6 @@ public:
return false;
}
/// Attempt to use a faster method to display the framebuffer to screen
virtual bool AccelerateDisplay([[maybe_unused]] const GPU::Regs::FramebufferConfig& config,
[[maybe_unused]] PAddr framebuffer_addr,
[[maybe_unused]] u32 pixel_stride,
[[maybe_unused]] OpenGL::ScreenInfo& screen_info) {
return false;
}
/// Attempt to draw using hardware shaders
virtual bool AccelerateDrawBatch([[maybe_unused]] bool is_indexed) {
return false;

View File

@@ -42,7 +42,7 @@ public:
virtual ~RendererBase();
/// Returns the rasterizer owned by the renderer
virtual VideoCore::RasterizerInterface* Rasterizer() const = 0;
virtual VideoCore::RasterizerInterface* Rasterizer() = 0;
/// Finalize rendering the guest frame and draw into the presentation texture
virtual void SwapBuffers() = 0;
@@ -72,9 +72,6 @@ public:
/// Ends the current frame
void EndFrame();
// Getter/setter functions:
// ------------------------
f32 GetCurrentFPS() const {
return current_fps;
}

View File

@@ -12,9 +12,9 @@
#include "video_core/regs_rasterizer.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/texture/texture_decode.h"
#include "video_core/video_core.h"
namespace OpenGL {
@@ -76,8 +76,9 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) {
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
VideoCore::CustomTexManager& custom_tex_manager,
VideoCore::RendererBase& renderer, Driver& driver_)
: VideoCore::RasterizerAccelerated{memory}, driver{driver_}, runtime{driver, renderer},
res_cache{memory, custom_tex_manager, runtime, regs, renderer},
: VideoCore::RasterizerAccelerated{memory}, driver{driver_},
shader_manager{renderer.GetRenderWindow(), driver, !driver.IsOpenGLES()},
runtime{driver, renderer}, res_cache{memory, custom_tex_manager, runtime, regs, renderer},
texture_buffer_size{TextureBufferSize()}, vertex_buffer{driver, GL_ARRAY_BUFFER,
VERTEX_BUFFER_SIZE},
uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE},
@@ -89,14 +90,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
state.clip_distance[0] = true;
// Create a 1x1 clear texture to use in the NULL case,
// instead of OpenGL's default of solid black
glGenTextures(1, &default_texture);
glBindTexture(GL_TEXTURE_2D, default_texture);
// For some reason alpha 0 wraps around to 1.0, so use 1/255 instead
u8 framebuffer_data[4] = {0, 0, 0, 1};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
// Generate VAO
sw_vao.Create();
hw_vao.Create();
@@ -142,9 +135,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
(GLvoid*)offsetof(HardwareVertex, view));
glEnableVertexAttribArray(ATTRIBUTE_VIEW);
// Create render framebuffer
framebuffer.Create();
// Allocate and bind texture buffer lut textures
texture_buffer_lut_lf.Create();
texture_buffer_lut_rg.Create();
@@ -165,9 +155,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
state.Apply();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle());
shader_program_manager =
std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, !GLES);
glEnable(GL_BLEND);
SyncEntireState();
@@ -181,7 +168,7 @@ void RasterizerOpenGL::TickFrame() {
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) {
shader_program_manager->LoadDiskCache(stop_loading, callback);
shader_manager.LoadDiskCache(stop_loading, callback);
}
void RasterizerOpenGL::SyncFixedState() {
@@ -277,7 +264,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
bool RasterizerOpenGL::SetupVertexShader() {
MICROPROFILE_SCOPE(OpenGL_VS);
return shader_program_manager->UseProgrammableVertexShader(regs, Pica::g_state.vs);
return shader_manager.UseProgrammableVertexShader(regs, Pica::g_state.vs);
}
bool RasterizerOpenGL::SetupGeometryShader() {
@@ -288,7 +275,7 @@ bool RasterizerOpenGL::SetupGeometryShader() {
return false;
}
shader_program_manager->UseFixedGeometryShader(regs);
shader_manager.UseFixedGeometryShader(regs);
return true;
}
@@ -302,11 +289,13 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
}
}
if (!SetupVertexShader())
if (!SetupVertexShader()) {
return false;
}
if (!SetupGeometryShader())
if (!SetupGeometryShader()) {
return false;
}
return Draw(true, is_indexed);
}
@@ -329,7 +318,7 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) {
SetupVertexArray(buffer_ptr, buffer_offset, vs_input_index_min, vs_input_index_max);
vertex_buffer.Unmap(vs_input_size);
shader_program_manager->ApplyTo(state);
shader_manager.ApplyTo(state);
state.Apply();
if (is_indexed) {
@@ -341,9 +330,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);
@@ -434,7 +423,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
// Sync and bind the shader
if (shader_dirty) {
shader_program_manager->UseFragmentShader(regs, use_custom_normal);
shader_manager.UseFragmentShader(regs, use_custom_normal);
shader_dirty = false;
}
@@ -452,9 +441,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
} else {
state.draw.vertex_array = sw_vao.handle;
state.draw.vertex_buffer = vertex_buffer.GetHandle();
shader_program_manager->UseTrivialVertexShader();
shader_program_manager->UseTrivialGeometryShader();
shader_program_manager->ApplyTo(state);
shader_manager.UseTrivialVertexShader();
shader_manager.UseTrivialGeometryShader();
shader_manager.ApplyTo(state);
state.Apply();
std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex)));
@@ -820,7 +809,7 @@ void RasterizerOpenGL::SyncBlendColor() {
void RasterizerOpenGL::SyncLogicOp() {
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
if (GLES) {
if (driver.IsOpenGLES()) {
if (!regs.framebuffer.output_merger.alphablend_enable) {
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
// Color output is disabled by logic operation. We use color write mask to skip
@@ -832,7 +821,7 @@ void RasterizerOpenGL::SyncLogicOp() {
}
void RasterizerOpenGL::SyncColorWriteMask() {
if (GLES) {
if (driver.IsOpenGLES()) {
if (!regs.framebuffer.output_merger.alphablend_enable) {
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
// Color output is disabled by logic operation. We use color write mask to skip
@@ -842,17 +831,19 @@ void RasterizerOpenGL::SyncColorWriteMask() {
}
}
auto IsColorWriteEnabled = [&](u32 value) {
auto is_color_write_enabled = [&](u32 value) {
return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE
: GL_FALSE;
};
state.color_mask.red_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.red_enable);
state.color_mask.red_enabled =
is_color_write_enabled(regs.framebuffer.output_merger.red_enable);
state.color_mask.green_enabled =
IsColorWriteEnabled(regs.framebuffer.output_merger.green_enable);
state.color_mask.blue_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.blue_enable);
is_color_write_enabled(regs.framebuffer.output_merger.green_enable);
state.color_mask.blue_enabled =
is_color_write_enabled(regs.framebuffer.output_merger.blue_enable);
state.color_mask.alpha_enabled =
IsColorWriteEnabled(regs.framebuffer.output_merger.alpha_enable);
is_color_write_enabled(regs.framebuffer.output_merger.alpha_enable);
}
void RasterizerOpenGL::SyncStencilWriteMask() {
@@ -903,12 +894,10 @@ void RasterizerOpenGL::SyncAndUploadLUTsLF() {
return;
}
u8* buffer;
GLintptr offset;
bool invalidate;
std::size_t bytes_used = 0;
glBindBuffer(GL_TEXTURE_BUFFER, texture_lf_buffer.GetHandle());
std::tie(buffer, offset, invalidate) = texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f));
const auto [buffer, offset, invalidate] =
texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f));
// Sync the lighting luts
if (uniform_block_data.lighting_lut_dirty_any || invalidate) {
@@ -973,50 +962,48 @@ void RasterizerOpenGL::SyncAndUploadLUTs() {
return;
}
u8* buffer;
GLintptr offset;
bool invalidate;
std::size_t bytes_used = 0;
glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle());
std::tie(buffer, offset, invalidate) = texture_buffer.Map(max_size, sizeof(Common::Vec4f));
const auto [buffer, offset, invalidate] = texture_buffer.Map(max_size, sizeof(Common::Vec4f));
// helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap
auto SyncProcTexValueLUT = [this, buffer, offset, invalidate, &bytes_used](
const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut,
std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) {
std::array<Common::Vec2f, 128> new_data;
std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) {
return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()};
});
const auto sync_proc_tex_value_lut =
[this, buffer = buffer, offset = offset, invalidate = invalidate,
&bytes_used](const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut,
std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) {
std::array<Common::Vec2f, 128> new_data;
std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) {
return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()};
});
if (new_data != lut_data || invalidate) {
lut_data = new_data;
std::memcpy(buffer + bytes_used, new_data.data(),
new_data.size() * sizeof(Common::Vec2f));
lut_offset = static_cast<GLint>((offset + bytes_used) / sizeof(Common::Vec2f));
uniform_block_data.dirty = true;
bytes_used += new_data.size() * sizeof(Common::Vec2f);
}
};
if (new_data != lut_data || invalidate) {
lut_data = new_data;
std::memcpy(buffer + bytes_used, new_data.data(),
new_data.size() * sizeof(Common::Vec2f));
lut_offset = static_cast<GLint>((offset + bytes_used) / sizeof(Common::Vec2f));
uniform_block_data.dirty = true;
bytes_used += new_data.size() * sizeof(Common::Vec2f);
}
};
// Sync the proctex noise lut
if (uniform_block_data.proctex_noise_lut_dirty || invalidate) {
SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data,
uniform_block_data.data.proctex_noise_lut_offset);
sync_proc_tex_value_lut(Pica::g_state.proctex.noise_table, proctex_noise_lut_data,
uniform_block_data.data.proctex_noise_lut_offset);
uniform_block_data.proctex_noise_lut_dirty = false;
}
// Sync the proctex color map
if (uniform_block_data.proctex_color_map_dirty || invalidate) {
SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data,
uniform_block_data.data.proctex_color_map_offset);
sync_proc_tex_value_lut(Pica::g_state.proctex.color_map_table, proctex_color_map_data,
uniform_block_data.data.proctex_color_map_offset);
uniform_block_data.proctex_color_map_dirty = false;
}
// Sync the proctex alpha map
if (uniform_block_data.proctex_alpha_map_dirty || invalidate) {
SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data,
uniform_block_data.data.proctex_alpha_map_offset);
sync_proc_tex_value_lut(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data,
uniform_block_data.data.proctex_alpha_map_offset);
uniform_block_data.proctex_alpha_map_dirty = false;
}
@@ -1070,28 +1057,25 @@ void RasterizerOpenGL::SyncAndUploadLUTs() {
}
void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) {
// glBindBufferRange below also changes the generic buffer binding point, so we sync the state
// first
// glBindBufferRange also changes the generic buffer binding point, so we sync the state first.
state.draw.uniform_buffer = uniform_buffer.GetHandle();
state.Apply();
bool sync_vs = accelerate_draw;
bool sync_fs = uniform_block_data.dirty;
if (!sync_vs && !sync_fs)
const bool sync_vs = accelerate_draw;
const bool sync_fs = uniform_block_data.dirty;
if (!sync_vs && !sync_fs) {
return;
}
std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs;
std::size_t used_bytes = 0;
u8* uniforms;
GLintptr offset;
bool invalidate;
std::tie(uniforms, offset, invalidate) =
const auto [uniforms, offset, invalidate] =
uniform_buffer.Map(uniform_size, uniform_buffer_alignment);
if (sync_vs) {
Pica::Shader::VSUniformData vs_uniforms;
vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs);
vs_uniforms.uniforms.SetFromRegs(regs.vs, Pica::g_state.vs);
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::VS),
uniform_buffer.GetHandle(), offset + used_bytes,

View File

@@ -6,7 +6,6 @@
#include "core/hw/gpu.h"
#include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_cache/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/regs_texturing.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
@@ -24,6 +23,8 @@ class CustomTexManager;
namespace OpenGL {
struct ScreenInfo;
class Driver;
class ShaderProgramManager;
@@ -48,7 +49,7 @@ public:
bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override;
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override;
bool AccelerateDisplay(const GPU::Regs::FramebufferConfig& config, PAddr framebuffer_addr,
u32 pixel_stride, ScreenInfo& screen_info) override;
u32 pixel_stride, ScreenInfo& screen_info);
bool AccelerateDrawBatch(bool is_indexed) override;
private:
@@ -132,10 +133,9 @@ private:
private:
Driver& driver;
OpenGLState state;
GLuint default_texture;
ShaderProgramManager shader_manager;
TextureRuntime runtime;
RasterizerCache res_cache;
std::unique_ptr<ShaderProgramManager> shader_program_manager;
OGLVertexArray sw_vao; // VAO for software shader draw
OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw
@@ -147,7 +147,6 @@ private:
OGLStreamBuffer index_buffer;
OGLStreamBuffer texture_buffer;
OGLStreamBuffer texture_lf_buffer;
OGLFramebuffer framebuffer;
GLint uniform_buffer_alignment;
std::size_t uniform_size_aligned_vs;
std::size_t uniform_size_aligned_fs;

View File

@@ -8,7 +8,6 @@
#include <thread>
#include <unordered_map>
#include <variant>
#include "common/scope_exit.h"
#include "core/frontend/emu_window.h"
#include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_vars.h"

View File

@@ -528,13 +528,13 @@ void Surface::ScaleUp(u32 new_scale) {
textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple,
DebugName(true));
VideoCore::TextureBlit blit = {
.src_rect = GetRect(),
.dst_rect = GetScaledRect(),
};
for (u32 level = 0; level < levels; level++) {
blit.src_level = level;
blit.dst_level = level;
const VideoCore::TextureBlit blit = {
.src_level = level,
.dst_level = level,
.src_rect = GetRect(level),
.dst_rect = GetScaledRect(level),
};
BlitScale(blit, true);
}
}

View File

@@ -78,7 +78,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window,
Frontend::EmuWindow* secondary_window)
: VideoCore::RendererBase{system, window, secondary_window}, driver{system.TelemetrySession()},
frame_dumper{system, window} {
rasterizer{system.Memory(), system.CustomTexManager(), *this, driver}, frame_dumper{system,
window} {
const bool has_debug_tool = driver.HasDebugTool();
window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
if (secondary_window) {
@@ -86,8 +87,6 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window
}
frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>();
InitOpenGLObjects();
rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), system.CustomTexManager(),
*this, driver);
}
RendererOpenGL::~RendererOpenGL() = default;
@@ -121,8 +120,7 @@ void RendererOpenGL::SwapBuffers() {
EndFrame();
prev_state.Apply();
rasterizer->TickFrame();
rasterizer.TickFrame();
}
void RendererOpenGL::RenderScreenshot() {
@@ -273,8 +271,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram
// only allows rows to have a memory alignement of 4.
ASSERT(pixel_stride % 4 == 0);
if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr,
static_cast<u32>(pixel_stride), screen_info)) {
if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast<u32>(pixel_stride),
screen_info)) {
// Reset the screen info's display texture to its own permanent texture
screen_info.display_texture = screen_info.texture.resource.handle;
screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
@@ -903,7 +901,7 @@ void RendererOpenGL::CleanupVideoDumping() {
}
void RendererOpenGL::Sync() {
rasterizer->SyncEntireState();
rasterizer.SyncEntireState();
}
} // namespace OpenGL

View File

@@ -46,8 +46,8 @@ public:
Frontend::EmuWindow* secondary_window);
~RendererOpenGL() override;
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override {
return rasterizer.get();
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override {
return &rasterizer;
}
void SwapBuffers() override;
@@ -86,8 +86,8 @@ private:
private:
Driver driver;
RasterizerOpenGL rasterizer;
OpenGLState state;
std::unique_ptr<RasterizerOpenGL> rasterizer;
// OpenGL object IDs
OGLVertexArray vertex_array;

View File

@@ -13,7 +13,7 @@ namespace SwRenderer {
RendererSoftware::RendererSoftware(Core::System& system, Frontend::EmuWindow& window)
: VideoCore::RendererBase{system, window, nullptr}, memory{system.Memory()},
rasterizer{std::make_unique<RasterizerSoftware>(system.Memory())} {}
rasterizer{system.Memory()} {}
RendererSoftware::~RendererSoftware() = default;

View File

@@ -24,8 +24,8 @@ public:
explicit RendererSoftware(Core::System& system, Frontend::EmuWindow& window);
~RendererSoftware() override;
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override {
return rasterizer.get();
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override {
return &rasterizer;
}
[[nodiscard]] const ScreenInfo& Screen(VideoCore::ScreenId id) const noexcept {
@@ -42,7 +42,7 @@ private:
private:
Memory::MemorySystem& memory;
std::unique_ptr<RasterizerSoftware> rasterizer;
RasterizerSoftware rasterizer;
std::array<ScreenInfo, 3> screen_infos{};
};