rasterizer_cache: Remove shared_ptr usage
* Switches to yuzu's slot vector for improved memory locality.
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include "core/frontend/image_interface.h"
|
#include "core/frontend/image_interface.h"
|
||||||
#include "video_core/custom_textures/custom_tex_manager.h"
|
#include "video_core/custom_textures/custom_tex_manager.h"
|
||||||
#include "video_core/rasterizer_cache/surface_params.h"
|
#include "video_core/rasterizer_cache/surface_params.h"
|
||||||
|
#include "video_core/rasterizer_cache/utils.h"
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
|
@@ -10,9 +10,9 @@ namespace VideoCore {
|
|||||||
|
|
||||||
FramebufferBase::FramebufferBase() = default;
|
FramebufferBase::FramebufferBase() = default;
|
||||||
|
|
||||||
FramebufferBase::FramebufferBase(const Pica::Regs& regs, const SurfaceBase* const color,
|
FramebufferBase::FramebufferBase(const Pica::Regs& regs, const SurfaceBase* color, u32 color_level,
|
||||||
u32 color_level, const SurfaceBase* const depth_stencil,
|
const SurfaceBase* depth_stencil, u32 depth_level,
|
||||||
u32 depth_level, Common::Rectangle<u32> surfaces_rect) {
|
Common::Rectangle<u32> surfaces_rect) {
|
||||||
res_scale = color ? color->res_scale : (depth_stencil ? depth_stencil->res_scale : 1u);
|
res_scale = color ? color->res_scale : (depth_stencil ? depth_stencil->res_scale : 1u);
|
||||||
|
|
||||||
// Determine the draw rectangle (render area + scissor)
|
// Determine the draw rectangle (render area + scissor)
|
||||||
|
@@ -29,8 +29,8 @@ struct ViewportInfo {
|
|||||||
class FramebufferBase {
|
class FramebufferBase {
|
||||||
public:
|
public:
|
||||||
FramebufferBase();
|
FramebufferBase();
|
||||||
FramebufferBase(const Pica::Regs& regs, const SurfaceBase* const color, u32 color_level,
|
FramebufferBase(const Pica::Regs& regs, const SurfaceBase* color, u32 color_level,
|
||||||
const SurfaceBase* const depth_stencil, u32 depth_level,
|
const SurfaceBase* depth_stencil, u32 depth_level,
|
||||||
Common::Rectangle<u32> surfaces_rect);
|
Common::Rectangle<u32> surfaces_rect);
|
||||||
|
|
||||||
SurfaceParams ColorParams() const noexcept {
|
SurfaceParams ColorParams() const noexcept {
|
||||||
@@ -66,6 +66,7 @@ protected:
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case VideoCore::SurfaceType::Color:
|
case VideoCore::SurfaceType::Color:
|
||||||
return 0;
|
return 0;
|
||||||
|
case VideoCore::SurfaceType::Depth:
|
||||||
case VideoCore::SurfaceType::DepthStencil:
|
case VideoCore::SurfaceType::DepthStencil:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -51,32 +51,32 @@ class RasterizerCache {
|
|||||||
/// Address shift for caching surfaces into a hash table
|
/// Address shift for caching surfaces into a hash table
|
||||||
static constexpr u64 CITRA_PAGEBITS = 18;
|
static constexpr u64 CITRA_PAGEBITS = 18;
|
||||||
|
|
||||||
using TextureRuntime = typename T::TextureRuntime;
|
using Runtime = typename T::Runtime;
|
||||||
using Sampler = typename T::Sampler;
|
using Sampler = typename T::Sampler;
|
||||||
using SurfaceRef = std::shared_ptr<typename T::Surface>;
|
using Surface = typename T::Surface;
|
||||||
using Framebuffer = typename T::Framebuffer;
|
using Framebuffer = typename T::Framebuffer;
|
||||||
|
|
||||||
using SurfaceMap = boost::icl::interval_map<PAddr, SurfaceRef, boost::icl::partial_absorber,
|
using SurfaceMap = boost::icl::interval_map<PAddr, SurfaceId, boost::icl::partial_absorber,
|
||||||
std::less, boost::icl::inplace_plus,
|
std::less, boost::icl::inplace_plus,
|
||||||
boost::icl::inter_section, SurfaceInterval>;
|
boost::icl::inter_section, SurfaceInterval>;
|
||||||
|
|
||||||
using SurfaceRect_Tuple = std::tuple<SurfaceRef, Common::Rectangle<u32>>;
|
using SurfaceRect_Tuple = std::pair<SurfaceId, Common::Rectangle<u32>>;
|
||||||
using PageMap = boost::icl::interval_map<u32, int>;
|
using PageMap = boost::icl::interval_map<u32, int>;
|
||||||
|
|
||||||
struct RenderTargets {
|
struct RenderTargets {
|
||||||
SurfaceRef color_surface;
|
SurfaceId color_id;
|
||||||
SurfaceRef depth_surface;
|
SurfaceId depth_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCube {
|
struct TextureCube {
|
||||||
SurfaceRef surface{};
|
SurfaceId surface_id;
|
||||||
std::array<SurfaceRef, 6> faces{};
|
std::array<SurfaceId, 6> face_ids;
|
||||||
std::array<u64, 6> ticks{};
|
std::array<u64, 6> ticks;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RasterizerCache(Memory::MemorySystem& memory, CustomTexManager& custom_tex_manager,
|
explicit RasterizerCache(Memory::MemorySystem& memory, CustomTexManager& custom_tex_manager,
|
||||||
TextureRuntime& runtime, Pica::Regs& regs, RendererBase& renderer);
|
Runtime& runtime, Pica::Regs& regs, RendererBase& renderer);
|
||||||
~RasterizerCache();
|
~RasterizerCache();
|
||||||
|
|
||||||
/// Notify the cache that a new frame has been queued
|
/// Notify the cache that a new frame has been queued
|
||||||
@@ -91,17 +91,19 @@ public:
|
|||||||
/// Perform hardware accelerated memory fill according to the provided configuration
|
/// Perform hardware accelerated memory fill according to the provided configuration
|
||||||
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config);
|
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config);
|
||||||
|
|
||||||
|
/// Returns a reference to the surface object assigned to surface_id
|
||||||
|
Surface& GetSurface(SurfaceId surface_id);
|
||||||
|
|
||||||
/// Returns a reference to the sampler object matching the provided configuration
|
/// Returns a reference to the sampler object matching the provided configuration
|
||||||
Sampler& GetSampler(const Pica::TexturingRegs::TextureConfig& config);
|
Sampler& GetSampler(const Pica::TexturingRegs::TextureConfig& config);
|
||||||
Sampler& GetSampler(SamplerId sampler_id);
|
Sampler& GetSampler(SamplerId sampler_id);
|
||||||
|
|
||||||
/// Copy one surface's region to another
|
/// Copy one surface's region to another
|
||||||
void CopySurface(const SurfaceRef& src_surface, const SurfaceRef& dst_surface,
|
void CopySurface(Surface& src_surface, Surface& dst_surface, SurfaceInterval copy_interval);
|
||||||
SurfaceInterval copy_interval);
|
|
||||||
|
|
||||||
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
||||||
SurfaceRef GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
|
SurfaceId GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||||
bool load_if_create);
|
bool load_if_create);
|
||||||
|
|
||||||
/// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
|
/// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
|
||||||
/// 3DS memory to OpenGL and caches it (if not already cached)
|
/// 3DS memory to OpenGL and caches it (if not already cached)
|
||||||
@@ -109,11 +111,11 @@ public:
|
|||||||
bool load_if_create);
|
bool load_if_create);
|
||||||
|
|
||||||
/// Get a surface based on the texture configuration
|
/// Get a surface based on the texture configuration
|
||||||
SurfaceRef GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
|
Surface& GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
|
||||||
SurfaceRef GetTextureSurface(const Pica::Texture::TextureInfo& info, u32 max_level = 0);
|
SurfaceId GetTextureSurface(const Pica::Texture::TextureInfo& info, u32 max_level = 0);
|
||||||
|
|
||||||
/// Get a texture cube based on the texture configuration
|
/// Get a texture cube based on the texture configuration
|
||||||
SurfaceRef GetTextureCube(const TextureCubeConfig& config);
|
Surface& GetTextureCube(const TextureCubeConfig& config);
|
||||||
|
|
||||||
/// Get the color and depth surfaces based on the framebuffer configuration
|
/// Get the color and depth surfaces based on the framebuffer configuration
|
||||||
Framebuffer GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb);
|
Framebuffer GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb);
|
||||||
@@ -125,10 +127,10 @@ public:
|
|||||||
SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params);
|
SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params);
|
||||||
|
|
||||||
/// Write any cached resources overlapping the region back to memory (if dirty)
|
/// Write any cached resources overlapping the region back to memory (if dirty)
|
||||||
void FlushRegion(PAddr addr, u32 size, SurfaceRef flush_surface = nullptr);
|
void FlushRegion(PAddr addr, u32 size, SurfaceId flush_surface = {});
|
||||||
|
|
||||||
/// Mark region as being invalidated by region_owner (nullptr if 3DS memory)
|
/// Mark region as being invalidated by region_owner (nullptr if 3DS memory)
|
||||||
void InvalidateRegion(PAddr addr, u32 size, const SurfaceRef& region_owner);
|
void InvalidateRegion(PAddr addr, u32 size, SurfaceId region_owner = {});
|
||||||
|
|
||||||
/// Flush all cached resources tracked by this cache manager
|
/// Flush all cached resources tracked by this cache manager
|
||||||
void FlushAll();
|
void FlushAll();
|
||||||
@@ -159,33 +161,29 @@ private:
|
|||||||
|
|
||||||
/// Get the best surface match (and its match type) for the given flags
|
/// Get the best surface match (and its match type) for the given flags
|
||||||
template <MatchFlags find_flags>
|
template <MatchFlags find_flags>
|
||||||
SurfaceRef FindMatch(const SurfaceParams& params, ScaleMatch match_scale_type,
|
SurfaceId FindMatch(const SurfaceParams& params, ScaleMatch match_scale_type,
|
||||||
std::optional<SurfaceInterval> validate_interval = std::nullopt);
|
std::optional<SurfaceInterval> validate_interval = std::nullopt);
|
||||||
|
|
||||||
/// Transfers ownership of a memory region from src_surface to dest_surface
|
/// Transfers ownership of a memory region from src_surface to dest_surface
|
||||||
void DuplicateSurface(const SurfaceRef& src_surface, const SurfaceRef& dest_surface);
|
void DuplicateSurface(SurfaceId src_id, SurfaceId dst_id);
|
||||||
|
|
||||||
/// Update surface's texture for given region when necessary
|
/// Update surface's texture for given region when necessary
|
||||||
void ValidateSurface(const SurfaceRef& surface, PAddr addr, u32 size);
|
void ValidateSurface(SurfaceId surface, PAddr addr, u32 size);
|
||||||
|
|
||||||
/// Copies pixel data in interval from the guest VRAM to the host GPU surface
|
/// Copies pixel data in interval from the guest VRAM to the host GPU surface
|
||||||
void UploadSurface(const SurfaceRef& surface, SurfaceInterval interval);
|
void UploadSurface(Surface& surface, SurfaceInterval interval);
|
||||||
|
|
||||||
/// Uploads a custom texture identified with hash to the target surface
|
/// Uploads a custom texture identified with hash to the target surface
|
||||||
bool UploadCustomSurface(const SurfaceRef& surface, const SurfaceParams& load_info, u64 hash);
|
bool UploadCustomSurface(SurfaceId surface_id, SurfaceInterval interval);
|
||||||
|
|
||||||
/// Returns the hash used to lookup the custom surface.
|
|
||||||
u64 ComputeCustomHash(const SurfaceParams& load_info, std::span<u8> decoded,
|
|
||||||
std::span<u8> upload_data);
|
|
||||||
|
|
||||||
/// Copies pixel data in interval from the host GPU surface to the guest VRAM
|
/// Copies pixel data in interval from the host GPU surface to the guest VRAM
|
||||||
void DownloadSurface(const SurfaceRef& surface, SurfaceInterval interval);
|
void DownloadSurface(Surface& surface, SurfaceInterval interval);
|
||||||
|
|
||||||
/// Downloads a fill surface to guest VRAM
|
/// Downloads a fill surface to guest VRAM
|
||||||
void DownloadFillSurface(const SurfaceRef& surface, SurfaceInterval interval);
|
void DownloadFillSurface(Surface& surface, SurfaceInterval interval);
|
||||||
|
|
||||||
/// Returns false if there is a surface in the cache at the interval with the same bit-width,
|
/// Returns false if there is a surface in the cache at the interval with the same bit-width,
|
||||||
bool NoUnimplementedReinterpretations(const SurfaceRef& surface, SurfaceParams params,
|
bool NoUnimplementedReinterpretations(const Surface& surface, SurfaceParams params,
|
||||||
const SurfaceInterval& interval);
|
const SurfaceInterval& interval);
|
||||||
|
|
||||||
/// Return true if a surface with an invalid pixel format exists at the interval
|
/// Return true if a surface with an invalid pixel format exists at the interval
|
||||||
@@ -193,17 +191,17 @@ private:
|
|||||||
const SurfaceInterval& interval);
|
const SurfaceInterval& interval);
|
||||||
|
|
||||||
/// Attempt to find a reinterpretable surface in the cache and use it to copy for validation
|
/// Attempt to find a reinterpretable surface in the cache and use it to copy for validation
|
||||||
bool ValidateByReinterpretation(const SurfaceRef& surface, SurfaceParams params,
|
bool ValidateByReinterpretation(Surface& surface, SurfaceParams params,
|
||||||
const SurfaceInterval& interval);
|
const SurfaceInterval& interval);
|
||||||
|
|
||||||
/// Create a new surface
|
/// Create a new surface
|
||||||
SurfaceRef CreateSurface(const SurfaceParams& params);
|
SurfaceId CreateSurface(const SurfaceParams& params);
|
||||||
|
|
||||||
/// Register surface into the cache
|
/// Register surface into the cache
|
||||||
void RegisterSurface(const SurfaceRef& surface);
|
void RegisterSurface(SurfaceId surface);
|
||||||
|
|
||||||
/// Remove surface from the cache
|
/// Remove surface from the cache
|
||||||
void UnregisterSurface(const SurfaceRef& surface);
|
void UnregisterSurface(SurfaceId surface);
|
||||||
|
|
||||||
/// Unregisters all surfaces from the cache
|
/// Unregisters all surfaces from the cache
|
||||||
void UnregisterAll();
|
void UnregisterAll();
|
||||||
@@ -214,16 +212,17 @@ private:
|
|||||||
private:
|
private:
|
||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
CustomTexManager& custom_tex_manager;
|
CustomTexManager& custom_tex_manager;
|
||||||
TextureRuntime& runtime;
|
Runtime& runtime;
|
||||||
Pica::Regs& regs;
|
Pica::Regs& regs;
|
||||||
RendererBase& renderer;
|
RendererBase& renderer;
|
||||||
std::unordered_map<TextureCubeConfig, TextureCube> texture_cube_cache;
|
std::unordered_map<TextureCubeConfig, TextureCube> texture_cube_cache;
|
||||||
tsl::robin_pg_map<u64, std::vector<SurfaceRef>, Common::IdentityHash<u64>> page_table;
|
tsl::robin_pg_map<u64, std::vector<SurfaceId>, Common::IdentityHash<u64>> page_table;
|
||||||
std::unordered_map<SamplerParams, SamplerId> samplers;
|
std::unordered_map<SamplerParams, SamplerId> samplers;
|
||||||
|
SlotVector<Surface> slot_surfaces;
|
||||||
SlotVector<Sampler> slot_samplers;
|
SlotVector<Sampler> slot_samplers;
|
||||||
SurfaceMap dirty_regions;
|
SurfaceMap dirty_regions;
|
||||||
PageMap cached_pages;
|
PageMap cached_pages;
|
||||||
std::vector<SurfaceRef> remove_surfaces;
|
std::vector<SurfaceId> remove_surfaces;
|
||||||
u32 resolution_scale_factor;
|
u32 resolution_scale_factor;
|
||||||
RenderTargets render_targets;
|
RenderTargets render_targets;
|
||||||
bool use_filter;
|
bool use_filter;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <compare>
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "video_core/regs_texturing.h"
|
#include "video_core/regs_texturing.h"
|
||||||
|
|
||||||
|
@@ -29,60 +29,6 @@ struct SlotId {
|
|||||||
template <class T>
|
template <class T>
|
||||||
class SlotVector {
|
class SlotVector {
|
||||||
public:
|
public:
|
||||||
class Iterator {
|
|
||||||
friend SlotVector<T>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr Iterator() = default;
|
|
||||||
|
|
||||||
Iterator& operator++() noexcept {
|
|
||||||
const u64* const bitset = slot_vector->stored_bitset.data();
|
|
||||||
const u32 size = static_cast<u32>(slot_vector->stored_bitset.size()) * 64;
|
|
||||||
if (id.index < size) {
|
|
||||||
do {
|
|
||||||
++id.index;
|
|
||||||
} while (id.index < size && !IsValid(bitset));
|
|
||||||
if (id.index == size) {
|
|
||||||
id.index = SlotId::INVALID_INDEX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator operator++(int) noexcept {
|
|
||||||
const Iterator copy{*this};
|
|
||||||
++*this;
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Iterator& other) const noexcept {
|
|
||||||
return id.index == other.id.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const Iterator& other) const noexcept {
|
|
||||||
return id.index != other.id.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<SlotId, T*> operator*() const noexcept {
|
|
||||||
return {id, std::addressof((*slot_vector)[id])};
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const noexcept {
|
|
||||||
return std::addressof((*slot_vector)[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Iterator(SlotVector<T>* slot_vector_, SlotId id_) noexcept
|
|
||||||
: slot_vector{slot_vector_}, id{id_} {}
|
|
||||||
|
|
||||||
bool IsValid(const u64* bitset) const noexcept {
|
|
||||||
return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotVector<T>* slot_vector;
|
|
||||||
SlotId id;
|
|
||||||
};
|
|
||||||
|
|
||||||
~SlotVector() noexcept {
|
~SlotVector() noexcept {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (u64 bits : stored_bitset) {
|
for (u64 bits : stored_bitset) {
|
||||||
@@ -121,21 +67,6 @@ public:
|
|||||||
ResetStorageBit(id.index);
|
ResetStorageBit(id.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Iterator begin() noexcept {
|
|
||||||
const auto it = std::find_if(stored_bitset.begin(), stored_bitset.end(),
|
|
||||||
[](u64 value) { return value != 0; });
|
|
||||||
if (it == stored_bitset.end()) {
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
const u32 word_index = static_cast<u32>(std::distance(it, stored_bitset.begin()));
|
|
||||||
const SlotId first_id{word_index * 64 + static_cast<u32>(std::countr_zero(*it))};
|
|
||||||
return Iterator(this, first_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] Iterator end() noexcept {
|
|
||||||
return Iterator(this, SlotId{SlotId::INVALID_INDEX});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NonTrivialDummy {
|
struct NonTrivialDummy {
|
||||||
NonTrivialDummy() noexcept {}
|
NonTrivialDummy() noexcept {}
|
||||||
|
@@ -13,6 +13,14 @@ using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterva
|
|||||||
|
|
||||||
struct Material;
|
struct Material;
|
||||||
|
|
||||||
|
enum class SurfaceFlagBits : u32 {
|
||||||
|
Registered = 1 << 0, ///< Surface is registed in the rasterizer cache.
|
||||||
|
Picked = 1 << 1, ///< Surface has been picked when searching for a match.
|
||||||
|
Tracked = 1 << 2, ///< Surface is part of a texture cube and should be tracked.
|
||||||
|
Custom = 1 << 3, ///< Surface texture has been replaced with a custom texture.
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(SurfaceFlagBits);
|
||||||
|
|
||||||
class SurfaceBase : public SurfaceParams {
|
class SurfaceBase : public SurfaceParams {
|
||||||
public:
|
public:
|
||||||
SurfaceBase(const SurfaceParams& params);
|
SurfaceBase(const SurfaceParams& params);
|
||||||
@@ -43,7 +51,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsCustom() const noexcept {
|
bool IsCustom() const noexcept {
|
||||||
return is_custom && custom_format != CustomPixelFormat::Invalid;
|
return True(flags & SurfaceFlagBits::Custom) && custom_format != CustomPixelFormat::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRegionValid(SurfaceInterval interval) const {
|
bool IsRegionValid(SurfaceInterval interval) const {
|
||||||
@@ -70,9 +78,7 @@ private:
|
|||||||
std::array<u8, 4> MakeFillBuffer(PAddr copy_addr);
|
std::array<u8, 4> MakeFillBuffer(PAddr copy_addr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool registered = false;
|
SurfaceFlagBits flags{};
|
||||||
bool picked = false;
|
|
||||||
bool is_custom = false;
|
|
||||||
const Material* material = nullptr;
|
const Material* material = nullptr;
|
||||||
SurfaceRegions invalid_regions;
|
SurfaceRegions invalid_regions;
|
||||||
u32 fill_size = 0;
|
u32 fill_size = 0;
|
||||||
|
@@ -11,7 +11,7 @@ bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
|
|||||||
return std::tie(other_surface.addr, other_surface.width, other_surface.height,
|
return std::tie(other_surface.addr, other_surface.width, other_surface.height,
|
||||||
other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) ==
|
other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) ==
|
||||||
std::tie(addr, width, height, stride, pixel_format, is_tiled) &&
|
std::tie(addr, width, height, stride, pixel_format, is_tiled) &&
|
||||||
pixel_format != PixelFormat::Invalid && levels >= other_surface.levels;
|
pixel_format != PixelFormat::Invalid /*&& levels >= other_surface.levels*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
|
bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
|
||||||
|
@@ -17,8 +17,13 @@ namespace VideoCore {
|
|||||||
|
|
||||||
using SurfaceInterval = boost::icl::right_open_interval<PAddr>;
|
using SurfaceInterval = boost::icl::right_open_interval<PAddr>;
|
||||||
|
|
||||||
|
using SurfaceId = SlotId;
|
||||||
using SamplerId = SlotId;
|
using SamplerId = SlotId;
|
||||||
|
|
||||||
|
/// Fake surface ID for null surfaces
|
||||||
|
constexpr SurfaceId NULL_SURFACE_ID{0};
|
||||||
|
/// Fake surface ID for null cube surfaces
|
||||||
|
constexpr SurfaceId NULL_SURFACE_CUBE_ID{1};
|
||||||
/// Fake sampler ID for null samplers
|
/// Fake sampler ID for null samplers
|
||||||
constexpr SamplerId NULL_SAMPLER_ID{0};
|
constexpr SamplerId NULL_SAMPLER_ID{0};
|
||||||
|
|
||||||
@@ -77,9 +82,9 @@ struct BufferTextureCopy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct StagingData {
|
struct StagingData {
|
||||||
u32 size = 0;
|
u32 size;
|
||||||
std::span<u8> mapped{};
|
std::span<u8> mapped;
|
||||||
u64 buffer_offset = 0;
|
u64 buffer_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCubeConfig {
|
struct TextureCubeConfig {
|
||||||
|
@@ -25,7 +25,7 @@ MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Array Setup", MP_RGB(255, 128,
|
|||||||
MICROPROFILE_DEFINE(OpenGL_VS, "OpenGL", "Vertex Shader Setup", MP_RGB(192, 128, 128));
|
MICROPROFILE_DEFINE(OpenGL_VS, "OpenGL", "Vertex Shader Setup", MP_RGB(192, 128, 128));
|
||||||
MICROPROFILE_DEFINE(OpenGL_GS, "OpenGL", "Geometry Shader Setup", MP_RGB(128, 192, 128));
|
MICROPROFILE_DEFINE(OpenGL_GS, "OpenGL", "Geometry Shader Setup", MP_RGB(128, 192, 128));
|
||||||
MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
|
MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
|
||||||
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
|
MICROPROFILE_DEFINE(OpenGL_Display, "OpenGL", "Display", MP_RGB(128, 128, 192));
|
||||||
|
|
||||||
using VideoCore::SurfaceType;
|
using VideoCore::SurfaceType;
|
||||||
|
|
||||||
@@ -241,14 +241,14 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PAddr data_addr =
|
const PAddr data_addr =
|
||||||
base_address + loader.data_offset + (vs_input_index_min * loader.byte_count);
|
base_address + loader.data_offset + (vs_input_index_min * loader.byte_count);
|
||||||
|
|
||||||
u32 vertex_num = vs_input_index_max - vs_input_index_min + 1;
|
const u32 vertex_num = vs_input_index_max - vs_input_index_min + 1;
|
||||||
u32 data_size = loader.byte_count * vertex_num;
|
const u32 data_size = loader.byte_count * vertex_num;
|
||||||
|
|
||||||
res_cache.FlushRegion(data_addr, data_size, nullptr);
|
res_cache.FlushRegion(data_addr, data_size);
|
||||||
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;
|
array_ptr += data_size;
|
||||||
buffer_offset += data_size;
|
buffer_offset += data_size;
|
||||||
@@ -277,8 +277,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
|
|||||||
|
|
||||||
bool RasterizerOpenGL::SetupVertexShader() {
|
bool RasterizerOpenGL::SetupVertexShader() {
|
||||||
MICROPROFILE_SCOPE(OpenGL_VS);
|
MICROPROFILE_SCOPE(OpenGL_VS);
|
||||||
return shader_program_manager->UseProgrammableVertexShader(Pica::g_state.regs,
|
return shader_program_manager->UseProgrammableVertexShader(regs, Pica::g_state.vs);
|
||||||
Pica::g_state.vs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerOpenGL::SetupGeometryShader() {
|
bool RasterizerOpenGL::SetupGeometryShader() {
|
||||||
@@ -510,8 +509,8 @@ void RasterizerOpenGL::SyncTextureUnits(const Framebuffer& framebuffer) {
|
|||||||
if (texture_index == 0) {
|
if (texture_index == 0) {
|
||||||
switch (texture.config.type.Value()) {
|
switch (texture.config.type.Value()) {
|
||||||
case TextureType::Shadow2D: {
|
case TextureType::Shadow2D: {
|
||||||
auto surface = res_cache.GetTextureSurface(texture);
|
Surface& surface = res_cache.GetTextureSurface(texture);
|
||||||
state.image_shadow_texture_px = surface->Handle();
|
state.image_shadow_texture_px = surface.Handle();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case TextureType::ShadowCube: {
|
case TextureType::ShadowCube: {
|
||||||
@@ -528,23 +527,14 @@ void RasterizerOpenGL::SyncTextureUnits(const Framebuffer& framebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sync texture unit sampler
|
// Sync texture unit sampler
|
||||||
const Sampler& sampler = res_cache.GetSampler(texture.config);
|
Sampler& sampler = res_cache.GetSampler(texture.config);
|
||||||
state.texture_units[texture_index].sampler = sampler.Handle();
|
state.texture_units[texture_index].sampler = sampler.Handle();
|
||||||
|
|
||||||
// Bind the texture provided by the rasterizer cache
|
// Bind the texture provided by the rasterizer cache
|
||||||
auto surface = res_cache.GetTextureSurface(texture);
|
Surface& surface = res_cache.GetTextureSurface(texture);
|
||||||
if (!surface) {
|
if (!IsFeedbackLoop(texture_index, framebuffer, surface)) {
|
||||||
// Can occur when texture addr is null or its memory is unmapped/invalid
|
BindMaterial(texture_index, surface);
|
||||||
// HACK: In this case, the correct behaviour for the PICA is to use the last
|
state.texture_units[texture_index].texture_2d = surface.Handle();
|
||||||
// rendered colour. But because this would be impractical to implement, the
|
|
||||||
// next best alternative is to use a clear texture, essentially skipping
|
|
||||||
// the geometry in question.
|
|
||||||
// For example: a bug in Pokemon X/Y causes NULL-texture squares to be drawn
|
|
||||||
// on the male character's face, which in the OpenGL default appear black.
|
|
||||||
state.texture_units[texture_index].texture_2d = default_texture;
|
|
||||||
} else if (!IsFeedbackLoop(texture_index, framebuffer, *surface)) {
|
|
||||||
BindMaterial(texture_index, *surface);
|
|
||||||
state.texture_units[texture_index].texture_2d = surface->Handle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -561,8 +551,9 @@ void RasterizerOpenGL::BindShadowCube(const Pica::TexturingRegs::FullTextureConf
|
|||||||
const u32 binding = static_cast<u32>(face);
|
const u32 binding = static_cast<u32>(face);
|
||||||
info.physical_address = regs.texturing.GetCubePhysicalAddress(face);
|
info.physical_address = regs.texturing.GetCubePhysicalAddress(face);
|
||||||
|
|
||||||
auto surface = res_cache.GetTextureSurface(info);
|
VideoCore::SurfaceId surface_id = res_cache.GetTextureSurface(info);
|
||||||
state.image_shadow_texture[binding] = surface->Handle();
|
Surface& surface = res_cache.GetSurface(surface_id);
|
||||||
|
state.image_shadow_texture[binding] = surface.Handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,10 +571,10 @@ void RasterizerOpenGL::BindTextureCube(const Pica::TexturingRegs::FullTextureCon
|
|||||||
.format = texture.format,
|
.format = texture.format,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto surface = res_cache.GetTextureCube(config);
|
Surface& surface = res_cache.GetTextureCube(config);
|
||||||
Sampler& sampler = res_cache.GetSampler(texture.config);
|
Sampler& sampler = res_cache.GetSampler(texture.config);
|
||||||
|
|
||||||
state.texture_cube_unit.texture_cube = surface->Handle();
|
state.texture_cube_unit.texture_cube = surface.Handle();
|
||||||
state.texture_cube_unit.sampler = sampler.Handle();
|
state.texture_cube_unit.sampler = sampler.Handle();
|
||||||
state.texture_units[0].texture_2d = 0;
|
state.texture_units[0].texture_2d = 0;
|
||||||
}
|
}
|
||||||
@@ -718,24 +709,20 @@ void RasterizerOpenGL::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::FlushAll() {
|
void RasterizerOpenGL::FlushAll() {
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
|
||||||
res_cache.FlushAll();
|
res_cache.FlushAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::FlushRegion(PAddr addr, u32 size) {
|
void RasterizerOpenGL::FlushRegion(PAddr addr, u32 size) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
|
||||||
res_cache.FlushRegion(addr, size);
|
res_cache.FlushRegion(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::InvalidateRegion(PAddr addr, u32 size) {
|
void RasterizerOpenGL::InvalidateRegion(PAddr addr, u32 size) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
res_cache.InvalidateRegion(addr, size);
|
||||||
res_cache.InvalidateRegion(addr, size, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::FlushAndInvalidateRegion(PAddr addr, u32 size) {
|
void RasterizerOpenGL::FlushAndInvalidateRegion(PAddr addr, u32 size) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
|
||||||
res_cache.FlushRegion(addr, size);
|
res_cache.FlushRegion(addr, size);
|
||||||
res_cache.InvalidateRegion(addr, size, nullptr);
|
res_cache.InvalidateRegion(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::ClearAll(bool flush) {
|
void RasterizerOpenGL::ClearAll(bool flush) {
|
||||||
@@ -760,7 +747,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
|
|||||||
if (framebuffer_addr == 0) {
|
if (framebuffer_addr == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
MICROPROFILE_SCOPE(OpenGL_Display);
|
||||||
|
|
||||||
VideoCore::SurfaceParams src_params;
|
VideoCore::SurfaceParams src_params;
|
||||||
src_params.addr = framebuffer_addr;
|
src_params.addr = framebuffer_addr;
|
||||||
@@ -771,27 +758,27 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
|
|||||||
src_params.pixel_format = VideoCore::PixelFormatFromGPUPixelFormat(config.color_format);
|
src_params.pixel_format = VideoCore::PixelFormatFromGPUPixelFormat(config.color_format);
|
||||||
src_params.UpdateParams();
|
src_params.UpdateParams();
|
||||||
|
|
||||||
auto [src_surface, src_rect] =
|
const auto [src_surface_id, src_rect] =
|
||||||
res_cache.GetSurfaceSubRect(src_params, VideoCore::ScaleMatch::Ignore, true);
|
res_cache.GetSurfaceSubRect(src_params, VideoCore::ScaleMatch::Ignore, true);
|
||||||
|
if (!src_surface_id) {
|
||||||
if (src_surface == nullptr) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 scaled_width = src_surface->GetScaledWidth();
|
const Surface& src_surface = res_cache.GetSurface(src_surface_id);
|
||||||
const u32 scaled_height = src_surface->GetScaledHeight();
|
const u32 scaled_width = src_surface.GetScaledWidth();
|
||||||
|
const u32 scaled_height = src_surface.GetScaledHeight();
|
||||||
|
|
||||||
screen_info.display_texcoords = Common::Rectangle<float>(
|
screen_info.display_texcoords = Common::Rectangle<float>(
|
||||||
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
|
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
|
||||||
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);
|
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);
|
||||||
|
|
||||||
screen_info.display_texture = src_surface->Handle();
|
screen_info.display_texture = src_surface.Handle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncClipEnabled() {
|
void RasterizerOpenGL::SyncClipEnabled() {
|
||||||
state.clip_distance[1] = Pica::g_state.regs.rasterizer.clip_enable != 0;
|
state.clip_distance[1] = regs.rasterizer.clip_enable != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncCullMode() {
|
void RasterizerOpenGL::SyncCullMode() {
|
||||||
@@ -819,7 +806,7 @@ void RasterizerOpenGL::SyncCullMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendEnabled() {
|
void RasterizerOpenGL::SyncBlendEnabled() {
|
||||||
state.blend.enabled = (Pica::g_state.regs.framebuffer.output_merger.alphablend_enable == 1);
|
state.blend.enabled = (regs.framebuffer.output_merger.alphablend_enable == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendFuncs() {
|
void RasterizerOpenGL::SyncBlendFuncs() {
|
||||||
@@ -838,8 +825,7 @@ void RasterizerOpenGL::SyncBlendFuncs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendColor() {
|
void RasterizerOpenGL::SyncBlendColor() {
|
||||||
auto blend_color =
|
auto blend_color = PicaToGL::ColorRGBA8(regs.framebuffer.output_merger.blend_const.raw);
|
||||||
PicaToGL::ColorRGBA8(Pica::g_state.regs.framebuffer.output_merger.blend_const.raw);
|
|
||||||
state.blend.color.red = blend_color[0];
|
state.blend.color.red = blend_color[0];
|
||||||
state.blend.color.green = blend_color[1];
|
state.blend.color.green = blend_color[1];
|
||||||
state.blend.color.blue = blend_color[2];
|
state.blend.color.blue = blend_color[2];
|
||||||
|
@@ -573,7 +573,6 @@ bool Surface::Swap(const VideoCore::Material* mat) {
|
|||||||
GetScaledWidth(), GetScaledHeight(), VideoCore::PixelFormatAsString(pixel_format),
|
GetScaledWidth(), GetScaledHeight(), VideoCore::PixelFormatAsString(pixel_format),
|
||||||
addr, width, height, VideoCore::CustomPixelFormatAsString(format));
|
addr, width, height, VideoCore::CustomPixelFormatAsString(format));
|
||||||
|
|
||||||
is_custom = true;
|
|
||||||
custom_format = format;
|
custom_format = format;
|
||||||
material = mat;
|
material = mat;
|
||||||
|
|
||||||
@@ -615,13 +614,13 @@ HostTextureTag Surface::MakeTag() const noexcept {
|
|||||||
.res_scale = alloc.res_scale,
|
.res_scale = alloc.res_scale,
|
||||||
.tuple = alloc.tuple,
|
.tuple = alloc.tuple,
|
||||||
.type = texture_type,
|
.type = texture_type,
|
||||||
.is_custom = is_custom,
|
.is_custom = True(flags & VideoCore::SurfaceFlagBits::Custom),
|
||||||
.has_normal = HasNormalMap(),
|
.has_normal = HasNormalMap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Framebuffer::Framebuffer(TextureRuntime& runtime, Surface* const color, u32 color_level,
|
Framebuffer::Framebuffer(TextureRuntime& runtime, const Surface* color, u32 color_level,
|
||||||
Surface* const depth_stencil, u32 depth_level, const Pica::Regs& regs,
|
const Surface* depth_stencil, u32 depth_level, const Pica::Regs& regs,
|
||||||
Common::Rectangle<u32> surfaces_rect)
|
Common::Rectangle<u32> surfaces_rect)
|
||||||
: VideoCore::FramebufferBase{regs, color, color_level,
|
: VideoCore::FramebufferBase{regs, color, color_level,
|
||||||
depth_stencil, depth_level, surfaces_rect} {
|
depth_stencil, depth_level, surfaces_rect} {
|
||||||
|
@@ -201,8 +201,8 @@ private:
|
|||||||
|
|
||||||
class Framebuffer : public VideoCore::FramebufferBase {
|
class Framebuffer : public VideoCore::FramebufferBase {
|
||||||
public:
|
public:
|
||||||
explicit Framebuffer(TextureRuntime& runtime, Surface* const color, u32 color_level,
|
explicit Framebuffer(TextureRuntime& runtime, const Surface* color, u32 color_level,
|
||||||
Surface* const depth_stencil, u32 depth_level, const Pica::Regs& regs,
|
const Surface* depth_stencil, u32 depth_level, const Pica::Regs& regs,
|
||||||
Common::Rectangle<u32> surfaces_rect);
|
Common::Rectangle<u32> surfaces_rect);
|
||||||
~Framebuffer();
|
~Framebuffer();
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Traits {
|
struct Traits {
|
||||||
using TextureRuntime = OpenGL::TextureRuntime;
|
using Runtime = OpenGL::TextureRuntime;
|
||||||
using Sampler = OpenGL::Sampler;
|
using Sampler = OpenGL::Sampler;
|
||||||
using Surface = OpenGL::Surface;
|
using Surface = OpenGL::Surface;
|
||||||
using Framebuffer = OpenGL::Framebuffer;
|
using Framebuffer = OpenGL::Framebuffer;
|
||||||
|
Reference in New Issue
Block a user