mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 00:13:08 +00:00
video_core: refactored post processing pipeline to another file
This commit is contained in:
parent
63c8e05abd
commit
c617f9d002
@ -845,6 +845,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderer_vulkan/vk_shader_util.h
|
src/video_core/renderer_vulkan/vk_shader_util.h
|
||||||
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
||||||
src/video_core/renderer_vulkan/vk_swapchain.h
|
src/video_core/renderer_vulkan/vk_swapchain.h
|
||||||
|
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
|
||||||
|
src/video_core/renderer_vulkan/host_passes/pp_pass.h
|
||||||
src/video_core/texture_cache/image.cpp
|
src/video_core/texture_cache/image.cpp
|
||||||
src/video_core/texture_cache/image.h
|
src/video_core/texture_cache/image.h
|
||||||
src/video_core/texture_cache/image_info.cpp
|
src/video_core/texture_cache/image_info.cpp
|
||||||
|
@ -81,8 +81,9 @@ void L::DrawMenuBar() {
|
|||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (BeginMenu("Display")) {
|
if (BeginMenu("Display")) {
|
||||||
|
auto& pp_settings = presenter->GetPPSettingsRef();
|
||||||
if (BeginMenu("Brightness")) {
|
if (BeginMenu("Brightness")) {
|
||||||
SliderFloat("Gamma", &presenter->GetGammaRef(), 0.1f, 2.0f);
|
SliderFloat("Gamma", &pp_settings.gamma, 0.1f, 2.0f);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -360,7 +360,7 @@ s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettin
|
|||||||
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
presenter->GetGammaRef() = settings->gamma;
|
presenter->GetPPSettingsRef().gamma = settings->gamma;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
255
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
Normal file
255
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "pp_pass.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "video_core/host_shaders/fs_tri_vert.h"
|
||||||
|
#include "video_core/host_shaders/post_process_frag.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_platform.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
|
|
||||||
|
#include <boost/container/static_vector.hpp>
|
||||||
|
|
||||||
|
namespace Vulkan::HostPasses {
|
||||||
|
|
||||||
|
void PostProcessingPass::Create(vk::Device device) {
|
||||||
|
static const std::array pp_shaders{
|
||||||
|
HostShaders::FS_TRI_VERT,
|
||||||
|
HostShaders::POST_PROCESS_FRAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci{
|
||||||
|
.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR,
|
||||||
|
.bindingCount = static_cast<u32>(bindings.size()),
|
||||||
|
.pBindings = bindings.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
desc_set_layout = Check<"create pp descriptor set layout">(
|
||||||
|
device.createDescriptorSetLayoutUnique(desc_layout_ci));
|
||||||
|
|
||||||
|
const vk::PushConstantRange push_constants{
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.offset = 0,
|
||||||
|
.size = sizeof(Settings),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto& vs_module = Compile(pp_shaders[0], vk::ShaderStageFlagBits::eVertex, device);
|
||||||
|
ASSERT(vs_module);
|
||||||
|
SetObjectName(device, vs_module, "fs_tri.vert");
|
||||||
|
|
||||||
|
const auto& fs_module = Compile(pp_shaders[1], vk::ShaderStageFlagBits::eFragment, device);
|
||||||
|
ASSERT(fs_module);
|
||||||
|
SetObjectName(device, fs_module, "post_process.frag");
|
||||||
|
|
||||||
|
const std::array shaders_ci{
|
||||||
|
vk::PipelineShaderStageCreateInfo{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||||
|
.module = vs_module,
|
||||||
|
.pName = "main",
|
||||||
|
},
|
||||||
|
vk::PipelineShaderStageCreateInfo{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.module = fs_module,
|
||||||
|
.pName = "main",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineLayoutCreateInfo layout_info{
|
||||||
|
.setLayoutCount = 1U,
|
||||||
|
.pSetLayouts = &*desc_set_layout,
|
||||||
|
.pushConstantRangeCount = 1,
|
||||||
|
.pPushConstantRanges = &push_constants,
|
||||||
|
};
|
||||||
|
|
||||||
|
pipeline_layout =
|
||||||
|
Check<"create pp pipeline layout">(device.createPipelineLayoutUnique(layout_info));
|
||||||
|
|
||||||
|
const std::array pp_color_formats{
|
||||||
|
vk::Format::eB8G8R8A8Unorm, // swapchain.GetSurfaceFormat().format,
|
||||||
|
};
|
||||||
|
const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci{
|
||||||
|
.colorAttachmentCount = pp_color_formats.size(),
|
||||||
|
.pColorAttachmentFormats = pp_color_formats.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineVertexInputStateCreateInfo vertex_input_info{
|
||||||
|
.vertexBindingDescriptionCount = 0u,
|
||||||
|
.vertexAttributeDescriptionCount = 0u,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineInputAssemblyStateCreateInfo input_assembly{
|
||||||
|
.topology = vk::PrimitiveTopology::eTriangleList,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::Viewport viewport{
|
||||||
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.width = 1.0f,
|
||||||
|
.height = 1.0f,
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::Rect2D scissor = {
|
||||||
|
.offset = {0, 0},
|
||||||
|
.extent = {1, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineViewportStateCreateInfo viewport_info{
|
||||||
|
.viewportCount = 1,
|
||||||
|
.pViewports = &viewport,
|
||||||
|
.scissorCount = 1,
|
||||||
|
.pScissors = &scissor,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineRasterizationStateCreateInfo raster_state{
|
||||||
|
.depthClampEnable = false,
|
||||||
|
.rasterizerDiscardEnable = false,
|
||||||
|
.polygonMode = vk::PolygonMode::eFill,
|
||||||
|
.cullMode = vk::CullModeFlagBits::eBack,
|
||||||
|
.frontFace = vk::FrontFace::eClockwise,
|
||||||
|
.depthBiasEnable = false,
|
||||||
|
.lineWidth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineMultisampleStateCreateInfo multisampling{
|
||||||
|
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::array attachments{
|
||||||
|
vk::PipelineColorBlendAttachmentState{
|
||||||
|
.blendEnable = false,
|
||||||
|
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||||
|
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineColorBlendStateCreateInfo color_blending{
|
||||||
|
.logicOpEnable = false,
|
||||||
|
.logicOp = vk::LogicOp::eCopy,
|
||||||
|
.attachmentCount = attachments.size(),
|
||||||
|
.pAttachments = attachments.data(),
|
||||||
|
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::array dynamic_states{
|
||||||
|
vk::DynamicState::eViewport,
|
||||||
|
vk::DynamicState::eScissor,
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::PipelineDynamicStateCreateInfo dynamic_info{
|
||||||
|
.dynamicStateCount = dynamic_states.size(),
|
||||||
|
.pDynamicStates = dynamic_states.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::GraphicsPipelineCreateInfo pipeline_info{
|
||||||
|
.pNext = &pipeline_rendering_ci,
|
||||||
|
.stageCount = shaders_ci.size(),
|
||||||
|
.pStages = shaders_ci.data(),
|
||||||
|
.pVertexInputState = &vertex_input_info,
|
||||||
|
.pInputAssemblyState = &input_assembly,
|
||||||
|
.pViewportState = &viewport_info,
|
||||||
|
.pRasterizationState = &raster_state,
|
||||||
|
.pMultisampleState = &multisampling,
|
||||||
|
.pColorBlendState = &color_blending,
|
||||||
|
.pDynamicState = &dynamic_info,
|
||||||
|
.layout = *pipeline_layout,
|
||||||
|
};
|
||||||
|
|
||||||
|
pipeline = Check<"create post process pipeline">(device.createGraphicsPipelineUnique(
|
||||||
|
/*pipeline_cache*/ {}, pipeline_info));
|
||||||
|
|
||||||
|
// Once pipeline is compiled, we don't need the shader module anymore
|
||||||
|
device.destroyShaderModule(vs_module);
|
||||||
|
device.destroyShaderModule(fs_module);
|
||||||
|
|
||||||
|
// Create sampler resource
|
||||||
|
const vk::SamplerCreateInfo sampler_ci{
|
||||||
|
.magFilter = vk::Filter::eLinear,
|
||||||
|
.minFilter = vk::Filter::eLinear,
|
||||||
|
.mipmapMode = vk::SamplerMipmapMode::eNearest,
|
||||||
|
.addressModeU = vk::SamplerAddressMode::eClampToEdge,
|
||||||
|
.addressModeV = vk::SamplerAddressMode::eClampToEdge,
|
||||||
|
};
|
||||||
|
sampler = Check<"create pp sampler">(device.createSamplerUnique(sampler_ci));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessingPass::Render(vk::CommandBuffer cmdbuf, vk::ImageView input,
|
||||||
|
vk::Extent2D input_size, Frame& frame, Settings settings) {
|
||||||
|
const std::array<vk::RenderingAttachmentInfo, 1> attachments{{
|
||||||
|
{
|
||||||
|
.imageView = frame.image_view,
|
||||||
|
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
},
|
||||||
|
}};
|
||||||
|
const vk::RenderingInfo rendering_info{
|
||||||
|
.renderArea{
|
||||||
|
.extent{
|
||||||
|
.width = frame.width,
|
||||||
|
.height = frame.height,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.layerCount = 1,
|
||||||
|
.colorAttachmentCount = attachments.size(),
|
||||||
|
.pColorAttachments = attachments.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::DescriptorImageInfo image_info{
|
||||||
|
.sampler = *sampler,
|
||||||
|
.imageView = input,
|
||||||
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::array set_writes{
|
||||||
|
vk::WriteDescriptorSet{
|
||||||
|
.dstSet = VK_NULL_HANDLE,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = &image_info,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, *pipeline);
|
||||||
|
|
||||||
|
const std::array viewports = {
|
||||||
|
vk::Viewport{
|
||||||
|
.width = static_cast<float>(frame.width),
|
||||||
|
.height = static_cast<float>(frame.height),
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
cmdbuf.setViewport(0, viewports);
|
||||||
|
cmdbuf.setScissor(0, vk::Rect2D{
|
||||||
|
.extent{
|
||||||
|
.width = frame.width,
|
||||||
|
.height = frame.height,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0, set_writes);
|
||||||
|
cmdbuf.pushConstants(*pipeline_layout, vk::ShaderStageFlagBits::eFragment, 0, sizeof(Settings),
|
||||||
|
&settings);
|
||||||
|
|
||||||
|
cmdbuf.beginRendering(rendering_info);
|
||||||
|
cmdbuf.draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.endRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vulkan::HostPasses
|
34
src/video_core/renderer_vulkan/host_passes/pp_pass.h
Normal file
34
src/video_core/renderer_vulkan/host_passes/pp_pass.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
class Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Vulkan::HostPasses {
|
||||||
|
|
||||||
|
class PostProcessingPass {
|
||||||
|
public:
|
||||||
|
struct Settings {
|
||||||
|
float gamma = 1.0f;
|
||||||
|
u32 hdr = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Create(vk::Device device);
|
||||||
|
|
||||||
|
void Render(vk::CommandBuffer cmdbuf, vk::ImageView input, vk::Extent2D input_size,
|
||||||
|
Frame& output, Settings settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
vk::UniquePipeline pipeline{};
|
||||||
|
vk::UniquePipelineLayout pipeline_layout{};
|
||||||
|
vk::UniqueDescriptorSetLayout desc_set_layout{};
|
||||||
|
vk::UniqueSampler sampler{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vulkan::HostPasses
|
@ -17,7 +17,6 @@
|
|||||||
#include "video_core/texture_cache/image.h"
|
#include "video_core/texture_cache/image.h"
|
||||||
|
|
||||||
#include "video_core/host_shaders/fs_tri_vert.h"
|
#include "video_core/host_shaders/fs_tri_vert.h"
|
||||||
#include "video_core/host_shaders/post_process_frag.h"
|
|
||||||
|
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
@ -107,181 +106,6 @@ static vk::Rect2D FitImage(s32 frame_width, s32 frame_height, s32 swapchain_widt
|
|||||||
dst_rect.offset.x, dst_rect.offset.y);
|
dst_rect.offset.x, dst_rect.offset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Presenter::CreatePostProcessPipeline() {
|
|
||||||
static const std::array pp_shaders{
|
|
||||||
HostShaders::FS_TRI_VERT,
|
|
||||||
HostShaders::POST_PROCESS_FRAG,
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{
|
|
||||||
{
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
|
||||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR,
|
|
||||||
.bindingCount = static_cast<u32>(bindings.size()),
|
|
||||||
.pBindings = bindings.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
pp_desc_set_layout = Check<"create pp descriptor set layout">(
|
|
||||||
instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci));
|
|
||||||
|
|
||||||
const vk::PushConstantRange push_constants = {
|
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
.offset = 0,
|
|
||||||
.size = sizeof(PostProcessSettings),
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto& vs_module =
|
|
||||||
Vulkan::Compile(pp_shaders[0], vk::ShaderStageFlagBits::eVertex, instance.GetDevice());
|
|
||||||
ASSERT(vs_module);
|
|
||||||
Vulkan::SetObjectName(instance.GetDevice(), vs_module, "fs_tri.vert");
|
|
||||||
|
|
||||||
const auto& fs_module =
|
|
||||||
Vulkan::Compile(pp_shaders[1], vk::ShaderStageFlagBits::eFragment, instance.GetDevice());
|
|
||||||
ASSERT(fs_module);
|
|
||||||
Vulkan::SetObjectName(instance.GetDevice(), fs_module, "post_process.frag");
|
|
||||||
|
|
||||||
const std::array shaders_ci{
|
|
||||||
vk::PipelineShaderStageCreateInfo{
|
|
||||||
.stage = vk::ShaderStageFlagBits::eVertex,
|
|
||||||
.module = vs_module,
|
|
||||||
.pName = "main",
|
|
||||||
},
|
|
||||||
vk::PipelineShaderStageCreateInfo{
|
|
||||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
.module = fs_module,
|
|
||||||
.pName = "main",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::DescriptorSetLayout set_layout = *pp_desc_set_layout;
|
|
||||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
|
||||||
.setLayoutCount = 1U,
|
|
||||||
.pSetLayouts = &set_layout,
|
|
||||||
.pushConstantRangeCount = 1,
|
|
||||||
.pPushConstantRanges = &push_constants,
|
|
||||||
};
|
|
||||||
|
|
||||||
pp_pipeline_layout = Check<"create pp pipeline layout">(
|
|
||||||
instance.GetDevice().createPipelineLayoutUnique(layout_info));
|
|
||||||
|
|
||||||
const std::array pp_color_formats{
|
|
||||||
vk::Format::eB8G8R8A8Unorm, // swapchain.GetSurfaceFormat().format,
|
|
||||||
};
|
|
||||||
const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci = {
|
|
||||||
.colorAttachmentCount = 1u,
|
|
||||||
.pColorAttachmentFormats = pp_color_formats.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
|
|
||||||
.vertexBindingDescriptionCount = 0u,
|
|
||||||
.vertexAttributeDescriptionCount = 0u,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
|
||||||
.topology = vk::PrimitiveTopology::eTriangleList,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::Viewport viewport = {
|
|
||||||
.x = 0.0f,
|
|
||||||
.y = 0.0f,
|
|
||||||
.width = 1.0f,
|
|
||||||
.height = 1.0f,
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::Rect2D scissor = {
|
|
||||||
.offset = {0, 0},
|
|
||||||
.extent = {1, 1},
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
|
||||||
.viewportCount = 1,
|
|
||||||
.pViewports = &viewport,
|
|
||||||
.scissorCount = 1,
|
|
||||||
.pScissors = &scissor,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
|
||||||
.depthClampEnable = false,
|
|
||||||
.rasterizerDiscardEnable = false,
|
|
||||||
.polygonMode = vk::PolygonMode::eFill,
|
|
||||||
.cullMode = vk::CullModeFlagBits::eBack,
|
|
||||||
.frontFace = vk::FrontFace::eClockwise,
|
|
||||||
.depthBiasEnable = false,
|
|
||||||
.lineWidth = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array attachments{
|
|
||||||
vk::PipelineColorBlendAttachmentState{
|
|
||||||
.blendEnable = false,
|
|
||||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
|
||||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
|
||||||
.logicOpEnable = false,
|
|
||||||
.logicOp = vk::LogicOp::eCopy,
|
|
||||||
.attachmentCount = attachments.size(),
|
|
||||||
.pAttachments = attachments.data(),
|
|
||||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array dynamic_states = {
|
|
||||||
vk::DynamicState::eViewport,
|
|
||||||
vk::DynamicState::eScissor,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
|
||||||
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
|
|
||||||
.pDynamicStates = dynamic_states.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
|
||||||
.pNext = &pipeline_rendering_ci,
|
|
||||||
.stageCount = static_cast<u32>(shaders_ci.size()),
|
|
||||||
.pStages = shaders_ci.data(),
|
|
||||||
.pVertexInputState = &vertex_input_info,
|
|
||||||
.pInputAssemblyState = &input_assembly,
|
|
||||||
.pViewportState = &viewport_info,
|
|
||||||
.pRasterizationState = &raster_state,
|
|
||||||
.pMultisampleState = &multisampling,
|
|
||||||
.pColorBlendState = &color_blending,
|
|
||||||
.pDynamicState = &dynamic_info,
|
|
||||||
.layout = *pp_pipeline_layout,
|
|
||||||
};
|
|
||||||
|
|
||||||
pp_pipeline =
|
|
||||||
Check<"create post process pipeline">(instance.GetDevice().createGraphicsPipelineUnique(
|
|
||||||
/*pipeline_cache*/ {}, pipeline_info));
|
|
||||||
|
|
||||||
// Once pipeline is compiled, we don't need the shader module anymore
|
|
||||||
instance.GetDevice().destroyShaderModule(vs_module);
|
|
||||||
instance.GetDevice().destroyShaderModule(fs_module);
|
|
||||||
|
|
||||||
// Create sampler resource
|
|
||||||
const vk::SamplerCreateInfo sampler_ci = {
|
|
||||||
.magFilter = vk::Filter::eLinear,
|
|
||||||
.minFilter = vk::Filter::eLinear,
|
|
||||||
.mipmapMode = vk::SamplerMipmapMode::eNearest,
|
|
||||||
.addressModeU = vk::SamplerAddressMode::eClampToEdge,
|
|
||||||
.addressModeV = vk::SamplerAddressMode::eClampToEdge,
|
|
||||||
};
|
|
||||||
pp_sampler = Check<"create pp sampler">(instance.GetDevice().createSamplerUnique(sampler_ci));
|
|
||||||
}
|
|
||||||
|
|
||||||
Presenter::Presenter(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
|
Presenter::Presenter(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
|
||||||
: window{window_}, liverpool{liverpool_},
|
: window{window_}, liverpool{liverpool_},
|
||||||
instance{window, Config::getGpuId(), Config::vkValidationEnabled(),
|
instance{window, Config::getGpuId(), Config::vkValidationEnabled(),
|
||||||
@ -303,7 +127,7 @@ Presenter::Presenter(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_
|
|||||||
free_queue.push(&frame);
|
free_queue.push(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatePostProcessPipeline();
|
pp_pass.Create(device);
|
||||||
|
|
||||||
ImGui::Layer::AddLayer(Common::Singleton<Core::Devtools::Layer>::Instance());
|
ImGui::Layer::AddLayer(Common::Singleton<Core::Devtools::Layer>::Instance());
|
||||||
}
|
}
|
||||||
@ -365,6 +189,7 @@ void Presenter::RecreateFrame(Frame* frame, u32 width, u32 height) {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
frame->image = vk::Image{unsafe_image};
|
frame->image = vk::Image{unsafe_image};
|
||||||
|
SetObjectName(device, frame->image, "Frame image");
|
||||||
|
|
||||||
const vk::ImageViewCreateInfo view_info = {
|
const vk::ImageViewCreateInfo view_info = {
|
||||||
.image = frame->image,
|
.image = frame->image,
|
||||||
@ -592,33 +417,12 @@ Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop)
|
|||||||
.pImageMemoryBarriers = &pre_barrier,
|
.pImageMemoryBarriers = &pre_barrier,
|
||||||
});
|
});
|
||||||
|
|
||||||
const std::array attachments = {vk::RenderingAttachmentInfo{
|
|
||||||
.imageView = frame->image_view,
|
|
||||||
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
||||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
|
||||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
|
||||||
}};
|
|
||||||
const vk::RenderingInfo rendering_info{
|
|
||||||
.renderArea =
|
|
||||||
vk::Rect2D{
|
|
||||||
.offset = {0, 0},
|
|
||||||
.extent = {frame->width, frame->height},
|
|
||||||
},
|
|
||||||
.layerCount = 1,
|
|
||||||
.colorAttachmentCount = attachments.size(),
|
|
||||||
.pColorAttachments = attachments.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (image_id != VideoCore::NULL_IMAGE_ID) {
|
if (image_id != VideoCore::NULL_IMAGE_ID) {
|
||||||
auto& image = texture_cache.GetImage(image_id);
|
auto& image = texture_cache.GetImage(image_id);
|
||||||
|
vk::Extent2D image_size = {image.info.size.width, image.info.size.height};
|
||||||
image.Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {},
|
image.Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {},
|
||||||
cmdbuf);
|
cmdbuf);
|
||||||
|
|
||||||
static vk::DescriptorImageInfo image_info{
|
|
||||||
.sampler = *pp_sampler,
|
|
||||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
|
||||||
};
|
|
||||||
|
|
||||||
VideoCore::ImageViewInfo info{};
|
VideoCore::ImageViewInfo info{};
|
||||||
info.format = image.info.pixel_format;
|
info.format = image.info.pixel_format;
|
||||||
// Exclude alpha from output frame to avoid blending with UI.
|
// Exclude alpha from output frame to avoid blending with UI.
|
||||||
@ -628,52 +432,32 @@ Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop)
|
|||||||
.b = vk::ComponentSwizzle::eIdentity,
|
.b = vk::ComponentSwizzle::eIdentity,
|
||||||
.a = vk::ComponentSwizzle::eOne,
|
.a = vk::ComponentSwizzle::eOne,
|
||||||
};
|
};
|
||||||
|
vk::ImageView imageView;
|
||||||
if (auto view = image.FindView(info)) {
|
if (auto view = image.FindView(info)) {
|
||||||
image_info.imageView = *texture_cache.GetImageView(view).image_view;
|
imageView = *texture_cache.GetImageView(view).image_view;
|
||||||
} else {
|
} else {
|
||||||
image_info.imageView = *texture_cache.RegisterImageView(image_id, info).image_view;
|
imageView = *texture_cache.RegisterImageView(image_id, info).image_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::array set_writes{
|
pp_pass.Render(cmdbuf, imageView, image_size, *frame, pp_settings);
|
||||||
vk::WriteDescriptorSet{
|
|
||||||
.dstSet = VK_NULL_HANDLE,
|
|
||||||
.dstBinding = 0,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.pImageInfo = &image_info,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, *pp_pipeline);
|
|
||||||
|
|
||||||
const auto& dst_rect =
|
|
||||||
FitImage(image.info.size.width, image.info.size.height, frame->width, frame->height);
|
|
||||||
|
|
||||||
const std::array viewports = {
|
|
||||||
vk::Viewport{
|
|
||||||
.x = 1.0f * dst_rect.offset.x,
|
|
||||||
.y = 1.0f * dst_rect.offset.y,
|
|
||||||
.width = 1.0f * dst_rect.extent.width,
|
|
||||||
.height = 1.0f * dst_rect.extent.height,
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
cmdbuf.setViewport(0, viewports);
|
|
||||||
cmdbuf.setScissor(0, {dst_rect});
|
|
||||||
|
|
||||||
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pp_pipeline_layout, 0,
|
|
||||||
set_writes);
|
|
||||||
cmdbuf.pushConstants(*pp_pipeline_layout, vk::ShaderStageFlagBits::eFragment, 0,
|
|
||||||
sizeof(PostProcessSettings), &pp_settings);
|
|
||||||
|
|
||||||
cmdbuf.beginRendering(rendering_info);
|
|
||||||
cmdbuf.draw(3, 1, 0, 0);
|
|
||||||
cmdbuf.endRendering();
|
|
||||||
} else {
|
} else {
|
||||||
// Fix display of garbage images on startup on some drivers
|
// Fix display of garbage images on startup on some drivers
|
||||||
|
const std::array<vk::RenderingAttachmentInfo, 1> attachments = {{
|
||||||
|
{
|
||||||
|
.imageView = frame->image_view,
|
||||||
|
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
},
|
||||||
|
}};
|
||||||
|
const vk::RenderingInfo rendering_info{
|
||||||
|
.renderArea{
|
||||||
|
.extent{frame->width, frame->height},
|
||||||
|
},
|
||||||
|
.layerCount = 1,
|
||||||
|
.colorAttachmentCount = attachments.size(),
|
||||||
|
.pColorAttachments = attachments.data(),
|
||||||
|
};
|
||||||
cmdbuf.beginRendering(rendering_info);
|
cmdbuf.beginRendering(rendering_info);
|
||||||
cmdbuf.endRendering();
|
cmdbuf.endRendering();
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "imgui/imgui_config.h"
|
#include "imgui/imgui_config.h"
|
||||||
#include "video_core/amdgpu/liverpool.h"
|
#include "video_core/amdgpu/liverpool.h"
|
||||||
|
#include "video_core/renderer_vulkan/host_passes/pp_pass.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
@ -45,17 +46,12 @@ enum SchedulerType {
|
|||||||
class Rasterizer;
|
class Rasterizer;
|
||||||
|
|
||||||
class Presenter {
|
class Presenter {
|
||||||
struct PostProcessSettings {
|
|
||||||
float gamma = 1.0f;
|
|
||||||
u32 hdr = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Presenter(Frontend::WindowSDL& window, AmdGpu::Liverpool* liverpool);
|
Presenter(Frontend::WindowSDL& window, AmdGpu::Liverpool* liverpool);
|
||||||
~Presenter();
|
~Presenter();
|
||||||
|
|
||||||
float& GetGammaRef() {
|
HostPasses::PostProcessingPass::Settings& GetPPSettingsRef() {
|
||||||
return pp_settings.gamma;
|
return pp_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frontend::WindowSDL& GetWindow() const {
|
Frontend::WindowSDL& GetWindow() const {
|
||||||
@ -117,16 +113,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreatePostProcessPipeline();
|
|
||||||
Frame* PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop = true);
|
Frame* PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop = true);
|
||||||
Frame* GetRenderFrame();
|
Frame* GetRenderFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PostProcessSettings pp_settings{};
|
HostPasses::PostProcessingPass::Settings pp_settings{};
|
||||||
vk::UniquePipeline pp_pipeline{};
|
HostPasses::PostProcessingPass pp_pass;
|
||||||
vk::UniquePipelineLayout pp_pipeline_layout{};
|
|
||||||
vk::UniqueDescriptorSetLayout pp_desc_set_layout{};
|
|
||||||
vk::UniqueSampler pp_sampler{};
|
|
||||||
Frontend::WindowSDL& window;
|
Frontend::WindowSDL& window;
|
||||||
AmdGpu::Liverpool* liverpool;
|
AmdGpu::Liverpool* liverpool;
|
||||||
Instance instance;
|
Instance instance;
|
||||||
|
Loading…
Reference in New Issue
Block a user