Compare commits

...

2 commits

Author SHA1 Message Date
Maufeat
b9bcfe23f8 apply alpha 3.5 patch 2025-07-19 02:41:37 +02:00
Maufeat
1b23e2b8f1 apply amichuchu patch 2025-07-19 02:30:05 +02:00
17 changed files with 270 additions and 27 deletions

0
.gdbinit Normal file
View file

View file

@ -863,6 +863,7 @@ add_library(core STATIC
hle/service/nvdrv/nvmemp.cpp
hle/service/nvdrv/nvmemp.h
hle/service/nvnflinger/binder.h
hle/service/nvnflinger/buffer_history.h
hle/service/nvnflinger/buffer_item.h
hle/service/nvnflinger/buffer_item_consumer.cpp
hle/service/nvnflinger/buffer_item_consumer.h

View file

@ -14,24 +14,25 @@ class BufferHistoryManager {
public:
void PushEntry(s32 slot, s64 timestamp, s64 frame_number) {
std::lock_guard<std::mutex> lock(mutex_);
if (entries_.size() >= kMaxHistorySize) {
entries_.pop_front();
if (history_entries.size() >= kMaxHistorySize) {
history_entries.pop_front();
}
entries_.emplace_back(BufferHistoryEntry{slot, timestamp, frame_number});
history_entries.emplace_back(BufferHistoryEntry{slot, timestamp, frame_number});
}
s32 GetHistory(std::span<BufferHistoryEntry> out_entries) {
s32 GetHistory(s32 wantedEntries, std::span<BufferHistoryEntry>& entries) {
std::lock_guard<std::mutex> lock(mutex_);
s32 count =
std::min<s32>(static_cast<s32>(entries_.size()), static_cast<s32>(out_entries.size()));
for (s32 i = 0; i < count; ++i) {
out_entries[i] = entries_[entries_.size() - count + i];
s32 countToCopy = std::min<s32>(wantedEntries, static_cast<s32>(history_entries.size()));
auto out_entries = std::vector<BufferHistoryEntry>(countToCopy);
for (s32 i = 0; i < countToCopy; ++i) {
out_entries[i] = history_entries[history_entries.size() - countToCopy + i];
}
return count;
entries = std::span(out_entries);
return countToCopy;
}
private:
static constexpr size_t kMaxHistorySize = 16;
std::deque<BufferHistoryEntry> entries_;
std::deque<BufferHistoryEntry> history_entries;
std::mutex mutex_;
};

View file

@ -27,7 +27,7 @@ BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext&
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
Service::Nvidia::NvCore::NvMap& nvmap_)
: service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots),
nvmap(nvmap_) {
buffer_history(), nvmap(nvmap_) {
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
}
@ -35,6 +35,18 @@ BufferQueueProducer::~BufferQueueProducer() {
service_context.CloseEvent(buffer_wait_event);
}
Status BufferQueueProducer::GetBufferHistory(s32 count, std::span<BufferHistoryEntry>& entries) {
if (count <= 0) {
LOG_ERROR(Service_Nvnflinger, "count must be positive");
entries = std::span<BufferHistoryEntry>();
return Status::BadValue;
} else {
buffer_history.GetHistory(count, entries);
return Status::NoError;
}
}
Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf) {
LOG_DEBUG(Service_Nvnflinger, "slot {}", slot);
@ -516,6 +528,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
slots[slot].buffer_state = BufferState::Queued;
++core->frame_counter;
slots[slot].frame_number = core->frame_counter;
buffer_history.PushEntry(slot, timestamp, static_cast<s64>(core->frame_counter));
item.acquire_called = slots[slot].acquire_called;
item.graphic_buffer = slots[slot].graphic_buffer;
@ -928,9 +941,18 @@ void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
}
case TransactionId::GetBufferHistory: {
LOG_DEBUG(Service_Nvnflinger, "GetBufferHistory");
auto out_span = parcel_in.Read<std::span<BufferHistoryEntry>>();
s32 count = buffer_history_.GetHistory(out_span);
parcel_out.Write(s32(count));
auto entries_wanted = parcel_in.Read<s32>();
if (entries_wanted <= 0) {
parcel_out.Write<s32>(0);
status = Status::BadValue;
}
else {
std::span<BufferHistoryEntry> entries;
buffer_history.GetHistory(entries_wanted, entries);
parcel_out.Write(static_cast<s32>(entries.size()));
parcel_out.Write(entries);
status = Status::NoError;
}
break;
}
default:

View file

@ -13,6 +13,7 @@
#include <memory>
#include <mutex>
#include "buffer_history.h"
#include "common/common_funcs.h"
#include "core/hle/service/nvdrv/nvdata.h"
#include "core/hle/service/nvnflinger/binder.h"
@ -59,6 +60,7 @@ public:
public:
Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
Status SetBufferCount(s32 buffer_count);
Status GetBufferHistory(s32 count, std::span<BufferHistoryEntry>& entries);
Status DequeueBuffer(s32* out_slot, android::Fence* out_fence, bool async, u32 width,
u32 height, PixelFormat format, u32 usage);
Status DetachBuffer(s32 slot);
@ -84,7 +86,7 @@ private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
BufferHistoryManager buffer_history_;
BufferHistoryManager buffer_history;
u32 sticky_transform{};
std::mutex callback_mutex;
s32 next_callback_ticket{};

View file

@ -21,8 +21,12 @@ set(SHADER_FILES
convert_abgr8_srgb_to_d24s8.frag
convert_abgr8_to_d24s8.frag
convert_abgr8_to_d32f.frag
convert_r8_to_abgr8.frag
convert_abgr8_to_r8.frag
convert_d32f_to_abgr8.frag
convert_d24s8_to_abgr8.frag
convert_bgra8_to_s8d24.frag
convert_b10gr11f_to_abgr8.frag
convert_depth_to_float.frag
convert_float_to_depth.frag
convert_msaa_to_non_msaa.comp

View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout(binding = 0) uniform sampler2D tex;
layout(location = 0) out float color;
layout(push_constant) uniform PushConstants {
uniform vec2 tex_scale;
uniform vec2 tex_offset;
};
void main() {
vec2 coord = gl_FragCoord.xy / tex_scale * textureSize(tex, 0);
vec4 fetch = texelFetch(tex, ivec2(coord), 0);
color = fetch.r;
}

View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout(binding = 0) uniform sampler2D tex;
layout(push_constant) uniform PushConstants {
uniform vec2 tex_scale;
uniform vec2 tex_offset;
};
layout(location = 0) out vec4 color;
void main() {
vec2 coord = gl_FragCoord.xy / tex_scale * textureSize(tex, 0);
vec4 fetch = texelFetch(tex, ivec2(coord), 0);
color = vec4(fetch.rgb, 1.0);
}

View file

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
#extension GL_ARB_shader_stencil_export : require
layout(binding = 0) uniform sampler2D color_texture;
void main() {
ivec2 coord = ivec2(gl_FragCoord.xy);
uvec4 color = uvec4(texelFetch(color_texture, coord, 0).bgra * (exp2(8) - 1.0f));
uvec4 bytes = color << uvec4(24, 16, 8, 0);
uint depth_stencil_unorm = bytes.x | bytes.y | bytes.z | bytes.w;
gl_FragDepth = float(depth_stencil_unorm >> 24) / (exp2(24.0) - 1.0f);
gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FFFFFFu);
}

View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout(binding = 0) uniform sampler2D tex;
layout(push_constant) uniform PushConstants {
uniform vec2 tex_scale;
uniform vec2 tex_offset;
};
layout(location = 0) out vec4 color;
void main() {
vec2 coord = gl_FragCoord.xy / tex_scale * textureSize(tex, 0);
float red = texelFetch(tex, ivec2(coord), 0).r;
color = vec4(1.0, red, red, red);
}

View file

@ -11,8 +11,11 @@
#include "video_core/host_shaders/convert_abgr8_to_d32f_frag_spv.h"
#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_d32f_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_r8_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
#include "video_core/host_shaders/convert_b10gr11f_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_bgra8_to_s8d24_frag_spv.h"
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
@ -29,6 +32,7 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/host_shaders/convert_abgr8_srgb_to_d24s8_frag_spv.h"
#include "video_core/host_shaders/convert_abgr8_to_r8_frag_spv.h"
#include "video_core/host_shaders/convert_rgba8_to_bgra8_frag_spv.h"
#include "video_core/host_shaders/convert_yuv420_to_rgb_comp_spv.h"
#include "video_core/host_shaders/convert_rgb_to_yuv420_comp_spv.h"
@ -385,6 +389,17 @@ VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
};
}
VkExtent2D GetConversionExtent(const Framebuffer* framebuffer) {
const auto& resolution = Settings::values.resolution_info;
const bool is_rescaled = framebuffer->IsRescaled();
u32 width = framebuffer->RenderArea().width;
u32 height = framebuffer->RenderArea().height;
return VkExtent2D{
.width = is_rescaled ? resolution.ScaleUp(width) : width,
.height = is_rescaled ? resolution.ScaleUp(height) : height,
};
}
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) {
constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
@ -442,13 +457,17 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)},
two_textures_descriptor_allocator{
descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
push_constant_range({
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>,
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstants)>
}),
one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
one_texture_set_layout.address(),
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))),
push_constant_range))),
two_textures_pipeline_layout(
device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
two_textures_set_layout.address(),
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))),
push_constant_range))),
clear_color_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
nullptr, PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(float) * 4>))),
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
@ -461,10 +480,14 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
convert_abgr8_to_d32f_frag(BuildShader(device, CONVERT_ABGR8_TO_D32F_FRAG_SPV)),
convert_abgr8_to_r8_frag(BuildShader(device, CONVERT_ABGR8_TO_R8_FRAG_SPV)),
convert_r8_to_abgr8_frag(BuildShader(device, CONVERT_R8_TO_ABGR8_FRAG_SPV)),
convert_d32f_to_abgr8_frag(BuildShader(device, CONVERT_D32F_TO_ABGR8_FRAG_SPV)),
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
convert_abgr8_srgb_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_SRGB_TO_D24S8_FRAG_SPV)),
convert_b10gr11f_to_abgr8_frag(BuildShader(device, CONVERT_B10GR11F_TO_ABGR8_FRAG_SPV)),
convert_bgra8_to_s8d24_frag(BuildShader(device, CONVERT_BGRA8_TO_S8D24_FRAG_SPV)),
convert_rgba_to_bgra_frag(BuildShader(device, CONVERT_RGBA8_TO_BGRA8_FRAG_SPV)),
convert_yuv420_to_rgb_comp(BuildShader(device, CONVERT_YUV420_TO_RGB_COMP_SPV)),
convert_rgb_to_yuv420_comp(BuildShader(device, CONVERT_RGB_TO_YUV420_COMP_SPV)),
@ -588,6 +611,20 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertR8ToABGR8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_r8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
convert_r8_to_abgr8_frag);
Convert(*convert_r8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertABGR8ToR8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_abgr8_to_r8_pipeline, dst_framebuffer->RenderPass(),
convert_abgr8_to_r8_frag);
Convert(*convert_abgr8_to_r8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
@ -631,6 +668,21 @@ void BlitImageHelper::ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer
Convert(*convert_abgr8_srgb_to_d24s8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertB10GR11ToABGR8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineDepthTargetEx(convert_b10gr11f_to_abgr8_pipeline,
dst_framebuffer->RenderPass(),
convert_b10gr11f_to_abgr8_frag);
Convert(*convert_b10gr11f_to_abgr8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertBGRA8ToS8D24(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineDepthTargetEx(convert_bgra8_to_s8d24_pipeline, dst_framebuffer->RenderPass(),
convert_bgra8_to_s8d24_frag);
Convert(*convert_bgra8_to_s8d24_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
const std::array<f32, 4>& clear_color,
const Region2D& dst_region) {
@ -684,10 +736,10 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
const VkSampler sampler = *nearest_sampler;
const VkExtent2D extent = GetConversionExtent(src_image_view);
const VkExtent2D extent = GetConversionExtent(dst_framebuffer);
scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) {
scheduler.Record([pipeline, layout, sampler, src_view, extent, this, dst_framebuffer](vk::CommandBuffer cmdbuf) {
const VkOffset2D offset{
.x = 0,
.y = 0,
@ -704,9 +756,16 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
.offset = offset,
.extent = extent,
};
const PushConstants push_constants{
/*const PushConstants push_constants_vertex{
.tex_scale = {viewport.width, viewport.height},
.tex_offset = {0.0f, 0.0f},
};*/
const PushConstants push_constants_frag{
.tex_scale = {
static_cast<float>(dst_framebuffer->RenderArea().width),
static_cast<float>(dst_framebuffer->RenderArea().height)
},
.tex_offset = {0.0f, 0.0f},
};
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
@ -717,7 +776,8 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
nullptr);
cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants_frag);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants_frag);
cmdbuf.Draw(3, 1, 0, 0);
});
scheduler.InvalidateState();

View file

@ -65,6 +65,10 @@ public:
void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertR8ToABGR8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8ToR8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
@ -77,6 +81,10 @@ public:
void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
void ConvertB10GR11ToABGR8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertBGRA8ToS8D24(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
const std::array<f32, 4>& clear_color, const Region2D& dst_region);
@ -131,6 +139,7 @@ private:
vk::DescriptorSetLayout two_textures_set_layout;
DescriptorAllocator one_texture_descriptor_allocator;
DescriptorAllocator two_textures_descriptor_allocator;
std::vector<VkPushConstantRange> push_constant_range;
vk::PipelineLayout one_texture_pipeline_layout;
vk::PipelineLayout two_textures_pipeline_layout;
vk::PipelineLayout clear_color_pipeline_layout;
@ -144,10 +153,15 @@ private:
vk::ShaderModule convert_float_to_depth_frag;
vk::ShaderModule convert_abgr8_to_d24s8_frag;
vk::ShaderModule convert_abgr8_to_d32f_frag;
vk::ShaderModule convert_abgr8_to_r8_frag;
vk::ShaderModule convert_r8_to_abgr8_frag;
vk::ShaderModule convert_d32f_to_abgr8_frag;
vk::ShaderModule convert_d24s8_to_abgr8_frag;
vk::ShaderModule convert_s8d24_to_abgr8_frag;
vk::ShaderModule convert_s8d24_to_bgra8_frag;
vk::ShaderModule convert_abgr8_srgb_to_d24s8_frag;
vk::ShaderModule convert_b10gr11f_to_abgr8_frag;
vk::ShaderModule convert_bgra8_to_s8d24_frag;
vk::ShaderModule convert_rgba_to_bgra_frag;
vk::ShaderModule convert_yuv420_to_rgb_comp;
vk::ShaderModule convert_rgb_to_yuv420_comp;
@ -176,7 +190,11 @@ private:
vk::Pipeline convert_d32f_to_abgr8_pipeline;
vk::Pipeline convert_d24s8_to_abgr8_pipeline;
vk::Pipeline convert_s8d24_to_abgr8_pipeline;
vk::Pipeline convert_r8_to_abgr8_pipeline;
vk::Pipeline convert_abgr8_to_r8_pipeline;
vk::Pipeline convert_abgr8_srgb_to_d24s8_pipeline;
vk::Pipeline convert_bgra8_to_s8d24_pipeline;
vk::Pipeline convert_b10gr11f_to_abgr8_pipeline;
vk::Pipeline convert_rgba_to_bgra_pipeline;
vk::Pipeline convert_yuv420_to_rgb_pipeline;
vk::Pipeline convert_rgb_to_yuv420_pipeline;

View file

@ -518,6 +518,14 @@ void RasterizerVulkan::DispatchCompute() {
}
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
scheduler.RequestOutsideRenderPassOperationContext();
static constexpr VkMemoryBarrier READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
};
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, READ_BARRIER); });
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
}

View file

@ -1219,8 +1219,27 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view);
}
break;
case PixelFormat::R8_UNORM:
if (src_view.format == PixelFormat::A8B8G8R8_UNORM) {
return blit_image_helper.ConvertABGR8ToR8(dst, src_view);
}
break;
case PixelFormat::A8B8G8R8_UNORM:
if (src_view.format == PixelFormat::R8_UNORM) {
return blit_image_helper.ConvertR8ToABGR8(dst, src_view);
}
if (src_view.format == PixelFormat::B10G11R11_FLOAT) {
return blit_image_helper.ConvertB10GR11ToABGR8(dst, src_view);
}
if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
return blit_image_helper.ConvertS8D24ToABGR8(dst, src_view);
}
break;
case PixelFormat::S8_UINT_D24_UNORM:
if (src_view.format == PixelFormat::B8G8R8A8_UNORM) {
return blit_image_helper.ConvertBGRA8ToS8D24(dst, src_view);
}
break;
case PixelFormat::A8B8G8R8_SNORM:
case PixelFormat::A8B8G8R8_SINT:
case PixelFormat::A8B8G8R8_UINT:
@ -1232,7 +1251,6 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
case PixelFormat::A2R10G10B10_UNORM:
case PixelFormat::A1B5G5R5_UNORM:
case PixelFormat::A5B5G5R1_UNORM:
case PixelFormat::R8_UNORM:
case PixelFormat::R8_SNORM:
case PixelFormat::R8_SINT:
case PixelFormat::R8_UINT:
@ -1319,12 +1337,12 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
case PixelFormat::D16_UNORM:
case PixelFormat::X8_D24_UNORM:
case PixelFormat::S8_UINT:
case PixelFormat::S8_UINT_D24_UNORM:
case PixelFormat::D32_FLOAT_S8_UINT:
case PixelFormat::Invalid:
default:
break;
}
LOG_WARNING(Render_Vulkan, "Unimplemented texture conversion from {} to {} format type", src_view.format, dst_view.format);
}
VkFormat TextureCacheRuntime::GetSupportedFormat(VkFormat requested_format,

View file

@ -237,6 +237,38 @@ SurfaceType GetFormatType(PixelFormat pixel_format) {
return SurfaceType::Invalid;
}
bool HasAlpha(PixelFormat pixel_format) {
switch (pixel_format) {
case PixelFormat::A8B8G8R8_UNORM:
case PixelFormat::A8B8G8R8_SNORM:
case PixelFormat::A8B8G8R8_SINT:
case PixelFormat::A8B8G8R8_UINT:
case PixelFormat::A1R5G5B5_UNORM:
case PixelFormat::A2B10G10R10_UNORM:
case PixelFormat::A2B10G10R10_UINT:
case PixelFormat::A2R10G10B10_UNORM:
case PixelFormat::A1B5G5R5_UNORM:
case PixelFormat::A5B5G5R1_UNORM:
case PixelFormat::R16G16B16A16_FLOAT:
case PixelFormat::R16G16B16A16_UNORM:
case PixelFormat::R16G16B16A16_SNORM:
case PixelFormat::R16G16B16A16_SINT:
case PixelFormat::R16G16B16A16_UINT:
case PixelFormat::R32G32B32A32_UINT:
case PixelFormat::BC1_RGBA_UNORM:
case PixelFormat::B8G8R8A8_UNORM:
case PixelFormat::R32G32B32A32_FLOAT:
case PixelFormat::R32G32B32A32_SINT:
case PixelFormat::A8B8G8R8_SRGB:
case PixelFormat::B8G8R8A8_SRGB:
case PixelFormat::BC1_RGBA_SRGB:
case PixelFormat::A4B4G4R4_UNORM:
return true;
default:
return false;
}
}
bool IsPixelFormatASTC(PixelFormat format) {
switch (format) {
case PixelFormat::ASTC_2D_4X4_UNORM:

View file

@ -503,6 +503,8 @@ PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format);
SurfaceType GetFormatType(PixelFormat pixel_format);
bool HasAlpha(PixelFormat pixel_format);
bool IsPixelFormatASTC(PixelFormat format);
bool IsPixelFormatBCn(PixelFormat format);

View file

@ -26,6 +26,7 @@ namespace VideoCommon {
using Tegra::Texture::TICEntry;
using Tegra::Texture::TSCEntry;
using VideoCore::Surface::GetFormatType;
using VideoCore::Surface::HasAlpha;
using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::SurfaceType;
using namespace Common::Literals;
@ -2398,7 +2399,7 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
}
const auto dst_format_type = GetFormatType(dst.info.format);
const auto src_format_type = GetFormatType(src.info.format);
if (src_format_type == dst_format_type) {
if (src_format_type == dst_format_type && HasAlpha(src.info.format) == HasAlpha(dst.info.format)) {
if constexpr (HAS_EMULATED_COPIES) {
if (!runtime.CanImageBeCopied(dst, src)) {
return runtime.EmulateCopyImage(dst, src, copies);
@ -2406,8 +2407,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
}
return runtime.CopyImage(dst, src, copies);
}
UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D);
UNIMPLEMENTED_IF(src.info.type != ImageType::e2D);
UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D && dst.info.type != ImageType::Linear);
UNIMPLEMENTED_IF(src.info.type != ImageType::e2D && dst.info.type != ImageType::Linear);
if (runtime.ShouldReinterpret(dst, src)) {
return runtime.ReinterpretImage(dst, src, copies);
}