mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-09 12:13:15 +00:00
video_core: Preliminary storage image support and more (#188)
* vk_rasterizer: Clear depth buffer when DB_RENDER_CONTROL says so * video_core: Preliminary storage image support, more opcodes * renderer_vulkan: a fix for vertex buffers merging * renderer_vulkan: a heuristic for blend override when alpha out is masked --------- Co-authored-by: psucien <bad_cast@protonmail.com>
This commit is contained in:
parent
23f11a3fda
commit
7b1a317b09
30 changed files with 429 additions and 101 deletions
|
@ -334,6 +334,19 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu
|
|||
if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Float) {
|
||||
return vk::Format::eR32Sfloat;
|
||||
}
|
||||
if (data_format == AmdGpu::DataFormat::Format16_16_16_16 &&
|
||||
num_format == AmdGpu::NumberFormat::Float) {
|
||||
return vk::Format::eR16G16B16A16Sfloat;
|
||||
}
|
||||
if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Uint) {
|
||||
return vk::Format::eR32Uint;
|
||||
}
|
||||
if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Sint) {
|
||||
return vk::Format::eR32Sint;
|
||||
}
|
||||
if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Unorm) {
|
||||
return vk::Format::eR8G8Unorm;
|
||||
}
|
||||
UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format));
|
||||
}
|
||||
|
||||
|
|
|
@ -111,14 +111,15 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
|
|||
|
||||
for (const auto& image : info.images) {
|
||||
const auto tsharp = info.ReadUd<AmdGpu::Image>(image.sgpr_base, image.dword_offset);
|
||||
const auto& image_view = texture_cache.FindImageView(tsharp);
|
||||
const auto& image_view = texture_cache.FindImageView(tsharp, image.is_storage);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, vk::ImageLayout::eGeneral);
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage
|
||||
: vk::DescriptorType::eSampledImage,
|
||||
.pImageInfo = &image_infos.back(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
const auto dst_color = LiverpoolToVK::BlendFactor(control.color_dst_factor);
|
||||
const auto color_blend = LiverpoolToVK::BlendOp(control.color_func);
|
||||
attachments[i] = vk::PipelineColorBlendAttachmentState{
|
||||
.blendEnable = key.blend_controls[i].enable,
|
||||
.blendEnable = control.enable,
|
||||
.srcColorBlendFactor = src_color,
|
||||
.dstColorBlendFactor = dst_color,
|
||||
.colorBlendOp = color_blend,
|
||||
|
@ -215,6 +215,29 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA
|
||||
: key.write_masks[i],
|
||||
};
|
||||
|
||||
// On GCN GPU there is an additional mask which allows to control color components exported
|
||||
// from a pixel shader. A situation possible, when the game may mask out the alpha channel,
|
||||
// while it is still need to be used in blending ops. For such cases, HW will default alpha
|
||||
// to 1 and perform the blending, while shader normally outputs 0 in the last component.
|
||||
// Unfortunatelly, Vulkan doesn't provide any control on blend inputs, so below we detecting
|
||||
// such cases and override alpha value in order to emulate HW behaviour.
|
||||
const auto has_alpha_masked_out =
|
||||
(key.cb_shader_mask.GetMask(i) & Liverpool::ColorBufferMask::ComponentA) == 0;
|
||||
const auto has_src_alpha_in_src_blend = src_color == vk::BlendFactor::eSrcAlpha ||
|
||||
src_color == vk::BlendFactor::eOneMinusSrcAlpha;
|
||||
const auto has_src_alpha_in_dst_blend = dst_color == vk::BlendFactor::eSrcAlpha ||
|
||||
dst_color == vk::BlendFactor::eOneMinusSrcAlpha;
|
||||
if (has_alpha_masked_out && has_src_alpha_in_src_blend) {
|
||||
attachments[i].srcColorBlendFactor = src_color == vk::BlendFactor::eSrcAlpha
|
||||
? vk::BlendFactor::eOne
|
||||
: vk::BlendFactor::eZero; // 1-A
|
||||
}
|
||||
if (has_alpha_masked_out && has_src_alpha_in_dst_blend) {
|
||||
attachments[i].dstColorBlendFactor = dst_color == vk::BlendFactor::eSrcAlpha
|
||||
? vk::BlendFactor::eOne
|
||||
: vk::BlendFactor::eZero; // 1-A
|
||||
}
|
||||
}
|
||||
|
||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||
|
@ -318,7 +341,7 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory, StreamBuffer&
|
|||
|
||||
for (const auto& image : stage.images) {
|
||||
const auto tsharp = stage.ReadUd<AmdGpu::Image>(image.sgpr_base, image.dword_offset);
|
||||
const auto& image_view = texture_cache.FindImageView(tsharp);
|
||||
const auto& image_view = texture_cache.FindImageView(tsharp, image.is_storage);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view,
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
set_writes.push_back({
|
||||
|
@ -326,7 +349,8 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory, StreamBuffer&
|
|||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage
|
||||
: vk::DescriptorType::eSampledImage,
|
||||
.pImageInfo = &image_infos.back(),
|
||||
});
|
||||
}
|
||||
|
@ -387,11 +411,11 @@ void GraphicsPipeline::BindVertexBuffers(StreamBuffer& staging) const {
|
|||
|
||||
boost::container::static_vector<BufferRange, MaxVertexBufferCount> ranges_merged{ranges[0]};
|
||||
for (auto range : ranges) {
|
||||
auto& prev_range = ranges.back();
|
||||
auto& prev_range = ranges_merged.back();
|
||||
if (prev_range.end_address < range.base_address) {
|
||||
ranges_merged.emplace_back(range);
|
||||
} else {
|
||||
ranges_merged.back().end_address = std::max(prev_range.end_address, range.end_address);
|
||||
prev_range.end_address = std::max(prev_range.end_address, range.end_address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct GraphicsPipelineKey {
|
|||
Liverpool::CullMode cull_mode;
|
||||
Liverpool::FrontFace front_face;
|
||||
Liverpool::ClipSpace clip_space;
|
||||
Liverpool::ColorBufferMask cb_shader_mask{};
|
||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ void PipelineCache::RefreshGraphicsKey() {
|
|||
key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable &&
|
||||
!col_buf.info.blend_bypass);
|
||||
key.write_masks[remapped_cb] = vk::ColorComponentFlags{regs.color_target_mask.GetMask(cb)};
|
||||
key.cb_shader_mask = regs.color_shader_mask;
|
||||
|
||||
++remapped_cb;
|
||||
}
|
||||
|
|
|
@ -60,13 +60,16 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
|
|||
});
|
||||
}
|
||||
if (regs.depth_control.depth_enable && regs.depth_buffer.Address() != 0) {
|
||||
const bool is_clear = regs.depth_render_control.depth_clear_enable;
|
||||
const auto& image_view =
|
||||
texture_cache.DepthTarget(regs.depth_buffer, liverpool->last_db_extent);
|
||||
depth_attachment = {
|
||||
.imageView = *image_view.image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
.loadOp = vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.loadOp = is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = is_clear ? vk::AttachmentStoreOp::eNone : vk::AttachmentStoreOp::eStore,
|
||||
.clearValue = vk::ClearValue{.depthStencil = {.depth = regs.depth_clear,
|
||||
.stencil = regs.stencil_clear}},
|
||||
};
|
||||
num_depth_attachments++;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue