mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
rasterizer_cache: Initial support for multi-sample surfaces
This commit is contained in:
parent
f682a89bdc
commit
fdf022753c
9 changed files with 109 additions and 55 deletions
|
|
@ -27,7 +27,8 @@ struct FramebufferParams {
|
|||
u32 color_level;
|
||||
u32 depth_level;
|
||||
bool shadow_rendering;
|
||||
INSERT_PADDING_BYTES(3);
|
||||
u8 sample_count;
|
||||
INSERT_PADDING_BYTES(2);
|
||||
|
||||
bool operator==(const FramebufferParams& params) const noexcept {
|
||||
return std::memcmp(this, ¶ms, sizeof(FramebufferParams)) == 0;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ RasterizerCache<T>::RasterizerCache(Memory::MemorySystem& memory_,
|
|||
Pica::RegsInternal& regs_, RendererBase& renderer_)
|
||||
: memory{memory_}, custom_tex_manager{custom_tex_manager_}, runtime{runtime_}, regs{regs_},
|
||||
renderer{renderer_}, resolution_scale_factor{renderer.GetResolutionScaleFactor()},
|
||||
filter{Settings::values.texture_filter.GetValue()},
|
||||
sample_count{renderer.GetSampleCount()}, filter{Settings::values.texture_filter.GetValue()},
|
||||
dump_textures{Settings::values.dump_textures.GetValue()},
|
||||
use_custom_textures{Settings::values.custom_textures.GetValue()} {
|
||||
using TextureConfig = Pica::TexturingRegs::TextureConfig;
|
||||
|
|
@ -96,12 +96,15 @@ void RasterizerCache<T>::TickFrame() {
|
|||
}
|
||||
|
||||
const u32 scale_factor = renderer.GetResolutionScaleFactor();
|
||||
const u32 samples = renderer.GetSampleCount();
|
||||
const bool resolution_scale_changed = resolution_scale_factor != scale_factor;
|
||||
const bool sample_count_changed = sample_count != samples;
|
||||
const bool use_custom_texture_changed =
|
||||
Settings::values.custom_textures.GetValue() != use_custom_textures;
|
||||
|
||||
if (resolution_scale_changed || use_custom_texture_changed) {
|
||||
if (resolution_scale_changed || use_custom_texture_changed || sample_count_changed) {
|
||||
resolution_scale_factor = scale_factor;
|
||||
sample_count = renderer.GetSampleCount();
|
||||
use_custom_textures = Settings::values.custom_textures.GetValue();
|
||||
if (use_custom_textures) {
|
||||
custom_tex_manager.FindCustomTextures();
|
||||
|
|
@ -287,6 +290,7 @@ bool RasterizerCache<T>::AccelerateDisplayTransfer(const Pica::DisplayTransferCo
|
|||
: config.output_height.Value();
|
||||
dst_params.is_tiled = config.input_linear != config.dont_swizzle;
|
||||
dst_params.pixel_format = PixelFormatFromGPUPixelFormat(config.output_format);
|
||||
dst_params.sample_count = sample_count;
|
||||
dst_params.UpdateParams();
|
||||
|
||||
// Using flip_vertically alongside crop_input_lines produces skewed output on hardware.
|
||||
|
|
@ -302,6 +306,7 @@ bool RasterizerCache<T>::AccelerateDisplayTransfer(const Pica::DisplayTransferCo
|
|||
}
|
||||
|
||||
dst_params.res_scale = slot_surfaces[src_surface_id].res_scale;
|
||||
dst_params.sample_count = slot_surfaces[src_surface_id].sample_count;
|
||||
|
||||
const auto [dst_surface_id, dst_rect] =
|
||||
GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, false);
|
||||
|
|
@ -432,8 +437,10 @@ void RasterizerCache<T>::CopySurface(Surface& src_surface, Surface& dst_surface,
|
|||
|
||||
const u32 src_scale = src_surface.res_scale;
|
||||
const u32 dst_scale = dst_surface.res_scale;
|
||||
if (src_scale > dst_scale) {
|
||||
dst_surface.ScaleUp(src_scale);
|
||||
const u32 src_sample_count = src_surface.sample_count;
|
||||
const u32 dst_sample_count = dst_surface.sample_count;
|
||||
if ((src_scale > dst_scale) || (src_sample_count > dst_sample_count)) {
|
||||
dst_surface.ScaleUp(src_scale, src_sample_count);
|
||||
}
|
||||
|
||||
const auto src_rect = src_surface.GetScaledSubRect(subrect_params);
|
||||
|
|
@ -502,6 +509,7 @@ typename RasterizerCache<T>::SurfaceRect_Tuple RasterizerCache<T>::GetSurfaceSub
|
|||
if (surface_id) {
|
||||
SurfaceParams new_params = slot_surfaces[surface_id];
|
||||
new_params.res_scale = params.res_scale;
|
||||
new_params.sample_count = params.sample_count;
|
||||
|
||||
surface_id = CreateSurface(new_params, create_initial_flags);
|
||||
RegisterSurface(surface_id);
|
||||
|
|
@ -706,6 +714,7 @@ FramebufferHelper<T> RasterizerCache<T>::GetFramebufferSurfaces(bool using_color
|
|||
SurfaceParams color_params;
|
||||
color_params.is_tiled = true;
|
||||
color_params.res_scale = resolution_scale_factor;
|
||||
color_params.sample_count = sample_count;
|
||||
color_params.width = config.GetWidth();
|
||||
color_params.height = config.GetHeight();
|
||||
SurfaceParams depth_params = color_params;
|
||||
|
|
@ -771,6 +780,7 @@ FramebufferHelper<T> RasterizerCache<T>::GetFramebufferSurfaces(bool using_color
|
|||
.color_level = color_level,
|
||||
.depth_level = depth_level,
|
||||
.shadow_rendering = regs.framebuffer.IsShadowRendering(),
|
||||
.sample_count = sample_count,
|
||||
};
|
||||
|
||||
auto [it, new_framebuffer] = framebuffers.try_emplace(fb_params);
|
||||
|
|
@ -861,12 +871,16 @@ SurfaceId RasterizerCache<T>::FindMatch(const SurfaceParams& params, ScaleMatch
|
|||
SurfaceId match_id{};
|
||||
bool match_valid = false;
|
||||
u32 match_scale = 0;
|
||||
u8 match_sample_count = 0;
|
||||
SurfaceInterval match_interval{};
|
||||
|
||||
ForEachSurfaceInRegion(params.addr, params.size, [&](SurfaceId surface_id, Surface& surface) {
|
||||
const bool res_scale_matched = match_scale_type == ScaleMatch::Exact
|
||||
? (params.res_scale == surface.res_scale)
|
||||
: (params.res_scale <= surface.res_scale);
|
||||
const bool sample_count_matched = match_scale_type == ScaleMatch::Exact
|
||||
? (params.sample_count == surface.sample_count)
|
||||
: (params.sample_count <= surface.sample_count);
|
||||
const bool is_valid =
|
||||
True(find_flags & MatchFlags::Copy)
|
||||
? true
|
||||
|
|
@ -886,11 +900,16 @@ SurfaceId RasterizerCache<T>::FindMatch(const SurfaceParams& params, ScaleMatch
|
|||
surface.type != SurfaceType::Fill)
|
||||
return;
|
||||
|
||||
if (!sample_count_matched && match_scale_type != ScaleMatch::Ignore &&
|
||||
surface.type != SurfaceType::Fill)
|
||||
return;
|
||||
|
||||
// Found a match, update only if this is better than the previous one
|
||||
auto UpdateMatch = [&] {
|
||||
match_id = surface_id;
|
||||
match_valid = is_valid;
|
||||
match_scale = surface.res_scale;
|
||||
match_sample_count = surface.sample_count;
|
||||
match_interval = surface_interval;
|
||||
};
|
||||
|
||||
|
|
@ -901,6 +920,13 @@ SurfaceId RasterizerCache<T>::FindMatch(const SurfaceParams& params, ScaleMatch
|
|||
return;
|
||||
}
|
||||
|
||||
if (surface.sample_count > match_sample_count) {
|
||||
UpdateMatch();
|
||||
return;
|
||||
} else if (surface.sample_count < match_sample_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_valid && !match_valid) {
|
||||
UpdateMatch();
|
||||
return;
|
||||
|
|
@ -1189,8 +1215,9 @@ bool RasterizerCache<T>::ValidateByReinterpretation(Surface& surface, SurfacePar
|
|||
return false;
|
||||
}
|
||||
const u32 res_scale = src_surface.res_scale;
|
||||
if (res_scale > surface.res_scale) {
|
||||
surface.ScaleUp(res_scale);
|
||||
const u8 sample_count = src_surface.sample_count;
|
||||
if ((res_scale > surface.res_scale) || (sample_count > surface.sample_count)) {
|
||||
surface.ScaleUp(res_scale, sample_count);
|
||||
}
|
||||
const PAddr addr = boost::icl::lower(interval);
|
||||
const SurfaceParams copy_params = surface.FromInterval(copy_interval);
|
||||
|
|
@ -1357,8 +1384,8 @@ SurfaceId RasterizerCache<T>::CreateSurface(const SurfaceParams& params,
|
|||
return surface_id;
|
||||
}();
|
||||
Surface& surface = slot_surfaces[surface_id];
|
||||
if (params.res_scale > surface.res_scale) {
|
||||
surface.ScaleUp(params.res_scale);
|
||||
if ((params.res_scale > surface.res_scale) || (params.sample_count > surface.sample_count)) {
|
||||
surface.ScaleUp(params.res_scale, params.sample_count);
|
||||
}
|
||||
surface.MarkInvalid(surface.GetInterval());
|
||||
return surface_id;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ private:
|
|||
SurfaceMap dirty_regions;
|
||||
PageMap cached_pages;
|
||||
u32 resolution_scale_factor;
|
||||
u8 sample_count;
|
||||
u64 frame_tick{};
|
||||
FramebufferParams fb_params;
|
||||
Settings::TextureFilter filter;
|
||||
|
|
|
|||
|
|
@ -219,12 +219,13 @@ u32 SurfaceParams::LevelOf(PAddr level_addr) const {
|
|||
return level;
|
||||
}
|
||||
|
||||
std::string SurfaceParams::DebugName(bool scaled, bool custom) const noexcept {
|
||||
std::string SurfaceParams::DebugName(bool scaled, bool custom, u8 sample_count) const noexcept {
|
||||
const u32 scaled_width = scaled ? GetScaledWidth() : width;
|
||||
const u32 scaled_height = scaled ? GetScaledHeight() : height;
|
||||
return fmt::format("Surface: {}x{} {} {} levels from {:#x} to {:#x} ({}{})", scaled_width,
|
||||
scaled_height, PixelFormatAsString(pixel_format), levels, addr, end,
|
||||
custom ? "custom," : "", scaled ? "scaled" : "unscaled");
|
||||
return fmt::format("Surface: {}x{} {} samples {} levels from {:#x} to {:#x} ({}{})",
|
||||
scaled_width, scaled_height, PixelFormatAsString(pixel_format),
|
||||
static_cast<u32>(sample_count), levels, addr, end, custom ? "custom," : "",
|
||||
scaled ? "scaled" : "unscaled");
|
||||
}
|
||||
|
||||
bool SurfaceParams::operator==(const SurfaceParams& other) const noexcept {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public:
|
|||
u32 LevelOf(PAddr addr) const;
|
||||
|
||||
/// Returns a string identifier of the params object
|
||||
std::string DebugName(bool scaled, bool custom = false) const noexcept;
|
||||
std::string DebugName(bool scaled, bool custom = false, u8 sample_count = 1) const noexcept;
|
||||
|
||||
bool operator==(const SurfaceParams& other) const noexcept;
|
||||
|
||||
|
|
@ -71,6 +71,10 @@ public:
|
|||
return height * res_scale;
|
||||
}
|
||||
|
||||
[[nodiscard]] u8 GetSampleCount() const noexcept {
|
||||
return sample_count;
|
||||
}
|
||||
|
||||
[[nodiscard]] Common::Rectangle<u32> GetRect(u32 level = 0) const noexcept {
|
||||
return {0, height >> level, width >> level, 0};
|
||||
}
|
||||
|
|
@ -104,6 +108,7 @@ public:
|
|||
u32 stride = 0;
|
||||
u32 levels = 1;
|
||||
u32 res_scale = 1;
|
||||
u8 sample_count = 1;
|
||||
|
||||
bool is_tiled = false;
|
||||
TextureType texture_type = TextureType::Texture2D;
|
||||
|
|
|
|||
|
|
@ -556,23 +556,31 @@ void Surface::Attach(GLenum target, u32 level, u32 layer, bool scaled) {
|
|||
}
|
||||
}
|
||||
|
||||
void Surface::ScaleUp(u32 new_scale) {
|
||||
if (res_scale == new_scale || new_scale == 1) {
|
||||
void Surface::ScaleUp(u32 new_scale, u8 new_sample_count) {
|
||||
if (res_scale == new_scale && sample_count == new_sample_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
res_scale = new_scale;
|
||||
textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple,
|
||||
DebugName(true));
|
||||
sample_count = new_sample_count;
|
||||
|
||||
for (u32 level = 0; level < levels; level++) {
|
||||
const VideoCore::TextureBlit blit = {
|
||||
.src_level = level,
|
||||
.dst_level = level,
|
||||
.src_rect = GetRect(level),
|
||||
.dst_rect = GetScaledRect(level),
|
||||
};
|
||||
BlitScale(blit, true);
|
||||
if (res_scale > 1) {
|
||||
|
||||
textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple,
|
||||
DebugName(true));
|
||||
for (u32 level = 0; level < levels; level++) {
|
||||
const VideoCore::TextureBlit blit = {
|
||||
.src_level = level,
|
||||
.dst_level = level,
|
||||
.src_rect = GetRect(level),
|
||||
.dst_rect = GetScaledRect(level),
|
||||
};
|
||||
BlitScale(blit, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_sample_count > 1) {
|
||||
// Todo(wunk): OpenGL MSAA
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@ public:
|
|||
/// Attaches a handle of surface to the specified framebuffer target
|
||||
void Attach(GLenum target, u32 level, u32 layer, bool scaled = true);
|
||||
|
||||
/// Scales up the surface to match the new resolution scale.
|
||||
void ScaleUp(u32 new_scale);
|
||||
/// Scales up the surface to match the new resolution scale and sample-count.
|
||||
void ScaleUp(u32 new_scale, u8 new_sample_count);
|
||||
|
||||
/// Returns the bpp of the internal surface format
|
||||
u32 GetInternalBytesPerPixel() const;
|
||||
|
|
|
|||
|
|
@ -731,7 +731,8 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
|
|||
const VideoCore::SurfaceFlagBits& initial_flag_bits)
|
||||
: SurfaceBase{params, initial_flag_bits}, runtime{runtime_}, instance{runtime_.GetInstance()},
|
||||
scheduler{runtime_.GetScheduler()}, traits{instance.GetTraits(pixel_format)},
|
||||
handles{Handle(instance), Handle(instance), Handle(instance), Handle(instance)} {
|
||||
handles{Handle(instance), Handle(instance), Handle(instance), Handle(instance),
|
||||
Handle(instance)} {
|
||||
|
||||
if (pixel_format == VideoCore::PixelFormat::Invalid || !traits.transfer_support) {
|
||||
return;
|
||||
|
|
@ -800,7 +801,8 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface
|
|||
const VideoCore::Material* mat)
|
||||
: SurfaceBase{surface}, runtime{runtime_}, instance{runtime_.GetInstance()},
|
||||
scheduler{runtime_.GetScheduler()}, traits{instance.GetTraits(mat->format)},
|
||||
handles{Handle(instance), Handle(instance), Handle(instance), Handle(instance)} {
|
||||
handles{Handle(instance), Handle(instance), Handle(instance), Handle(instance),
|
||||
Handle(instance)} {
|
||||
if (!traits.transfer_support) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1096,12 +1098,13 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download,
|
|||
});
|
||||
}
|
||||
|
||||
void Surface::ScaleUp(u32 new_scale) {
|
||||
if (res_scale == new_scale || new_scale == 1) {
|
||||
void Surface::ScaleUp(u32 new_scale, u8 new_sample_count) {
|
||||
if (res_scale == new_scale && sample_count == new_sample_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
res_scale = new_scale;
|
||||
sample_count = new_sample_count;
|
||||
|
||||
const bool is_mutable = pixel_format == VideoCore::PixelFormat::RGBA8;
|
||||
|
||||
|
|
@ -1113,29 +1116,36 @@ void Surface::ScaleUp(u32 new_scale) {
|
|||
flags |= vk::ImageCreateFlagBits::eMutableFormat;
|
||||
}
|
||||
|
||||
handles[Type::Scaled].Create(GetScaledWidth(), GetScaledHeight(), levels, texture_type,
|
||||
traits.native, traits.usage, flags, traits.aspect, false,
|
||||
DebugName(true));
|
||||
current = Type::Scaled;
|
||||
if (res_scale > 1) {
|
||||
|
||||
runtime.renderpass_cache.EndRendering();
|
||||
scheduler.Record(
|
||||
[raw_images = std::array{Image()}, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
std::array<vk::ImageMemoryBarrier, 1> barriers;
|
||||
MakeInitBarriers(aspect, 1, raw_images, barriers);
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||
});
|
||||
handles[Type::Scaled].Create(GetScaledWidth(), GetScaledHeight(), levels, texture_type,
|
||||
traits.native, traits.usage, flags, traits.aspect, false,
|
||||
DebugName(true));
|
||||
current = Type::Scaled;
|
||||
|
||||
for (u32 level = 0; level < levels; level++) {
|
||||
const VideoCore::TextureBlit blit = {
|
||||
.src_level = level,
|
||||
.dst_level = level,
|
||||
.src_rect = GetRect(level),
|
||||
.dst_rect = GetScaledRect(level),
|
||||
};
|
||||
BlitScale(blit, true);
|
||||
runtime.renderpass_cache.EndRendering();
|
||||
scheduler.Record(
|
||||
[raw_images = std::array{Image()}, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
std::array<vk::ImageMemoryBarrier, 1> barriers;
|
||||
MakeInitBarriers(aspect, 1, raw_images, barriers);
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||
});
|
||||
|
||||
for (u32 level = 0; level < levels; level++) {
|
||||
const VideoCore::TextureBlit blit = {
|
||||
.src_level = level,
|
||||
.dst_level = level,
|
||||
.src_rect = GetRect(level),
|
||||
.dst_rect = GetScaledRect(level),
|
||||
};
|
||||
BlitScale(blit, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_sample_count > 1) {
|
||||
// Todo(wunk): Vulkan MSAA
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ enum Type {
|
|||
Current = -1,
|
||||
Base = 0,
|
||||
Scaled,
|
||||
MultiSampled,
|
||||
Custom,
|
||||
Copy,
|
||||
Num,
|
||||
|
|
@ -252,8 +253,8 @@ public:
|
|||
void Download(const VideoCore::BufferTextureCopy& download,
|
||||
const VideoCore::StagingData& staging);
|
||||
|
||||
/// Scales up the surface to match the new resolution scale.
|
||||
void ScaleUp(u32 new_scale);
|
||||
/// Scales up the surface to match the new resolution scale and sample-count.
|
||||
void ScaleUp(u32 new_scale, u8 new_sample_count);
|
||||
|
||||
/// Returns the bpp of the internal surface format
|
||||
u32 GetInternalBytesPerPixel() const;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue