rasterizer_cache: Simplify SurfaceBase
* The casts are bit ugly but will be refactored soon
This commit is contained in:
@ -37,6 +37,7 @@ add_library(video_core STATIC
|
|||||||
rasterizer_cache/sampler_params.h
|
rasterizer_cache/sampler_params.h
|
||||||
rasterizer_cache/slot_vector.h
|
rasterizer_cache/slot_vector.h
|
||||||
rasterizer_cache/surface_base.h
|
rasterizer_cache/surface_base.h
|
||||||
|
rasterizer_cache/surface_base.cpp
|
||||||
rasterizer_cache/utils.cpp
|
rasterizer_cache/utils.cpp
|
||||||
rasterizer_cache/utils.h
|
rasterizer_cache/utils.h
|
||||||
rasterizer_cache/surface_params.cpp
|
rasterizer_cache/surface_params.cpp
|
||||||
|
@ -611,7 +611,8 @@ auto RasterizerCache<T>::GetTextureSurface(const Pica::Texture::TextureInfo& inf
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (watcher && !watcher->IsValid()) {
|
if (watcher && !watcher->IsValid()) {
|
||||||
auto level_surface = watcher->Get();
|
auto level_surface =
|
||||||
|
std::static_pointer_cast<typename T::SurfaceType>(watcher->Get());
|
||||||
if (!level_surface->invalid_regions.empty()) {
|
if (!level_surface->invalid_regions.empty()) {
|
||||||
ValidateSurface(level_surface, level_surface->addr, level_surface->size);
|
ValidateSurface(level_surface, level_surface->addr, level_surface->size);
|
||||||
}
|
}
|
||||||
@ -684,7 +685,7 @@ auto RasterizerCache<T>::GetTextureCube(const TextureCubeConfig& config) -> cons
|
|||||||
for (std::size_t i = 0; i < addresses.size(); i++) {
|
for (std::size_t i = 0; i < addresses.size(); i++) {
|
||||||
const auto& watcher = watchers[i];
|
const auto& watcher = watchers[i];
|
||||||
if (watcher && !watcher->IsValid()) {
|
if (watcher && !watcher->IsValid()) {
|
||||||
auto face = watcher->Get();
|
auto face = std::static_pointer_cast<typename T::SurfaceType>(watcher->Get());
|
||||||
if (!face->invalid_regions.empty()) {
|
if (!face->invalid_regions.empty()) {
|
||||||
ValidateSurface(face, face->addr, face->size);
|
ValidateSurface(face, face->addr, face->size);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,6 @@ class RasterizerCache : NonCopyable {
|
|||||||
using TextureRuntime = typename T::RuntimeType;
|
using TextureRuntime = typename T::RuntimeType;
|
||||||
using Sampler = typename T::Sampler;
|
using Sampler = typename T::Sampler;
|
||||||
using Surface = std::shared_ptr<typename T::SurfaceType>;
|
using Surface = std::shared_ptr<typename T::SurfaceType>;
|
||||||
using Watcher = SurfaceWatcher<typename T::SurfaceType>;
|
|
||||||
|
|
||||||
/// Declare rasterizer interval types
|
/// Declare rasterizer interval types
|
||||||
using SurfaceMap = boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber,
|
using SurfaceMap = boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber,
|
||||||
|
127
src/video_core/rasterizer_cache/surface_base.cpp
Normal file
127
src/video_core/rasterizer_cache/surface_base.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2023 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/alignment.h"
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "video_core/rasterizer_cache/surface_base.h"
|
||||||
|
|
||||||
|
namespace VideoCore {
|
||||||
|
|
||||||
|
SurfaceBase::SurfaceBase() = default;
|
||||||
|
|
||||||
|
SurfaceBase::SurfaceBase(const SurfaceParams& params) : SurfaceParams{params} {}
|
||||||
|
|
||||||
|
bool SurfaceBase::CanFill(const SurfaceParams& dest_surface, SurfaceInterval fill_interval) const {
|
||||||
|
if (type == SurfaceType::Fill && IsRegionValid(fill_interval) &&
|
||||||
|
boost::icl::first(fill_interval) >= addr &&
|
||||||
|
boost::icl::last_next(fill_interval) <= end && // dest_surface is within our fill range
|
||||||
|
dest_surface.FromInterval(fill_interval).GetInterval() ==
|
||||||
|
fill_interval) { // make sure interval is a rectangle in dest surface
|
||||||
|
|
||||||
|
if (fill_size * 8 != dest_surface.GetFormatBpp()) {
|
||||||
|
// Check if bits repeat for our fill_size
|
||||||
|
const u32 dest_bytes_per_pixel = std::max(dest_surface.GetFormatBpp() / 8, 1u);
|
||||||
|
std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < dest_bytes_per_pixel; ++i)
|
||||||
|
std::memcpy(&fill_test[i * fill_size], &fill_data[0], fill_size);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < fill_size; ++i)
|
||||||
|
if (std::memcmp(&fill_test[dest_bytes_per_pixel * i], &fill_test[0],
|
||||||
|
dest_bytes_per_pixel) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (dest_surface.GetFormatBpp() == 4 && (fill_test[0] & 0xF) != (fill_test[0] >> 4))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SurfaceBase::CanCopy(const SurfaceParams& dest_surface, SurfaceInterval copy_interval) const {
|
||||||
|
SurfaceParams subrect_params = dest_surface.FromInterval(copy_interval);
|
||||||
|
ASSERT(subrect_params.GetInterval() == copy_interval);
|
||||||
|
if (CanSubRect(subrect_params))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (CanFill(dest_surface, copy_interval))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceInterval SurfaceBase::GetCopyableInterval(const SurfaceParams& params) const {
|
||||||
|
SurfaceInterval result{};
|
||||||
|
const u32 tile_align = params.BytesInPixels(params.is_tiled ? 8 * 8 : 1);
|
||||||
|
const auto valid_regions =
|
||||||
|
SurfaceRegions{params.GetInterval() & GetInterval()} - invalid_regions;
|
||||||
|
|
||||||
|
for (auto& valid_interval : valid_regions) {
|
||||||
|
const SurfaceInterval aligned_interval{
|
||||||
|
params.addr +
|
||||||
|
Common::AlignUp(boost::icl::first(valid_interval) - params.addr, tile_align),
|
||||||
|
params.addr +
|
||||||
|
Common::AlignDown(boost::icl::last_next(valid_interval) - params.addr, tile_align)};
|
||||||
|
|
||||||
|
if (tile_align > boost::icl::length(valid_interval) ||
|
||||||
|
boost::icl::length(aligned_interval) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the rectangle within aligned_interval
|
||||||
|
const u32 stride_bytes = params.BytesInPixels(params.stride) * (params.is_tiled ? 8 : 1);
|
||||||
|
SurfaceInterval rect_interval{
|
||||||
|
params.addr +
|
||||||
|
Common::AlignUp(boost::icl::first(aligned_interval) - params.addr, stride_bytes),
|
||||||
|
params.addr + Common::AlignDown(boost::icl::last_next(aligned_interval) - params.addr,
|
||||||
|
stride_bytes),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (boost::icl::first(rect_interval) > boost::icl::last_next(rect_interval)) {
|
||||||
|
// 1 row
|
||||||
|
rect_interval = aligned_interval;
|
||||||
|
} else if (boost::icl::length(rect_interval) == 0) {
|
||||||
|
// 2 rows that do not make a rectangle, return the larger one
|
||||||
|
const SurfaceInterval row1{boost::icl::first(aligned_interval),
|
||||||
|
boost::icl::first(rect_interval)};
|
||||||
|
const SurfaceInterval row2{boost::icl::first(rect_interval),
|
||||||
|
boost::icl::last_next(aligned_interval)};
|
||||||
|
rect_interval = (boost::icl::length(row1) > boost::icl::length(row2)) ? row1 : row2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boost::icl::length(rect_interval) > boost::icl::length(result)) {
|
||||||
|
result = rect_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Watcher> SurfaceBase::CreateWatcher() {
|
||||||
|
auto weak_ptr = weak_from_this();
|
||||||
|
auto watcher = std::make_shared<Watcher>(std::move(weak_ptr));
|
||||||
|
watchers.push_back(watcher);
|
||||||
|
return watcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceBase::InvalidateAllWatcher() {
|
||||||
|
for (const auto& watcher : watchers) {
|
||||||
|
if (auto locked = watcher.lock()) {
|
||||||
|
locked->valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceBase::UnlinkAllWatcher() {
|
||||||
|
for (const auto& watcher : watchers) {
|
||||||
|
if (auto locked = watcher.lock()) {
|
||||||
|
locked->valid = false;
|
||||||
|
locked->surface.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watchers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace VideoCore
|
@ -5,22 +5,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "common/alignment.h"
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "video_core/rasterizer_cache/surface_params.h"
|
#include "video_core/rasterizer_cache/surface_params.h"
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
|
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
|
||||||
|
|
||||||
|
class SurfaceBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A watcher that notifies whether a cached surface has been changed. This is useful for caching
|
* A watcher that notifies whether a cached surface has been changed. This is useful for caching
|
||||||
* surface collection objects, including texture cube and mipmap.
|
* surface collection objects, including texture cube and mipmap.
|
||||||
*/
|
*/
|
||||||
template <class S>
|
class Watcher {
|
||||||
class SurfaceWatcher {
|
|
||||||
public:
|
public:
|
||||||
explicit SurfaceWatcher(std::weak_ptr<S>&& surface) : surface(std::move(surface)) {}
|
explicit Watcher(std::weak_ptr<SurfaceBase>&& surface) : surface(std::move(surface)) {}
|
||||||
|
|
||||||
/// Checks whether the surface has been changed.
|
/// Checks whether the surface has been changed.
|
||||||
bool IsValid() const {
|
bool IsValid() const {
|
||||||
@ -34,23 +33,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the referencing surface. Returns null if the surface has been destroyed
|
/// Gets the referencing surface. Returns null if the surface has been destroyed
|
||||||
std::shared_ptr<S> Get() const {
|
std::shared_ptr<SurfaceBase> Get() const {
|
||||||
return surface.lock();
|
return surface.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::weak_ptr<S> surface;
|
std::weak_ptr<SurfaceBase> surface;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class S>
|
class SurfaceBase : public SurfaceParams, public std::enable_shared_from_this<SurfaceBase> {
|
||||||
class SurfaceBase : public SurfaceParams, public std::enable_shared_from_this<S> {
|
|
||||||
using Watcher = SurfaceWatcher<S>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SurfaceBase() = default;
|
SurfaceBase();
|
||||||
SurfaceBase(const SurfaceParams& params) : SurfaceParams{params} {}
|
explicit SurfaceBase(const SurfaceParams& params);
|
||||||
virtual ~SurfaceBase() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
|
[[nodiscard]] bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
|
||||||
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
|
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
|
||||||
@ -99,124 +94,4 @@ public:
|
|||||||
std::vector<std::weak_ptr<Watcher>> watchers;
|
std::vector<std::weak_ptr<Watcher>> watchers;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class S>
|
|
||||||
bool SurfaceBase<S>::CanFill(const SurfaceParams& dest_surface,
|
|
||||||
SurfaceInterval fill_interval) const {
|
|
||||||
if (type == SurfaceType::Fill && IsRegionValid(fill_interval) &&
|
|
||||||
boost::icl::first(fill_interval) >= addr &&
|
|
||||||
boost::icl::last_next(fill_interval) <= end && // dest_surface is within our fill range
|
|
||||||
dest_surface.FromInterval(fill_interval).GetInterval() ==
|
|
||||||
fill_interval) { // make sure interval is a rectangle in dest surface
|
|
||||||
|
|
||||||
if (fill_size * 8 != dest_surface.GetFormatBpp()) {
|
|
||||||
// Check if bits repeat for our fill_size
|
|
||||||
const u32 dest_bytes_per_pixel = std::max(dest_surface.GetFormatBpp() / 8, 1u);
|
|
||||||
std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < dest_bytes_per_pixel; ++i)
|
|
||||||
std::memcpy(&fill_test[i * fill_size], &fill_data[0], fill_size);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < fill_size; ++i)
|
|
||||||
if (std::memcmp(&fill_test[dest_bytes_per_pixel * i], &fill_test[0],
|
|
||||||
dest_bytes_per_pixel) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (dest_surface.GetFormatBpp() == 4 && (fill_test[0] & 0xF) != (fill_test[0] >> 4))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class S>
|
|
||||||
bool SurfaceBase<S>::CanCopy(const SurfaceParams& dest_surface,
|
|
||||||
SurfaceInterval copy_interval) const {
|
|
||||||
SurfaceParams subrect_params = dest_surface.FromInterval(copy_interval);
|
|
||||||
ASSERT(subrect_params.GetInterval() == copy_interval);
|
|
||||||
if (CanSubRect(subrect_params))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (CanFill(dest_surface, copy_interval))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class S>
|
|
||||||
SurfaceInterval SurfaceBase<S>::GetCopyableInterval(const SurfaceParams& params) const {
|
|
||||||
SurfaceInterval result{};
|
|
||||||
const u32 tile_align = params.BytesInPixels(params.is_tiled ? 8 * 8 : 1);
|
|
||||||
const auto valid_regions =
|
|
||||||
SurfaceRegions{params.GetInterval() & GetInterval()} - invalid_regions;
|
|
||||||
|
|
||||||
for (auto& valid_interval : valid_regions) {
|
|
||||||
const SurfaceInterval aligned_interval{
|
|
||||||
params.addr +
|
|
||||||
Common::AlignUp(boost::icl::first(valid_interval) - params.addr, tile_align),
|
|
||||||
params.addr +
|
|
||||||
Common::AlignDown(boost::icl::last_next(valid_interval) - params.addr, tile_align)};
|
|
||||||
|
|
||||||
if (tile_align > boost::icl::length(valid_interval) ||
|
|
||||||
boost::icl::length(aligned_interval) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the rectangle within aligned_interval
|
|
||||||
const u32 stride_bytes = params.BytesInPixels(params.stride) * (params.is_tiled ? 8 : 1);
|
|
||||||
SurfaceInterval rect_interval{
|
|
||||||
params.addr +
|
|
||||||
Common::AlignUp(boost::icl::first(aligned_interval) - params.addr, stride_bytes),
|
|
||||||
params.addr + Common::AlignDown(boost::icl::last_next(aligned_interval) - params.addr,
|
|
||||||
stride_bytes),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (boost::icl::first(rect_interval) > boost::icl::last_next(rect_interval)) {
|
|
||||||
// 1 row
|
|
||||||
rect_interval = aligned_interval;
|
|
||||||
} else if (boost::icl::length(rect_interval) == 0) {
|
|
||||||
// 2 rows that do not make a rectangle, return the larger one
|
|
||||||
const SurfaceInterval row1{boost::icl::first(aligned_interval),
|
|
||||||
boost::icl::first(rect_interval)};
|
|
||||||
const SurfaceInterval row2{boost::icl::first(rect_interval),
|
|
||||||
boost::icl::last_next(aligned_interval)};
|
|
||||||
rect_interval = (boost::icl::length(row1) > boost::icl::length(row2)) ? row1 : row2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boost::icl::length(rect_interval) > boost::icl::length(result)) {
|
|
||||||
result = rect_interval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class S>
|
|
||||||
auto SurfaceBase<S>::CreateWatcher() -> std::shared_ptr<Watcher> {
|
|
||||||
auto weak_ptr = reinterpret_cast<S*>(this)->weak_from_this();
|
|
||||||
auto watcher = std::make_shared<Watcher>(std::move(weak_ptr));
|
|
||||||
watchers.push_back(watcher);
|
|
||||||
return watcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class S>
|
|
||||||
void SurfaceBase<S>::InvalidateAllWatcher() {
|
|
||||||
for (const auto& watcher : watchers) {
|
|
||||||
if (auto locked = watcher.lock()) {
|
|
||||||
locked->valid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class S>
|
|
||||||
void SurfaceBase<S>::UnlinkAllWatcher() {
|
|
||||||
for (const auto& watcher : watchers) {
|
|
||||||
if (auto locked = watcher.lock()) {
|
|
||||||
locked->valid = false;
|
|
||||||
locked->surface.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -313,7 +313,7 @@ void TextureRuntime::BindFramebuffer(GLenum target, GLint level, GLenum textarge
|
|||||||
}
|
}
|
||||||
|
|
||||||
Surface::Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime)
|
Surface::Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime)
|
||||||
: VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, driver{runtime.GetDriver()} {
|
: VideoCore::SurfaceBase{params}, runtime{runtime}, driver{runtime.GetDriver()} {
|
||||||
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
||||||
texture = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, params.pixel_format,
|
texture = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, params.pixel_format,
|
||||||
texture_type);
|
texture_type);
|
||||||
|
@ -99,10 +99,10 @@ private:
|
|||||||
OGLFramebuffer read_fbo, draw_fbo;
|
OGLFramebuffer read_fbo, draw_fbo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Surface : public VideoCore::SurfaceBase<Surface> {
|
class Surface : public VideoCore::SurfaceBase {
|
||||||
public:
|
public:
|
||||||
Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime);
|
Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime);
|
||||||
~Surface() override;
|
~Surface();
|
||||||
|
|
||||||
/// Returns the surface image handle
|
/// Returns the surface image handle
|
||||||
GLuint Handle() const noexcept {
|
GLuint Handle() const noexcept {
|
||||||
|
@ -747,11 +747,8 @@ bool TextureRuntime::NeedsConvertion(VideoCore::PixelFormat format) const {
|
|||||||
traits.aspect != (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil);
|
traits.aspect != (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface::Surface(TextureRuntime& runtime)
|
|
||||||
: runtime{runtime}, instance{runtime.GetInstance()}, scheduler{runtime.GetScheduler()} {}
|
|
||||||
|
|
||||||
Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime)
|
Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime)
|
||||||
: VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
: VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
||||||
scheduler{runtime.GetScheduler()}, traits{instance.GetTraits(pixel_format)} {
|
scheduler{runtime.GetScheduler()}, traits{instance.GetTraits(pixel_format)} {
|
||||||
|
|
||||||
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
||||||
@ -762,7 +759,7 @@ Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime
|
|||||||
|
|
||||||
Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format,
|
Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format,
|
||||||
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect, TextureRuntime& runtime)
|
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect, TextureRuntime& runtime)
|
||||||
: VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
: VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
||||||
scheduler{runtime.GetScheduler()} {
|
scheduler{runtime.GetScheduler()} {
|
||||||
if (format != vk::Format::eUndefined) {
|
if (format != vk::Format::eUndefined) {
|
||||||
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, pixel_format,
|
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, pixel_format,
|
||||||
|
@ -163,15 +163,14 @@ private:
|
|||||||
std::unordered_multimap<HostTextureTag, ImageAlloc> texture_recycler;
|
std::unordered_multimap<HostTextureTag, ImageAlloc> texture_recycler;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Surface : public VideoCore::SurfaceBase<Surface> {
|
class Surface : public VideoCore::SurfaceBase {
|
||||||
friend class TextureRuntime;
|
friend class TextureRuntime;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Surface(TextureRuntime& runtime);
|
|
||||||
Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime);
|
Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime);
|
||||||
Surface(const VideoCore::SurfaceParams& params, vk::Format format, vk::ImageUsageFlags usage,
|
Surface(const VideoCore::SurfaceParams& params, vk::Format format, vk::ImageUsageFlags usage,
|
||||||
vk::ImageAspectFlags aspect, TextureRuntime& runtime);
|
vk::ImageAspectFlags aspect, TextureRuntime& runtime);
|
||||||
~Surface() override;
|
~Surface();
|
||||||
|
|
||||||
/// Returns the surface aspect
|
/// Returns the surface aspect
|
||||||
vk::ImageAspectFlags Aspect() const noexcept {
|
vk::ImageAspectFlags Aspect() const noexcept {
|
||||||
|
Reference in New Issue
Block a user