Browse Source

Inline unique_ptr versions of framebuffers + normal buffers + images

pull/3317/head
lizzie 3 weeks ago
parent
commit
f083b9052f
  1. 17
      src/video_core/renderer_opengl/gl_texture_cache.cpp
  2. 2
      src/video_core/renderer_opengl/gl_texture_cache.h
  3. 51
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  4. 74
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  5. 189
      src/video_core/renderer_vulkan/vk_texture_cache.h
  6. 8
      src/video_core/texture_cache/texture_cache.h

17
src/video_core/renderer_opengl/gl_texture_cache.cpp

@ -1214,19 +1214,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageV
ImageView::~ImageView() = default;
GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) {
if (image_format == Shader::ImageFormat::Typeless) {
if (image_format == Shader::ImageFormat::Typeless)
return Handle(texture_type);
}
const bool is_signed{image_format == Shader::ImageFormat::R8_SINT ||
image_format == Shader::ImageFormat::R16_SINT};
if (!storage_views) {
storage_views = std::make_unique<StorageViews>();
}
const bool is_signed = image_format == Shader::ImageFormat::R8_SINT
|| image_format == Shader::ImageFormat::R16_SINT;
if (!storage_views)
storage_views = std::make_optional<StorageViews>();
auto& type_views{is_signed ? storage_views->signeds : storage_views->unsigneds};
GLuint& view{type_views[static_cast<size_t>(texture_type)]};
if (view == 0) {
GLuint& view{type_views[size_t(texture_type)]};
if (view == 0)
view = MakeView(texture_type, ShaderFormat(image_format));
}
return view;
}

2
src/video_core/renderer_opengl/gl_texture_cache.h

@ -302,7 +302,7 @@ private:
std::array<GLuint, Shader::NUM_TEXTURE_TYPES> views{};
std::vector<OGLTextureView> stored_views;
std::unique_ptr<StorageViews> storage_views;
std::optional<StorageViews> storage_views;
GLenum internal_format = GL_NONE;
GLuint default_handle = 0;
u32 buffer_size = 0;

51
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -376,7 +376,6 @@ void RasterizerVulkan::DrawTexture() {
}
void RasterizerVulkan::Clear(u32 layer_count) {
FlushWork();
gpu_memory->FlushCaching();
@ -396,9 +395,7 @@ void RasterizerVulkan::Clear(u32 layer_count) {
scheduler.RequestRenderpass(framebuffer);
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
u32 up_scale = 1;
u32 down_shift = 0;
if (texture_cache.IsRescaling()) {
@ -443,14 +440,14 @@ void RasterizerVulkan::Clear(u32 layer_count) {
offset = 0;
return;
}
if (offset >= static_cast<s32>(limit)) {
offset = static_cast<s32>(limit);
if (offset >= s32(limit)) {
offset = s32(limit);
extent = 0;
return;
}
const u64 end_coord = static_cast<u64>(offset) + extent;
const u64 end_coord = u64(offset) + extent;
if (end_coord > limit) {
extent = limit - static_cast<u32>(offset);
extent = limit - u32(offset);
}
};
@ -464,30 +461,22 @@ void RasterizerVulkan::Clear(u32 layer_count) {
const u32 color_attachment = regs.clear_surface.RT;
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
const auto format =
VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
const auto format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
bool is_integer = IsPixelFormatInteger(format);
bool is_signed = IsPixelFormatSignedInteger(format);
size_t int_size = PixelComponentSizeBitsInteger(format);
VkClearValue clear_value{};
if (!is_integer) {
std::memcpy(clear_value.color.float32, regs.clear_color.data(),
regs.clear_color.size() * sizeof(f32));
std::memcpy(clear_value.color.float32, regs.clear_color.data(), regs.clear_color.size() * sizeof(f32));
} else if (!is_signed) {
for (size_t i = 0; i < 4; i++) {
clear_value.color.uint32[i] = static_cast<u32>(
static_cast<f32>(static_cast<u64>(int_size) << 1U) * regs.clear_color[i]);
}
for (size_t i = 0; i < 4; i++)
clear_value.color.uint32[i] = u32(f32(u64(int_size) << 1U) * regs.clear_color[i]);
} else {
for (size_t i = 0; i < 4; i++) {
clear_value.color.int32[i] =
static_cast<s32>(static_cast<f32>(static_cast<s64>(int_size - 1) << 1) *
(regs.clear_color[i] - 0.5f));
}
for (size_t i = 0; i < 4; i++)
clear_value.color.int32[i] = s32(f32(s64(int_size - 1) << 1) * (regs.clear_color[i] - 0.5f));
}
if (regs.clear_surface.R && regs.clear_surface.G && regs.clear_surface.B &&
regs.clear_surface.A) {
if (regs.clear_surface.R && regs.clear_surface.G && regs.clear_surface.B && regs.clear_surface.A) {
scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
const VkClearAttachment attachment{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@ -497,14 +486,11 @@ void RasterizerVulkan::Clear(u32 layer_count) {
cmdbuf.ClearAttachments(attachment, clear_rect);
});
} else {
u8 color_mask = static_cast<u8>(regs.clear_surface.R | regs.clear_surface.G << 1 |
regs.clear_surface.B << 2 | regs.clear_surface.A << 3);
u8 color_mask = u8(regs.clear_surface.R | regs.clear_surface.G << 1 | regs.clear_surface.B << 2 | regs.clear_surface.A << 3);
Region2D dst_region = {
Offset2D{.x = clear_rect.rect.offset.x, .y = clear_rect.rect.offset.y},
Offset2D{.x = clear_rect.rect.offset.x +
static_cast<s32>(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y +
static_cast<s32>(clear_rect.rect.extent.height)}};
Offset2D{.x = clear_rect.rect.offset.x + s32(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y + s32(clear_rect.rect.extent.height)}};
blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region);
}
}
@ -527,11 +513,10 @@ void RasterizerVulkan::Clear(u32 layer_count) {
regs.stencil_front_mask != 0) {
Region2D dst_region = {
Offset2D{.x = clear_rect.rect.offset.x, .y = clear_rect.rect.offset.y},
Offset2D{.x = clear_rect.rect.offset.x + static_cast<s32>(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y +
static_cast<s32>(clear_rect.rect.extent.height)}};
Offset2D{.x = clear_rect.rect.offset.x + s32(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y + s32(clear_rect.rect.extent.height)}};
blit_image.ClearDepthStencil(framebuffer, use_depth, regs.clear_depth,
static_cast<u8>(regs.stencil_front_mask), regs.clear_stencil,
u8(regs.stencil_front_mask), regs.clear_stencil,
regs.stencil_front_func_mask, dst_region);
} else {
scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,

74
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -860,8 +860,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
compute_pass_descriptor_queue, memory_allocator);
}
if (device.IsStorageImageMultisampleSupported()) {
msaa_copy_pass = std::make_unique<MSAACopyPass>(
device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue);
msaa_copy_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue);
}
if (!device.IsKhrImageFormatListSupported()) {
return;
@ -1675,10 +1674,10 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
// CHANGE: Gate the MSAA path more strictly and only use it for color, when the pass and device
// support are available. Avoid running the MSAA path when prerequisites aren't met,
// preventing validation and runtime issues.
const bool wants_msaa_upload = info.num_samples > 1 &&
(aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0 &&
runtime->CanUploadMSAA() && runtime->msaa_copy_pass != nullptr &&
runtime->device.IsStorageImageMultisampleSupported();
const bool wants_msaa_upload = info.num_samples > 1
&& (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0
&& runtime->CanUploadMSAA() && runtime->msaa_copy_pass.has_value()
&& runtime->device.IsStorageImageMultisampleSupported();
if (wants_msaa_upload) {
// Create a temporary non-MSAA image to upload the data first
@ -2047,8 +2046,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
const u32 scaled_width = resolution.ScaleUp(info.size.width);
const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height;
std::unique_ptr<ImageView>& blit_view = scale_up ? scale_view : normal_view;
std::unique_ptr<Framebuffer>& blit_framebuffer =
scale_up ? scale_framebuffer : normal_framebuffer;
std::optional<Framebuffer>& blit_framebuffer = scale_up ? scale_framebuffer : normal_framebuffer;
if (!blit_view) {
const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format);
blit_view = std::make_unique<ImageView>(*runtime, view_info, NULL_IMAGE_ID, *this);
@ -2060,11 +2058,11 @@ bool Image::BlitScaleHelper(bool scale_up) {
const u32 dst_height = scale_up ? scaled_height : info.size.height;
const Region2D src_region{
.start = {0, 0},
.end = {static_cast<s32>(src_width), static_cast<s32>(src_height)},
.end = {s32(src_width), s32(src_height)},
};
const Region2D dst_region{
.start = {0, 0},
.end = {static_cast<s32>(dst_width), static_cast<s32>(dst_height)},
.end = {s32(dst_width), s32(dst_height)},
};
const VkExtent2D extent{
.width = (std::max)(scaled_width, info.size.width),
@ -2073,21 +2071,15 @@ bool Image::BlitScaleHelper(bool scale_up) {
auto* view_ptr = blit_view.get();
if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) {
if (!blit_framebuffer) {
blit_framebuffer =
std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent, scale_up);
}
runtime->blit_image_helper.BlitColor(blit_framebuffer.get(), *blit_view, dst_region,
src_region, operation, BLIT_OPERATION);
if (!blit_framebuffer)
blit_framebuffer.emplace(*runtime, view_ptr, nullptr, extent, scale_up);
runtime->blit_image_helper.BlitColor(&*blit_framebuffer, *blit_view,
dst_region, src_region, operation, BLIT_OPERATION);
} else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if (!blit_framebuffer) {
blit_framebuffer =
std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent, scale_up);
}
runtime->blit_image_helper.BlitDepthStencil(blit_framebuffer.get(), *blit_view,
dst_region, src_region, operation,
BLIT_OPERATION);
if (!blit_framebuffer)
blit_framebuffer.emplace(*runtime, nullptr, view_ptr, extent, scale_up);
runtime->blit_image_helper.BlitDepthStencil(&*blit_framebuffer, *blit_view,
dst_region, src_region, operation, BLIT_OPERATION);
} else {
// TODO: Use helper blits where applicable
flags &= ~ImageFlagBits::Rescaled;
@ -2200,9 +2192,9 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
}
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs)
: ImageView{runtime, info, image_id_, image} {
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs)
: ImageView{runtime, info, image_id_, image}
{
slot_images = &slot_imgs;
}
@ -2267,33 +2259,25 @@ VkImageView ImageView::ColorView() {
VkImageView ImageView::StorageView(Shader::TextureType texture_type,
Shader::ImageFormat image_format) {
if (!image_handle) {
return VK_NULL_HANDLE;
}
if (image_handle) {
if (image_format == Shader::ImageFormat::Typeless) {
return Handle(texture_type);
}
const bool is_signed{image_format == Shader::ImageFormat::R8_SINT ||
image_format == Shader::ImageFormat::R16_SINT};
if (!storage_views) {
storage_views = std::make_unique<StorageViews>();
}
const bool is_signed = image_format == Shader::ImageFormat::R8_SINT
|| image_format == Shader::ImageFormat::R16_SINT;
if (!storage_views)
storage_views = std::make_optional<StorageViews>();
auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds};
auto& view{views[static_cast<size_t>(texture_type)]};
if (view) {
return *view;
}
auto& view{views[size_t(texture_type)]};
if (!view)
view = MakeView(Format(image_format), VK_IMAGE_ASPECT_COLOR_BIT);
return *view;
}
return VK_NULL_HANDLE;
}
bool ImageView::IsRescaled() const noexcept {
if (!slot_images) {
return false;
}
const auto& slots = *slot_images;
const auto& src_image = slots[image_id];
return src_image.IsRescaled();
return (*slot_images)[image_id].IsRescaled();
}
vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {

189
src/video_core/renderer_vulkan/vk_texture_cache.h

@ -133,7 +133,7 @@ public:
vk::Buffer swizzle_table_buffer;
VkDeviceSize swizzle_table_size = 0;
std::unique_ptr<MSAACopyPass> msaa_copy_pass;
std::optional<MSAACopyPass> msaa_copy_pass;
const Settings::ResolutionScalingInfo& resolution;
std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats;
@ -141,6 +141,110 @@ public:
std::array<vk::Buffer, indexing_slots> buffers{};
};
class Sampler {
public:
explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&);
[[nodiscard]] VkSampler Handle() const noexcept {
return *sampler;
}
[[nodiscard]] VkSampler HandleWithDefaultAnisotropy() const noexcept {
return *sampler_default_anisotropy;
}
[[nodiscard]] bool HasAddedAnisotropy() const noexcept {
return static_cast<bool>(sampler_default_anisotropy);
}
private:
vk::Sampler sampler;
vk::Sampler sampler_default_anisotropy;
};
class Framebuffer {
public:
explicit Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers,
ImageView* depth_buffer, const VideoCommon::RenderTargets& key);
explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer,
ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled);
~Framebuffer();
Framebuffer(const Framebuffer&) = delete;
Framebuffer& operator=(const Framebuffer&) = delete;
Framebuffer(Framebuffer&&) = default;
Framebuffer& operator=(Framebuffer&&) = default;
void CreateFramebuffer(TextureCacheRuntime& runtime,
std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer,
bool is_rescaled = false);
[[nodiscard]] VkFramebuffer Handle() const noexcept {
return *framebuffer;
}
[[nodiscard]] VkRenderPass RenderPass() const noexcept {
return renderpass;
}
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
return render_area;
}
[[nodiscard]] VkSampleCountFlagBits Samples() const noexcept {
return samples;
}
[[nodiscard]] u32 NumColorBuffers() const noexcept {
return num_color_buffers;
}
[[nodiscard]] u32 NumImages() const noexcept {
return num_images;
}
[[nodiscard]] const std::array<VkImage, 9>& Images() const noexcept {
return images;
}
[[nodiscard]] const std::array<VkImageSubresourceRange, 9>& ImageRanges() const noexcept {
return image_ranges;
}
[[nodiscard]] bool HasAspectColorBit(size_t index) const noexcept {
return (image_ranges.at(rt_map[index]).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
}
[[nodiscard]] bool HasAspectDepthBit() const noexcept {
return has_depth;
}
[[nodiscard]] bool HasAspectStencilBit() const noexcept {
return has_stencil;
}
[[nodiscard]] bool IsRescaled() const noexcept {
return is_rescaled;
}
private:
vk::Framebuffer framebuffer;
VkRenderPass renderpass{};
VkExtent2D render_area{};
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
u32 num_color_buffers = 0;
u32 num_images = 0;
std::array<VkImage, 9> images{};
std::array<VkImageSubresourceRange, 9> image_ranges{};
std::array<size_t, NUM_RT> rt_map{};
bool has_depth{};
bool has_stencil{};
bool is_rescaled{};
};
class Image : public VideoCommon::ImageBase {
public:
explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr,
@ -331,89 +435,6 @@ private:
vk::Sampler sampler_default_anisotropy;
};
class Framebuffer {
public:
explicit Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers,
ImageView* depth_buffer, const VideoCommon::RenderTargets& key);
explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer,
ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled);
~Framebuffer();
Framebuffer(const Framebuffer&) = delete;
Framebuffer& operator=(const Framebuffer&) = delete;
Framebuffer(Framebuffer&&) = default;
Framebuffer& operator=(Framebuffer&&) = default;
void CreateFramebuffer(TextureCacheRuntime& runtime,
std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer,
bool is_rescaled = false);
[[nodiscard]] VkFramebuffer Handle() const noexcept {
return *framebuffer;
}
[[nodiscard]] VkRenderPass RenderPass() const noexcept {
return renderpass;
}
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
return render_area;
}
[[nodiscard]] VkSampleCountFlagBits Samples() const noexcept {
return samples;
}
[[nodiscard]] u32 NumColorBuffers() const noexcept {
return num_color_buffers;
}
[[nodiscard]] u32 NumImages() const noexcept {
return num_images;
}
[[nodiscard]] const std::array<VkImage, 9>& Images() const noexcept {
return images;
}
[[nodiscard]] const std::array<VkImageSubresourceRange, 9>& ImageRanges() const noexcept {
return image_ranges;
}
[[nodiscard]] bool HasAspectColorBit(size_t index) const noexcept {
return (image_ranges.at(rt_map[index]).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
}
[[nodiscard]] bool HasAspectDepthBit() const noexcept {
return has_depth;
}
[[nodiscard]] bool HasAspectStencilBit() const noexcept {
return has_stencil;
}
[[nodiscard]] bool IsRescaled() const noexcept {
return is_rescaled;
}
private:
vk::Framebuffer framebuffer;
VkRenderPass renderpass{};
VkExtent2D render_area{};
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
u32 num_color_buffers = 0;
u32 num_images = 0;
std::array<VkImage, 9> images{};
std::array<VkImageSubresourceRange, 9> image_ranges{};
std::array<size_t, NUM_RT> rt_map{};
bool has_depth{};
bool has_stencil{};
bool is_rescaled{};
};
struct TextureCacheParams {
static constexpr bool ENABLE_VALIDATION = true;
static constexpr bool FRAMEBUFFER_BLITS = false;

8
src/video_core/texture_cache/texture_cache.h

@ -596,10 +596,10 @@ FramebufferId TextureCache<P>::GetFramebufferId(const RenderTargets& key) {
return framebuffer_id;
}
std::array<ImageView*, NUM_RT> color_buffers;
std::ranges::transform(key.color_buffer_ids, color_buffers.begin(),
[this](ImageViewId id) { return id ? &slot_image_views[id] : nullptr; });
ImageView* const depth_buffer =
key.depth_buffer_id ? &slot_image_views[key.depth_buffer_id] : nullptr;
std::ranges::transform(key.color_buffer_ids, color_buffers.begin(), [this](ImageViewId id) {
return id ? &slot_image_views[id] : nullptr;
});
ImageView* const depth_buffer = key.depth_buffer_id ? &slot_image_views[key.depth_buffer_id] : nullptr;
framebuffer_id = slot_framebuffers.insert(runtime, color_buffers, depth_buffer, key);
return framebuffer_id;
}

Loading…
Cancel
Save