mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-10 21:40:43 +00:00
vk: Enable use of input attachments
This commit is contained in:
parent
b8b5b93b63
commit
f85881c18c
@ -10,10 +10,26 @@ namespace vk
|
||||
{
|
||||
std::unordered_map<u64, std::vector<std::unique_ptr<vk::framebuffer_holder>>> g_framebuffers_cache;
|
||||
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, const std::vector<vk::image*>& image_list)
|
||||
union framebuffer_storage_key
|
||||
{
|
||||
u64 key = u64(width) | (u64(height) << 16);
|
||||
auto &queue = g_framebuffers_cache[key];
|
||||
u64 encoded;
|
||||
|
||||
struct
|
||||
{
|
||||
u64 width : 16; // Width of FBO
|
||||
u64 height : 16; // Height of FBO
|
||||
u64 ia_ref : 1; // Input attachment references?
|
||||
};
|
||||
|
||||
framebuffer_storage_key(u16 width_, u16 height_, VkBool32 has_input_attachments)
|
||||
: width(width_), height(height_), ia_ref(has_input_attachments)
|
||||
{}
|
||||
};
|
||||
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector<vk::image*>& image_list)
|
||||
{
|
||||
framebuffer_storage_key key(width, height, has_input_attachments);
|
||||
auto &queue = g_framebuffers_cache[key.encoded];
|
||||
|
||||
for (auto &fbo : queue)
|
||||
{
|
||||
@ -39,10 +55,10 @@ namespace vk
|
||||
return ret;
|
||||
}
|
||||
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, VkFormat format, VkImage attachment)
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment)
|
||||
{
|
||||
u64 key = u64(width) | (u64(height) << 16);
|
||||
auto &queue = g_framebuffers_cache[key];
|
||||
framebuffer_storage_key key(width, height, has_input_attachments);
|
||||
auto &queue = g_framebuffers_cache[key.encoded];
|
||||
|
||||
for (const auto &e : queue)
|
||||
{
|
||||
|
@ -9,8 +9,8 @@ namespace vk
|
||||
using framebuffer::framebuffer;
|
||||
};
|
||||
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, const std::vector<vk::image*>& image_list);
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, VkFormat format, VkImage attachment);
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector<vk::image*>& image_list);
|
||||
vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment);
|
||||
|
||||
void remove_unused_framebuffers();
|
||||
void clear_framebuffer_cache();
|
||||
|
@ -1289,7 +1289,8 @@ void VKGSRender::clear_surface(u32 mask)
|
||||
if (!renderpass)
|
||||
{
|
||||
std::vector<vk::image*> surfaces = { rtt };
|
||||
const auto key = vk::get_renderpass_key(surfaces);
|
||||
std::vector<u8> input_attachments = { 0 };
|
||||
const auto key = vk::get_renderpass_key(surfaces, input_attachments);
|
||||
renderpass = vk::get_renderpass(*m_device, key);
|
||||
}
|
||||
|
||||
@ -2277,7 +2278,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||
m_draw_fbo->release();
|
||||
}
|
||||
|
||||
m_draw_fbo = vk::get_framebuffer(*m_device, fbo_width, fbo_height, m_cached_renderpass, m_fbo_images);
|
||||
m_draw_fbo = vk::get_framebuffer(*m_device, fbo_width, fbo_height, VK_FALSE, m_cached_renderpass, m_fbo_images);
|
||||
m_draw_fbo->add_ref();
|
||||
|
||||
set_viewport();
|
||||
|
@ -60,16 +60,26 @@ namespace vk
|
||||
|
||||
void overlay_pass::init_descriptors()
|
||||
{
|
||||
VkDescriptorPoolSize descriptor_pool_sizes[2] =
|
||||
std::vector<VkDescriptorPoolSize> descriptor_pool_sizes =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_OVERLAY_MAX_DRAW_CALLS * m_num_usable_samplers },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_OVERLAY_MAX_DRAW_CALLS },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_OVERLAY_MAX_DRAW_CALLS }
|
||||
};
|
||||
|
||||
// Reserve descriptor pools
|
||||
m_descriptor_pool.create(*m_device, descriptor_pool_sizes, 2, VK_OVERLAY_MAX_DRAW_CALLS, 2);
|
||||
if (m_num_usable_samplers)
|
||||
{
|
||||
descriptor_pool_sizes.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_OVERLAY_MAX_DRAW_CALLS * m_num_usable_samplers });
|
||||
}
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings(1 + m_num_usable_samplers);
|
||||
if (m_num_input_attachments)
|
||||
{
|
||||
descriptor_pool_sizes.push_back({ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_OVERLAY_MAX_DRAW_CALLS * m_num_input_attachments });
|
||||
}
|
||||
|
||||
// Reserve descriptor pools
|
||||
m_descriptor_pool.create(*m_device, descriptor_pool_sizes.data(), ::size32(descriptor_pool_sizes), VK_OVERLAY_MAX_DRAW_CALLS, 2);
|
||||
|
||||
const auto num_bindings = 1 + m_num_usable_samplers + m_num_input_attachments;
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings(num_bindings);
|
||||
|
||||
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[0].descriptorCount = 1;
|
||||
@ -77,19 +87,31 @@ namespace vk
|
||||
bindings[0].binding = 0;
|
||||
bindings[0].pImmutableSamplers = nullptr;
|
||||
|
||||
for (u32 n = 1; n <= m_num_usable_samplers; ++n)
|
||||
u32 descriptor_index = 1;
|
||||
for (u32 n = 0; n < m_num_usable_samplers; ++n, ++descriptor_index)
|
||||
{
|
||||
bindings[n].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[n].descriptorCount = 1;
|
||||
bindings[n].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[n].binding = n;
|
||||
bindings[n].pImmutableSamplers = nullptr;
|
||||
bindings[descriptor_index].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[descriptor_index].descriptorCount = 1;
|
||||
bindings[descriptor_index].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[descriptor_index].binding = descriptor_index;
|
||||
bindings[descriptor_index].pImmutableSamplers = nullptr;
|
||||
}
|
||||
|
||||
for (u32 n = 0; n < m_num_input_attachments; ++n, ++descriptor_index)
|
||||
{
|
||||
bindings[descriptor_index].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
bindings[descriptor_index].descriptorCount = 1;
|
||||
bindings[descriptor_index].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[descriptor_index].binding = descriptor_index;
|
||||
bindings[descriptor_index].pImmutableSamplers = nullptr;
|
||||
}
|
||||
|
||||
ensure(descriptor_index == num_bindings);
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo infos = {};
|
||||
infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
infos.pBindings = bindings.data();
|
||||
infos.bindingCount = 1 + m_num_usable_samplers;
|
||||
infos.bindingCount = ::size32(bindings);
|
||||
|
||||
CHECK_RESULT(vkCreateDescriptorSetLayout(*m_device, &infos, nullptr, &m_descriptor_layout));
|
||||
|
||||
@ -119,9 +141,15 @@ namespace vk
|
||||
std::vector<vk::glsl::program_input> fs_inputs;
|
||||
fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_uniform_buffer,{},{}, 0, "static_data" });
|
||||
|
||||
for (u32 n = 1; n <= m_num_usable_samplers; ++n)
|
||||
u32 binding = 1;
|
||||
for (u32 n = 0; n < m_num_usable_samplers; ++n, ++binding)
|
||||
{
|
||||
fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, n, "fs" + std::to_string(n-1) });
|
||||
fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, binding, "fs" + std::to_string(n) });
|
||||
}
|
||||
|
||||
for (u32 n = 0; n < m_num_input_attachments; ++n, ++binding)
|
||||
{
|
||||
fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, binding, "sp" + std::to_string(n) });
|
||||
}
|
||||
|
||||
return fs_inputs;
|
||||
@ -222,7 +250,7 @@ namespace vk
|
||||
CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, &m_descriptor_set));
|
||||
m_used_descriptors++;
|
||||
|
||||
if (!m_sampler)
|
||||
if (!m_sampler && !src.empty())
|
||||
{
|
||||
m_sampler = std::make_unique<vk::sampler>(*m_device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
@ -290,7 +318,7 @@ namespace vk
|
||||
vk::framebuffer* overlay_pass::get_framebuffer(vk::image* target, VkRenderPass render_pass)
|
||||
{
|
||||
VkDevice dev = (*vk::get_current_renderer());
|
||||
return vk::get_framebuffer(dev, target->width(), target->height(), render_pass, { target });
|
||||
return vk::get_framebuffer(dev, target->width(), target->height(), m_num_input_attachments > 0, render_pass, { target });
|
||||
}
|
||||
|
||||
void overlay_pass::emit_geometry(vk::command_buffer& cmd)
|
||||
@ -778,15 +806,12 @@ namespace vk
|
||||
"#version 450\n"
|
||||
"#extension GL_ARB_separate_shader_objects : enable\n"
|
||||
"layout(push_constant) uniform static_data{ vec4 regs[2]; };\n"
|
||||
"layout(location=0) out vec2 tc0;\n"
|
||||
"layout(location=1) out vec4 color;\n"
|
||||
"layout(location=2) out vec4 mask;\n"
|
||||
"layout(location=0) out vec4 color;\n"
|
||||
"layout(location=1) out vec4 mask;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n"
|
||||
" vec2 coords[] = {vec2(0., 0.), vec2(1., 0.), vec2(0., 1.), vec2(1., 1.)};\n"
|
||||
" tc0 = coords[gl_VertexIndex % 4];\n"
|
||||
" color = regs[0];\n"
|
||||
" mask = regs[1];\n"
|
||||
" gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n"
|
||||
@ -795,18 +820,23 @@ namespace vk
|
||||
fs_src =
|
||||
"#version 420\n"
|
||||
"#extension GL_ARB_separate_shader_objects : enable\n"
|
||||
"layout(set=0, binding=1) uniform sampler2D fs0;\n"
|
||||
"layout(location=0) in vec2 tc0;\n"
|
||||
"layout(location=1) in vec4 color;\n"
|
||||
"layout(location=2) in vec4 mask;\n"
|
||||
"layout(input_attachment_index=0, binding=1) uniform subpassInput sp0;\n"
|
||||
"layout(location=0) in vec4 color;\n"
|
||||
"layout(location=1) in vec4 mask;\n"
|
||||
"layout(location=0) out vec4 out_color;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 original_color = texture(fs0, tc0);\n"
|
||||
" vec4 original_color = subpassLoad(sp0);\n"
|
||||
" out_color = mix(original_color, color, bvec4(mask));\n"
|
||||
"}\n";
|
||||
|
||||
// Disable samplers
|
||||
m_num_usable_samplers = 0;
|
||||
|
||||
// Enable subpass attachment 0
|
||||
m_num_input_attachments = 1;
|
||||
|
||||
renderpass_config.set_depth_mask(false);
|
||||
renderpass_config.set_color_mask(0, true, true, true, true);
|
||||
renderpass_config.set_attachment_count(1);
|
||||
@ -822,7 +852,7 @@ namespace vk
|
||||
return { constant };
|
||||
}
|
||||
|
||||
void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/)
|
||||
void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* program)
|
||||
{
|
||||
f32 data[8];
|
||||
data[0] = clear_color.r;
|
||||
@ -835,6 +865,9 @@ namespace vk
|
||||
data[7] = colormask.a;
|
||||
|
||||
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 32, data);
|
||||
|
||||
// Bind subpass attachment 0
|
||||
program->bind_uniform(input_attachment_info, "sp0", VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_descriptor_set);
|
||||
}
|
||||
|
||||
void attachment_clear_pass::set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h)
|
||||
@ -872,13 +905,14 @@ namespace vk
|
||||
void attachment_clear_pass::run(vk::command_buffer& cmd, vk::render_target* target, VkRect2D rect, VkRenderPass render_pass)
|
||||
{
|
||||
region = rect;
|
||||
input_attachment_info = { VK_NULL_HANDLE, target->get_view(0xAAE4, rsx::default_remap_vector)->value, target->current_layout };
|
||||
|
||||
target->read_barrier(cmd);
|
||||
|
||||
// Coverage sampling disabled, but actually report correct number of samples
|
||||
renderpass_config.set_multisample_state(target->samples(), 0xFFFF, false, false, false);
|
||||
|
||||
overlay_pass::run(cmd, { 0, 0, target->width(), target->height() }, target,
|
||||
target->get_view(0xAAE4, rsx::default_remap_vector), render_pass);
|
||||
overlay_pass::run(cmd, { 0, 0, target->width(), target->height() }, target, std::vector<vk::image_view*>{}, render_pass);
|
||||
}
|
||||
|
||||
stencil_clear_pass::stencil_clear_pass()
|
||||
|
@ -49,6 +49,7 @@ namespace vk
|
||||
|
||||
VkFilter m_sampler_filter = VK_FILTER_LINEAR;
|
||||
u32 m_num_usable_samplers = 1;
|
||||
u32 m_num_input_attachments = 0;
|
||||
|
||||
std::unordered_map<u64, std::unique_ptr<vk::glsl::program>> m_program_cache;
|
||||
std::unique_ptr<vk::sampler> m_sampler;
|
||||
@ -175,12 +176,13 @@ namespace vk
|
||||
color4f clear_color = { 0.f, 0.f, 0.f, 0.f };
|
||||
color4f colormask = { 1.f, 1.f, 1.f, 1.f };
|
||||
VkRect2D region = {};
|
||||
VkDescriptorImageInfo input_attachment_info = {};
|
||||
|
||||
attachment_clear_pass();
|
||||
|
||||
std::vector<VkPushConstantRange> get_push_constants() override;
|
||||
|
||||
void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/) override;
|
||||
void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* program) override;
|
||||
|
||||
void set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h) override;
|
||||
|
||||
|
@ -637,7 +637,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
single_target_pass = vk::get_renderpass(*m_device, key);
|
||||
ensure(single_target_pass != VK_NULL_HANDLE);
|
||||
|
||||
direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, single_target_pass, m_swapchain->get_surface_format(), target_image);
|
||||
direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, VK_FALSE, single_target_pass, m_swapchain->get_surface_format(), target_image);
|
||||
direct_fbo->add_ref();
|
||||
image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
@ -715,7 +715,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
single_target_pass = vk::get_renderpass(*m_device, key);
|
||||
ensure(single_target_pass != VK_NULL_HANDLE);
|
||||
|
||||
direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, single_target_pass, m_swapchain->get_surface_format(), target_image);
|
||||
direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, VK_FALSE, single_target_pass, m_swapchain->get_surface_format(), target_image);
|
||||
}
|
||||
|
||||
direct_fbo->add_ref();
|
||||
|
@ -19,77 +19,187 @@ namespace vk
|
||||
shared_mutex g_renderpass_cache_mutex;
|
||||
std::unordered_map<u64, VkRenderPass> g_renderpass_cache;
|
||||
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images)
|
||||
// Key structure
|
||||
// 0-7 color_format
|
||||
// 8-15 depth_format
|
||||
// 16-21 sample_counts
|
||||
// 22-36 current layouts
|
||||
// 37-41 input attachments
|
||||
union renderpass_key_blob
|
||||
{
|
||||
// Key structure
|
||||
// 0-8 color_format
|
||||
// 8-16 depth_format
|
||||
// 16-21 sample_counts
|
||||
// 21-37 current layouts
|
||||
u64 key = 0;
|
||||
u64 layout_offset = 22;
|
||||
for (const auto &surface : images)
|
||||
private:
|
||||
// Internal utils
|
||||
static u64 encode_layout(VkImageLayout layout)
|
||||
{
|
||||
const auto format_code = u64(surface->format()) & 0xFF;
|
||||
switch (format_code)
|
||||
switch (layout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
return static_cast<u64>(layout);
|
||||
default:
|
||||
fmt::throw_exception("Unsupported layout 0x%llx here", static_cast<usz>(layout));
|
||||
}
|
||||
}
|
||||
|
||||
static VkImageLayout decode_layout(u64 encoded)
|
||||
{
|
||||
switch (encoded)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return static_cast<VkImageLayout>(encoded);
|
||||
default:
|
||||
fmt::throw_exception("Unsupported layout encoding 0x%llx here", encoded);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
u64 encoded;
|
||||
|
||||
struct
|
||||
{
|
||||
u64 color_format : 8;
|
||||
u64 depth_format : 8;
|
||||
u64 sample_count : 6;
|
||||
u64 layout_blob : 15;
|
||||
u64 input_attachments_mask : 5;
|
||||
};
|
||||
|
||||
renderpass_key_blob(u64 encoded_) : encoded(encoded_)
|
||||
{}
|
||||
|
||||
// Encoders
|
||||
inline void set_layout(u32 index, VkImageLayout layout)
|
||||
{
|
||||
switch (layout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
layout_blob |= encode_layout(layout) << (index * 3);
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported image layout 0x%x", static_cast<u32>(layout));
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_input_attachment(u32 index)
|
||||
{
|
||||
input_attachments_mask |= (1ull << index);
|
||||
}
|
||||
|
||||
inline void set_format(VkFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
key |= (format_code << 8);
|
||||
depth_format = static_cast<u64>(format);
|
||||
break;
|
||||
default:
|
||||
key |= format_code;
|
||||
color_format = static_cast<u64>(format);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (const auto layout = surface->current_layout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
key |= (u64(layout) << layout_offset);
|
||||
layout_offset += 3;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported image layout 0x%x", static_cast<u32>(layout));
|
||||
}
|
||||
}
|
||||
|
||||
key |= u64(images[0]->samples()) << 16;
|
||||
return key;
|
||||
// Decoders
|
||||
inline VkSampleCountFlagBits get_sample_count() const
|
||||
{
|
||||
return static_cast<VkSampleCountFlagBits>(sample_count);
|
||||
}
|
||||
|
||||
inline VkFormat get_color_format() const
|
||||
{
|
||||
return static_cast<VkFormat>(color_format);
|
||||
}
|
||||
|
||||
inline VkFormat get_depth_format() const
|
||||
{
|
||||
return static_cast<VkFormat>(depth_format);
|
||||
}
|
||||
|
||||
std::vector<VkAttachmentReference> get_input_attachments() const
|
||||
{
|
||||
if (input_attachments_mask == 0) [[likely]]
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<VkAttachmentReference> result;
|
||||
for (u32 i = 0; i < 5; ++i)
|
||||
{
|
||||
if (input_attachments_mask & (1ull << i))
|
||||
{
|
||||
const auto layout = decode_layout((layout_blob >> (i * 3)) & 0x7);
|
||||
result.push_back({i, layout});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<VkImageLayout> get_image_layouts() const
|
||||
{
|
||||
std::vector<VkImageLayout> result;
|
||||
|
||||
for (u32 i = 0, layout_offset = 0; i < 5; ++i, layout_offset += 3)
|
||||
{
|
||||
if (const auto layout = VkImageLayout((layout_blob >> layout_offset) & 0x7))
|
||||
{
|
||||
result.push_back(layout);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images, const std::vector<u8>& input_attachment_ids)
|
||||
{
|
||||
renderpass_key_blob key(0);
|
||||
|
||||
for (u32 i = 0; i < ::size32(images); ++i)
|
||||
{
|
||||
const auto& surface = images[i];
|
||||
key.set_format(surface->format());
|
||||
key.set_layout(i, surface->current_layout);
|
||||
}
|
||||
|
||||
for (const auto& ref_id : input_attachment_ids)
|
||||
{
|
||||
key.set_input_attachment(ref_id);
|
||||
}
|
||||
|
||||
key.sample_count = images[0]->samples();
|
||||
return key.encoded;
|
||||
}
|
||||
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images, u64 previous_key)
|
||||
{
|
||||
// Partial update; assumes compatible renderpass keys
|
||||
const u64 layout_mask = (0x7FFFull << 22);
|
||||
renderpass_key_blob key(previous_key);
|
||||
key.layout_blob = 0;
|
||||
|
||||
u64 key = previous_key & ~layout_mask;
|
||||
u64 layout_offset = 22;
|
||||
|
||||
for (const auto &surface : images)
|
||||
for (u32 i = 0; i < ::size32(images); ++i)
|
||||
{
|
||||
switch (const auto layout = surface->current_layout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
key |= (u64(layout) << layout_offset);
|
||||
layout_offset += 3;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported image layout 0x%x", static_cast<u32>(layout));
|
||||
}
|
||||
key.set_layout(i, images[i]->current_layout);
|
||||
}
|
||||
|
||||
return key;
|
||||
return key.encoded;
|
||||
}
|
||||
|
||||
u64 get_renderpass_key(VkFormat surface_format)
|
||||
{
|
||||
u64 key = (1ull << 16);
|
||||
renderpass_key_blob key(0);
|
||||
key.sample_count = 1;
|
||||
|
||||
switch (surface_format)
|
||||
{
|
||||
@ -97,16 +207,16 @@ namespace vk
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
key |= (u64(surface_format) << 8);
|
||||
key |= (u64(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) << 22);
|
||||
key.depth_format = static_cast<u64>(surface_format);
|
||||
key.layout_blob = static_cast<u64>(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
break;
|
||||
default:
|
||||
key |= u64(surface_format);
|
||||
key |= (u64(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) << 22);
|
||||
key.color_format = static_cast<u64>(surface_format);
|
||||
key.layout_blob = static_cast<u64>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
return key;
|
||||
return key.encoded;
|
||||
}
|
||||
|
||||
VkRenderPass get_renderpass(VkDevice dev, u64 renderpass_key)
|
||||
@ -132,38 +242,24 @@ namespace vk
|
||||
}
|
||||
|
||||
// Decode
|
||||
VkSampleCountFlagBits samples = VkSampleCountFlagBits((renderpass_key >> 16) & 0xF);
|
||||
renderpass_key_blob key(renderpass_key);
|
||||
VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(key.sample_count);
|
||||
std::vector<VkImageLayout> rtv_layouts;
|
||||
VkImageLayout dsv_layout;
|
||||
|
||||
u64 layout_offset = 22;
|
||||
for (int n = 0; n < 5; ++n)
|
||||
{
|
||||
const VkImageLayout layout = VkImageLayout((renderpass_key >> layout_offset) & 0x7);
|
||||
layout_offset += 3;
|
||||
VkFormat color_format = static_cast<VkFormat>(key.color_format);
|
||||
VkFormat depth_format = static_cast<VkFormat>(key.depth_format);
|
||||
|
||||
if (layout)
|
||||
{
|
||||
rtv_layouts.push_back(layout);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VkFormat color_format = VkFormat(renderpass_key & 0xFF);
|
||||
VkFormat depth_format = VkFormat((renderpass_key >> 8) & 0xFF);
|
||||
std::vector<VkAttachmentDescription> attachments = {};
|
||||
std::vector<VkAttachmentReference> attachment_references;
|
||||
|
||||
rtv_layouts = key.get_image_layouts();
|
||||
if (depth_format)
|
||||
{
|
||||
dsv_layout = rtv_layouts.back();
|
||||
rtv_layouts.pop_back();
|
||||
}
|
||||
|
||||
std::vector<VkAttachmentDescription> attachments = {};
|
||||
std::vector<VkAttachmentReference> attachment_references;
|
||||
|
||||
u32 attachment_count = 0;
|
||||
for (const auto &layout : rtv_layouts)
|
||||
{
|
||||
@ -203,9 +299,16 @@ namespace vk
|
||||
subpass.pColorAttachments = attachment_count? attachment_references.data() : nullptr;
|
||||
subpass.pDepthStencilAttachment = depth_format? &attachment_references.back() : nullptr;
|
||||
|
||||
const auto input_attachments = key.get_input_attachments();
|
||||
if (!input_attachments.empty())
|
||||
{
|
||||
subpass.inputAttachmentCount = ::size32(input_attachments);
|
||||
subpass.pInputAttachments = input_attachments.data();
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo rp_info = {};
|
||||
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
rp_info.attachmentCount = static_cast<u32>(attachments.size());
|
||||
rp_info.attachmentCount = ::size32(attachments);
|
||||
rp_info.pAttachments = attachments.data();
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
|
@ -7,7 +7,7 @@ namespace vk
|
||||
{
|
||||
class image;
|
||||
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images);
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images, const std::vector<u8>& input_attachment_ids = {});
|
||||
u64 get_renderpass_key(const std::vector<vk::image*>& images, u64 previous_key);
|
||||
u64 get_renderpass_key(VkFormat surface_format);
|
||||
VkRenderPass get_renderpass(VkDevice dev, u64 renderpass_key);
|
||||
|
@ -98,7 +98,7 @@ namespace rsx
|
||||
sample_layout = surface_sample_layout::null;
|
||||
}
|
||||
|
||||
VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
if (samples == 1) [[likely]]
|
||||
{
|
||||
usage_flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
Loading…
x
Reference in New Issue
Block a user