2023-04-21 09:14:55 +02:00
|
|
|
// Copyright 2023 Citra Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "video_core/rasterizer_cache/framebuffer_base.h"
|
2023-05-07 01:34:28 +02:00
|
|
|
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
|
2023-07-18 16:31:31 +02:00
|
|
|
#include "video_core/rasterizer_cache/surface_base.h"
|
2023-04-21 09:14:55 +02:00
|
|
|
#include "video_core/renderer_opengl/gl_blit_helper.h"
|
|
|
|
|
|
|
|
namespace VideoCore {
|
2023-04-27 06:38:28 +02:00
|
|
|
struct Material;
|
2023-04-21 09:14:55 +02:00
|
|
|
class RendererBase;
|
2023-04-27 06:38:28 +02:00
|
|
|
} // namespace VideoCore
|
2023-04-21 09:14:55 +02:00
|
|
|
|
|
|
|
namespace OpenGL {
|
|
|
|
|
|
|
|
struct FormatTuple {
|
|
|
|
GLint internal_format;
|
|
|
|
GLenum format;
|
|
|
|
GLenum type;
|
|
|
|
|
|
|
|
bool operator==(const FormatTuple& other) const noexcept {
|
|
|
|
return std::tie(internal_format, format, type) ==
|
|
|
|
std::tie(other.internal_format, other.format, other.type);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Surface;
|
|
|
|
class Driver;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides texture manipulation functions to the rasterizer cache
|
|
|
|
* Separating this into a class makes it easier to abstract graphics API code
|
|
|
|
*/
|
|
|
|
class TextureRuntime {
|
|
|
|
friend class Surface;
|
|
|
|
friend class Framebuffer;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit TextureRuntime(const Driver& driver, VideoCore::RendererBase& renderer);
|
|
|
|
~TextureRuntime();
|
|
|
|
|
2023-08-01 02:35:41 +02:00
|
|
|
/// Returns the removal threshold ticks for the garbage collector
|
|
|
|
u32 RemoveThreshold();
|
2023-04-27 06:38:28 +02:00
|
|
|
|
2023-09-13 00:28:50 +02:00
|
|
|
/// Submits and waits for current GPU work.
|
|
|
|
void Finish() {}
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
/// Returns true if the provided pixel format cannot be used natively by the runtime.
|
|
|
|
bool NeedsConversion(VideoCore::PixelFormat pixel_format) const;
|
|
|
|
|
|
|
|
/// Maps an internal staging buffer of the provided size of pixel uploads/downloads
|
|
|
|
VideoCore::StagingData FindStaging(u32 size, bool upload);
|
|
|
|
|
|
|
|
/// Returns the OpenGL format tuple associated with the provided pixel format
|
|
|
|
const FormatTuple& GetFormatTuple(VideoCore::PixelFormat pixel_format) const;
|
2023-04-27 06:38:28 +02:00
|
|
|
const FormatTuple& GetFormatTuple(VideoCore::CustomPixelFormat pixel_format);
|
2023-04-21 09:14:55 +02:00
|
|
|
|
2023-05-07 01:34:28 +02:00
|
|
|
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
|
2023-09-13 00:28:50 +02:00
|
|
|
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
|
2023-04-21 09:14:55 +02:00
|
|
|
|
|
|
|
/// Fills the rectangle of the texture with the clear value provided
|
2023-08-08 00:10:28 +02:00
|
|
|
void ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);
|
2023-04-21 09:14:55 +02:00
|
|
|
|
|
|
|
/// Copies a rectangle of source to another rectange of dest
|
|
|
|
bool CopyTextures(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
|
|
|
|
|
|
|
|
/// Blits a rectangle of source to another rectange of dest
|
|
|
|
bool BlitTextures(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
|
|
|
|
|
|
|
|
/// Generates mipmaps for all the available levels of the texture
|
2023-04-27 06:38:28 +02:00
|
|
|
void GenerateMipmaps(Surface& surface);
|
2023-04-21 09:14:55 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
/// Returns the OpenGL driver class
|
|
|
|
const Driver& GetDriver() const {
|
|
|
|
return driver;
|
|
|
|
}
|
|
|
|
|
2023-08-08 00:10:28 +02:00
|
|
|
/// Fills the rectangle of the surface with the value provided, without an fbo.
|
|
|
|
bool ClearTextureWithoutFbo(Surface& surface, const VideoCore::TextureClear& clear);
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
private:
|
|
|
|
const Driver& driver;
|
|
|
|
BlitHelper blit_helper;
|
|
|
|
std::vector<u8> staging_buffer;
|
|
|
|
std::array<OGLFramebuffer, 3> draw_fbos;
|
|
|
|
std::array<OGLFramebuffer, 3> read_fbos;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Surface : public VideoCore::SurfaceBase {
|
|
|
|
public:
|
|
|
|
explicit Surface(TextureRuntime& runtime, const VideoCore::SurfaceParams& params);
|
2023-08-01 02:35:41 +02:00
|
|
|
explicit Surface(TextureRuntime& runtime, const VideoCore::SurfaceBase& surface,
|
|
|
|
const VideoCore::Material* material);
|
2023-04-21 09:14:55 +02:00
|
|
|
~Surface();
|
|
|
|
|
|
|
|
Surface(const Surface&) = delete;
|
|
|
|
Surface& operator=(const Surface&) = delete;
|
|
|
|
|
|
|
|
Surface(Surface&& o) noexcept = default;
|
|
|
|
Surface& operator=(Surface&& o) noexcept = default;
|
|
|
|
|
2023-05-07 01:34:28 +02:00
|
|
|
[[nodiscard]] const FormatTuple& Tuple() const noexcept {
|
2023-08-01 02:35:41 +02:00
|
|
|
return tuple;
|
2023-04-21 09:14:55 +02:00
|
|
|
}
|
|
|
|
|
2023-08-01 02:35:41 +02:00
|
|
|
/// Returns the texture handle at index, otherwise the first one if not valid.
|
|
|
|
GLuint Handle(u32 index = 1) const noexcept;
|
|
|
|
|
|
|
|
/// Returns a copy of the upscaled texture handle, used for feedback loops.
|
|
|
|
GLuint CopyHandle() noexcept;
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
/// Uploads pixel data in staging to a rectangle region of the surface texture
|
|
|
|
void Upload(const VideoCore::BufferTextureCopy& upload, const VideoCore::StagingData& staging);
|
|
|
|
|
2023-04-27 06:38:28 +02:00
|
|
|
/// Uploads the custom material to the surface allocation.
|
|
|
|
void UploadCustom(const VideoCore::Material* material, u32 level);
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
/// Downloads pixel data to staging from a rectangle region of the surface texture
|
|
|
|
void Download(const VideoCore::BufferTextureCopy& download,
|
|
|
|
const VideoCore::StagingData& staging);
|
|
|
|
|
|
|
|
/// Attaches a handle of surface to the specified framebuffer target
|
|
|
|
void Attach(GLenum target, u32 level, u32 layer, bool scaled = true);
|
|
|
|
|
2023-08-01 02:35:41 +02:00
|
|
|
/// Scales up the surface to match the new resolution scale.
|
|
|
|
void ScaleUp(u32 new_scale);
|
2023-04-27 06:38:28 +02:00
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
/// Returns the bpp of the internal surface format
|
|
|
|
u32 GetInternalBytesPerPixel() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Performs blit between the scaled/unscaled images
|
|
|
|
void BlitScale(const VideoCore::TextureBlit& blit, bool up_scale);
|
|
|
|
|
|
|
|
/// Attempts to download without using an fbo
|
|
|
|
bool DownloadWithoutFbo(const VideoCore::BufferTextureCopy& download,
|
|
|
|
const VideoCore::StagingData& staging);
|
|
|
|
|
|
|
|
private:
|
|
|
|
const Driver* driver;
|
|
|
|
TextureRuntime* runtime;
|
2023-08-01 02:35:41 +02:00
|
|
|
std::array<OGLTexture, 3> textures;
|
|
|
|
OGLTexture copy_texture;
|
|
|
|
FormatTuple tuple;
|
2023-04-21 09:14:55 +02:00
|
|
|
};
|
|
|
|
|
2023-08-01 02:35:41 +02:00
|
|
|
class Framebuffer : public VideoCore::FramebufferParams {
|
2023-04-21 09:14:55 +02:00
|
|
|
public:
|
2023-08-01 02:35:41 +02:00
|
|
|
explicit Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferParams& params,
|
|
|
|
const Surface* color, const Surface* depth_stencil);
|
2023-04-21 09:14:55 +02:00
|
|
|
~Framebuffer();
|
|
|
|
|
2023-08-01 02:35:41 +02:00
|
|
|
Framebuffer(const Framebuffer&) = delete;
|
|
|
|
Framebuffer& operator=(const Framebuffer&) = delete;
|
|
|
|
|
|
|
|
Framebuffer(Framebuffer&& o) noexcept = default;
|
|
|
|
Framebuffer& operator=(Framebuffer&& o) noexcept = default;
|
|
|
|
|
|
|
|
[[nodiscard]] u32 Scale() const noexcept {
|
|
|
|
return res_scale;
|
|
|
|
}
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
[[nodiscard]] GLuint Handle() const noexcept {
|
2023-08-01 02:35:41 +02:00
|
|
|
return framebuffer.handle;
|
2023-04-21 09:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] GLuint Attachment(VideoCore::SurfaceType type) const noexcept {
|
|
|
|
return attachments[Index(type)];
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] bool HasAttachment(VideoCore::SurfaceType type) const noexcept {
|
|
|
|
return static_cast<bool>(attachments[Index(type)]);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2023-08-01 02:35:41 +02:00
|
|
|
u32 res_scale{1};
|
2023-04-21 09:14:55 +02:00
|
|
|
std::array<GLuint, 2> attachments{};
|
2023-08-01 02:35:41 +02:00
|
|
|
OGLFramebuffer framebuffer;
|
2023-04-21 09:14:55 +02:00
|
|
|
};
|
|
|
|
|
2023-05-07 01:34:28 +02:00
|
|
|
class Sampler {
|
|
|
|
public:
|
|
|
|
explicit Sampler(TextureRuntime&, VideoCore::SamplerParams params);
|
|
|
|
~Sampler();
|
|
|
|
|
|
|
|
Sampler(const Sampler&) = delete;
|
|
|
|
Sampler& operator=(const Sampler&) = delete;
|
|
|
|
|
|
|
|
Sampler(Sampler&&) = default;
|
|
|
|
Sampler& operator=(Sampler&&) = default;
|
|
|
|
|
|
|
|
[[nodiscard]] GLuint Handle() const noexcept {
|
|
|
|
return sampler.handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
OGLSampler sampler;
|
|
|
|
};
|
|
|
|
|
2023-06-23 03:37:13 +02:00
|
|
|
class DebugScope {
|
|
|
|
public:
|
|
|
|
template <typename... T>
|
|
|
|
explicit DebugScope(TextureRuntime& runtime, Common::Vec4f color,
|
|
|
|
fmt::format_string<T...> format, T... args)
|
|
|
|
: DebugScope{runtime, color, fmt::format(format, std::forward<T>(args)...)} {}
|
|
|
|
explicit DebugScope(TextureRuntime& runtime, Common::Vec4f, std::string_view label);
|
|
|
|
~DebugScope();
|
|
|
|
|
|
|
|
private:
|
|
|
|
inline static GLuint global_scope_depth = 0;
|
|
|
|
const GLuint local_scope_depth{};
|
|
|
|
};
|
|
|
|
|
2023-05-07 01:34:28 +02:00
|
|
|
struct Traits {
|
|
|
|
using Runtime = OpenGL::TextureRuntime;
|
|
|
|
using Sampler = OpenGL::Sampler;
|
|
|
|
using Surface = OpenGL::Surface;
|
|
|
|
using Framebuffer = OpenGL::Framebuffer;
|
2023-06-23 03:37:13 +02:00
|
|
|
using DebugScope = OpenGL::DebugScope;
|
2023-05-07 01:34:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
using RasterizerCache = VideoCore::RasterizerCache<Traits>;
|
|
|
|
|
2023-04-21 09:14:55 +02:00
|
|
|
} // namespace OpenGL
|