mirror of
https://github.com/libretro/RetroArch
synced 2025-02-03 17:54:04 +00:00
Vulkan: Begin implementing history and feedback.
This commit is contained in:
parent
4f3ade1b95
commit
83ab0d799f
@ -191,6 +191,7 @@ typedef struct vulkan_context_fp
|
|||||||
|
|
||||||
/* Image commands */
|
/* Image commands */
|
||||||
PFN_vkCmdCopyImage vkCmdCopyImage;
|
PFN_vkCmdCopyImage vkCmdCopyImage;
|
||||||
|
PFN_vkCmdClearColorImage vkCmdClearColorImage;
|
||||||
|
|
||||||
/* Pipeline commands */
|
/* Pipeline commands */
|
||||||
PFN_vkCmdBindPipeline vkCmdBindPipeline;
|
PFN_vkCmdBindPipeline vkCmdBindPipeline;
|
||||||
|
@ -1153,6 +1153,7 @@ static bool vulkan_load_device_symbols(gfx_ctx_vulkan_data_t *vk)
|
|||||||
|
|
||||||
/* Image commands */
|
/* Image commands */
|
||||||
VK_GET_DEVICE_PROC_ADDR(CmdCopyImage);
|
VK_GET_DEVICE_PROC_ADDR(CmdCopyImage);
|
||||||
|
VK_GET_DEVICE_PROC_ADDR(CmdClearColorImage);
|
||||||
|
|
||||||
/* Vertex input descriptions */
|
/* Vertex input descriptions */
|
||||||
VK_GET_DEVICE_PROC_ADDR(CmdBindVertexBuffers);
|
VK_GET_DEVICE_PROC_ADDR(CmdBindVertexBuffers);
|
||||||
|
@ -584,6 +584,7 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
|
|||||||
info.swapchain.format = vk->context->swapchain_format;
|
info.swapchain.format = vk->context->swapchain_format;
|
||||||
info.swapchain.render_pass = vk->render_pass;
|
info.swapchain.render_pass = vk->render_pass;
|
||||||
info.swapchain.num_indices = vk->context->num_swapchain_images;
|
info.swapchain.num_indices = vk->context->num_swapchain_images;
|
||||||
|
info.original_format = vk->tex_fmt;
|
||||||
|
|
||||||
vk->filter_chain = vulkan_filter_chain_create_default(
|
vk->filter_chain = vulkan_filter_chain_create_default(
|
||||||
&info,
|
&info,
|
||||||
@ -614,6 +615,7 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path)
|
|||||||
info.swapchain.format = vk->context->swapchain_format;
|
info.swapchain.format = vk->context->swapchain_format;
|
||||||
info.swapchain.render_pass = vk->render_pass;
|
info.swapchain.render_pass = vk->render_pass;
|
||||||
info.swapchain.num_indices = vk->context->num_swapchain_images;
|
info.swapchain.num_indices = vk->context->num_swapchain_images;
|
||||||
|
info.original_format = vk->tex_fmt;
|
||||||
|
|
||||||
vk->filter_chain = vulkan_filter_chain_create_from_preset(
|
vk->filter_chain = vulkan_filter_chain_create_from_preset(
|
||||||
&info, shader_path,
|
&info, shader_path,
|
||||||
@ -1495,6 +1497,7 @@ static bool vulkan_frame(void *data, const void *frame,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.image = vk->hw.image->create_info.image;
|
||||||
input.view = vk->hw.image->image_view;
|
input.view = vk->hw.image->image_view;
|
||||||
input.layout = vk->hw.image->image_layout;
|
input.layout = vk->hw.image->image_layout;
|
||||||
|
|
||||||
@ -1520,6 +1523,7 @@ static bool vulkan_frame(void *data, const void *frame,
|
|||||||
else
|
else
|
||||||
vulkan_transition_texture(vk, tex);
|
vulkan_transition_texture(vk, tex);
|
||||||
|
|
||||||
|
input.image = tex->image;
|
||||||
input.view = tex->view;
|
input.view = tex->view;
|
||||||
input.layout = tex->layout;
|
input.layout = tex->layout;
|
||||||
input.width = tex->width;
|
input.width = tex->width;
|
||||||
|
@ -29,6 +29,34 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
static void image_layout_transition(
|
||||||
|
VkCommandBuffer cmd, VkImage image,
|
||||||
|
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||||
|
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
||||||
|
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages)
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||||
|
|
||||||
|
barrier.srcAccessMask = srcAccess;
|
||||||
|
barrier.dstAccessMask = dstAccess;
|
||||||
|
barrier.oldLayout = old_layout;
|
||||||
|
barrier.newLayout = new_layout;
|
||||||
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.image = image;
|
||||||
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
barrier.subresourceRange.levelCount = 1;
|
||||||
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
VKFUNC(vkCmdPipelineBarrier)(cmd,
|
||||||
|
srcStages,
|
||||||
|
dstStages,
|
||||||
|
false,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t find_memory_type(
|
static uint32_t find_memory_type(
|
||||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||||
uint32_t device_reqs, uint32_t host_reqs)
|
uint32_t device_reqs, uint32_t host_reqs)
|
||||||
@ -153,6 +181,9 @@ class Framebuffer
|
|||||||
VkFramebuffer get_framebuffer() const { return framebuffer; }
|
VkFramebuffer get_framebuffer() const { return framebuffer; }
|
||||||
VkRenderPass get_render_pass() const { return render_pass; }
|
VkRenderPass get_render_pass() const { return render_pass; }
|
||||||
|
|
||||||
|
void clear(VkCommandBuffer cmd);
|
||||||
|
void copy(VkCommandBuffer cmd, VkImage image, VkImageLayout layout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
const VkPhysicalDeviceMemoryProperties &memory_properties;
|
const VkPhysicalDeviceMemoryProperties &memory_properties;
|
||||||
@ -211,6 +242,11 @@ class Pass
|
|||||||
return *framebuffer;
|
return *framebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Framebuffer *get_feedback_framebuffer()
|
||||||
|
{
|
||||||
|
return framebuffer_feedback.get();
|
||||||
|
}
|
||||||
|
|
||||||
Size2D set_pass_info(
|
Size2D set_pass_info(
|
||||||
const Size2D &max_original,
|
const Size2D &max_original,
|
||||||
const Size2D &max_source,
|
const Size2D &max_source,
|
||||||
@ -222,6 +258,7 @@ class Pass
|
|||||||
size_t spirv_words);
|
size_t spirv_words);
|
||||||
|
|
||||||
bool build();
|
bool build();
|
||||||
|
bool init_feedback();
|
||||||
|
|
||||||
void build_commands(
|
void build_commands(
|
||||||
DeferredDisposer &disposer,
|
DeferredDisposer &disposer,
|
||||||
@ -246,6 +283,13 @@ class Pass
|
|||||||
this->common = &common;
|
this->common = &common;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const slang_reflection &get_reflection() const
|
||||||
|
{
|
||||||
|
return reflection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_frame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
const VkPhysicalDeviceMemoryProperties &memory_properties;
|
const VkPhysicalDeviceMemoryProperties &memory_properties;
|
||||||
@ -273,6 +317,7 @@ class Pass
|
|||||||
vector<uint32_t> vertex_shader;
|
vector<uint32_t> vertex_shader;
|
||||||
vector<uint32_t> fragment_shader;
|
vector<uint32_t> fragment_shader;
|
||||||
unique_ptr<Framebuffer> framebuffer;
|
unique_ptr<Framebuffer> framebuffer;
|
||||||
|
unique_ptr<Framebuffer> framebuffer_feedback;
|
||||||
VkRenderPass swapchain_render_pass;
|
VkRenderPass swapchain_render_pass;
|
||||||
|
|
||||||
void clear_vk();
|
void clear_vk();
|
||||||
@ -280,12 +325,6 @@ class Pass
|
|||||||
bool init_pipeline_layout();
|
bool init_pipeline_layout();
|
||||||
bool init_buffers();
|
bool init_buffers();
|
||||||
|
|
||||||
void image_layout_transition(VkDevice device,
|
|
||||||
VkCommandBuffer cmd, VkImage image,
|
|
||||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
|
||||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
|
||||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages);
|
|
||||||
|
|
||||||
void set_texture(VkDescriptorSet set, unsigned binding,
|
void set_texture(VkDescriptorSet set, unsigned binding,
|
||||||
const Texture &texture);
|
const Texture &texture);
|
||||||
|
|
||||||
@ -349,6 +388,7 @@ struct vulkan_filter_chain
|
|||||||
vector<vulkan_filter_chain_pass_info> pass_info;
|
vector<vulkan_filter_chain_pass_info> pass_info;
|
||||||
vector<vector<function<void ()>>> deferred_calls;
|
vector<vector<function<void ()>>> deferred_calls;
|
||||||
CommonResources common;
|
CommonResources common;
|
||||||
|
VkFormat original_format;
|
||||||
|
|
||||||
vulkan_filter_chain_texture input_texture;
|
vulkan_filter_chain_texture input_texture;
|
||||||
|
|
||||||
@ -364,6 +404,11 @@ struct vulkan_filter_chain
|
|||||||
void execute_deferred();
|
void execute_deferred();
|
||||||
void set_num_sync_indices(unsigned num_indices);
|
void set_num_sync_indices(unsigned num_indices);
|
||||||
void set_swapchain_info(const vulkan_filter_chain_swapchain_info &info);
|
void set_swapchain_info(const vulkan_filter_chain_swapchain_info &info);
|
||||||
|
|
||||||
|
bool init_history();
|
||||||
|
void update_history(DeferredDisposer &disposer, VkCommandBuffer cmd);
|
||||||
|
vector<unique_ptr<Framebuffer>> original_history;
|
||||||
|
bool require_clear = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
vulkan_filter_chain::vulkan_filter_chain(
|
vulkan_filter_chain::vulkan_filter_chain(
|
||||||
@ -371,7 +416,8 @@ vulkan_filter_chain::vulkan_filter_chain(
|
|||||||
: device(info.device),
|
: device(info.device),
|
||||||
memory_properties(*info.memory_properties),
|
memory_properties(*info.memory_properties),
|
||||||
cache(info.pipeline_cache),
|
cache(info.pipeline_cache),
|
||||||
common(info.device, *info.memory_properties)
|
common(info.device, *info.memory_properties),
|
||||||
|
original_format(info.original_format)
|
||||||
{
|
{
|
||||||
max_input_size = { info.max_input_size.width, info.max_input_size.height };
|
max_input_size = { info.max_input_size.width, info.max_input_size.height };
|
||||||
set_swapchain_info(info.swapchain);
|
set_swapchain_info(info.swapchain);
|
||||||
@ -466,6 +512,38 @@ void vulkan_filter_chain::flush()
|
|||||||
execute_deferred();
|
execute_deferred();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vulkan_filter_chain::init_history()
|
||||||
|
{
|
||||||
|
original_history.clear();
|
||||||
|
require_clear = false;
|
||||||
|
|
||||||
|
size_t required_images = 0;
|
||||||
|
for (auto &pass : passes)
|
||||||
|
{
|
||||||
|
required_images =
|
||||||
|
max(required_images,
|
||||||
|
pass->get_reflection().semantic_textures[SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (required_images < 2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// We don't need to store array element #0, since it's aliased with the actual original.
|
||||||
|
required_images--;
|
||||||
|
original_history.reserve(required_images);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < required_images; i++)
|
||||||
|
{
|
||||||
|
original_history.emplace_back(new Framebuffer(device, memory_properties,
|
||||||
|
max_input_size, original_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
// On first frame, we need to clear the textures to a known state, but we need
|
||||||
|
// a command buffer for that, so just defer to first frame.
|
||||||
|
require_clear = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool vulkan_filter_chain::init()
|
bool vulkan_filter_chain::init()
|
||||||
{
|
{
|
||||||
Size2D source = max_input_size;
|
Size2D source = max_input_size;
|
||||||
@ -479,12 +557,29 @@ bool vulkan_filter_chain::init()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!init_history())
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd,
|
void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd,
|
||||||
const VkViewport &vp)
|
const VkViewport &vp)
|
||||||
{
|
{
|
||||||
|
// First frame, make sure our history and feedback textures are in a clean state.
|
||||||
|
if (require_clear)
|
||||||
|
{
|
||||||
|
for (auto &texture : original_history)
|
||||||
|
texture->clear(cmd);
|
||||||
|
for (auto &pass : passes)
|
||||||
|
{
|
||||||
|
auto *fb = pass->get_feedback_framebuffer();
|
||||||
|
if (fb)
|
||||||
|
fb->clear(cmd);
|
||||||
|
}
|
||||||
|
require_clear = false;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
DeferredDisposer disposer(deferred_calls[current_sync_index]);
|
DeferredDisposer disposer(deferred_calls[current_sync_index]);
|
||||||
const Texture original = {
|
const Texture original = {
|
||||||
@ -506,6 +601,54 @@ void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vulkan_filter_chain::update_history(DeferredDisposer &disposer, VkCommandBuffer cmd)
|
||||||
|
{
|
||||||
|
VkImageLayout src_layout = input_texture.layout;
|
||||||
|
// Transition input texture to something appropriate.
|
||||||
|
if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL)
|
||||||
|
{
|
||||||
|
image_layout_transition(cmd,
|
||||||
|
input_texture.image,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
0,
|
||||||
|
VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
|
src_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr<Framebuffer> tmp;
|
||||||
|
unique_ptr<Framebuffer> &back = original_history.back();
|
||||||
|
swap(back, tmp);
|
||||||
|
|
||||||
|
if (input_texture.width != tmp->get_size().width ||
|
||||||
|
input_texture.height != tmp->get_size().height)
|
||||||
|
{
|
||||||
|
tmp->set_size(disposer, { input_texture.width, input_texture.height });
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp->copy(cmd, input_texture.image, src_layout);
|
||||||
|
|
||||||
|
// Transition input texture back.
|
||||||
|
if (input_texture.layout != VK_IMAGE_LAYOUT_GENERAL)
|
||||||
|
{
|
||||||
|
image_layout_transition(cmd,
|
||||||
|
input_texture.image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
0,
|
||||||
|
VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should ring buffer, but we don't have *that* many passes.
|
||||||
|
move(begin(original_history), end(original_history) - 1, begin(original_history) + 1);
|
||||||
|
swap(original_history.front(), tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void vulkan_filter_chain::build_viewport_pass(
|
void vulkan_filter_chain::build_viewport_pass(
|
||||||
VkCommandBuffer cmd, const VkViewport &vp, const float *mvp)
|
VkCommandBuffer cmd, const VkViewport &vp, const float *mvp)
|
||||||
{
|
{
|
||||||
@ -528,6 +671,16 @@ void vulkan_filter_chain::build_viewport_pass(
|
|||||||
|
|
||||||
passes.back()->build_commands(disposer, cmd,
|
passes.back()->build_commands(disposer, cmd,
|
||||||
original, source, vp, mvp);
|
original, source, vp, mvp);
|
||||||
|
|
||||||
|
// If we need to keep old frames, copy it after fragment is complete.
|
||||||
|
// TODO: We can improve pipelining by figuring out which pass is the last that reads from
|
||||||
|
// the history and dispatch the copy earlier.
|
||||||
|
if (!original_history.empty())
|
||||||
|
update_history(disposer, cmd);
|
||||||
|
|
||||||
|
// For feedback FBOs, swap current and previous.
|
||||||
|
for (auto &pass : passes)
|
||||||
|
pass->end_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Buffer(VkDevice device,
|
Buffer::Buffer(VkDevice device,
|
||||||
@ -978,8 +1131,29 @@ bool Pass::init_buffers()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pass::end_frame()
|
||||||
|
{
|
||||||
|
if (framebuffer_feedback)
|
||||||
|
swap(framebuffer, framebuffer_feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Pass::init_feedback()
|
||||||
|
{
|
||||||
|
if (final_pass)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
framebuffer_feedback = unique_ptr<Framebuffer>(
|
||||||
|
new Framebuffer(device, memory_properties,
|
||||||
|
current_framebuffer_size,
|
||||||
|
pass_info.rt_format));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Pass::build()
|
bool Pass::build()
|
||||||
{
|
{
|
||||||
|
framebuffer.reset();
|
||||||
|
framebuffer_feedback.reset();
|
||||||
|
|
||||||
if (!final_pass)
|
if (!final_pass)
|
||||||
{
|
{
|
||||||
framebuffer = unique_ptr<Framebuffer>(
|
framebuffer = unique_ptr<Framebuffer>(
|
||||||
@ -1001,34 +1175,6 @@ bool Pass::build()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pass::image_layout_transition(VkDevice device,
|
|
||||||
VkCommandBuffer cmd, VkImage image,
|
|
||||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
|
||||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
|
||||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages)
|
|
||||||
{
|
|
||||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
|
||||||
|
|
||||||
barrier.srcAccessMask = srcAccess;
|
|
||||||
barrier.dstAccessMask = dstAccess;
|
|
||||||
barrier.oldLayout = old_layout;
|
|
||||||
barrier.newLayout = new_layout;
|
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.image = image;
|
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
barrier.subresourceRange.levelCount = 1;
|
|
||||||
barrier.subresourceRange.layerCount = 1;
|
|
||||||
|
|
||||||
VKFUNC(vkCmdPipelineBarrier)(cmd,
|
|
||||||
srcStages,
|
|
||||||
dstStages,
|
|
||||||
0,
|
|
||||||
0, nullptr,
|
|
||||||
0, nullptr,
|
|
||||||
1, &barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Pass::set_uniform_buffer(VkDescriptorSet set, unsigned binding,
|
void Pass::set_uniform_buffer(VkDescriptorSet set, unsigned binding,
|
||||||
VkBuffer buffer,
|
VkBuffer buffer,
|
||||||
VkDeviceSize offset,
|
VkDeviceSize offset,
|
||||||
@ -1169,7 +1315,7 @@ void Pass::build_commands(
|
|||||||
if (!final_pass)
|
if (!final_pass)
|
||||||
{
|
{
|
||||||
// Render.
|
// Render.
|
||||||
image_layout_transition(device, cmd,
|
image_layout_transition(cmd,
|
||||||
framebuffer->get_image(),
|
framebuffer->get_image(),
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
@ -1247,7 +1393,6 @@ void Pass::build_commands(
|
|||||||
|
|
||||||
// Barrier to sync with next pass.
|
// Barrier to sync with next pass.
|
||||||
image_layout_transition(
|
image_layout_transition(
|
||||||
device,
|
|
||||||
cmd,
|
cmd,
|
||||||
framebuffer->get_image(),
|
framebuffer->get_image(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
@ -1274,6 +1419,63 @@ Framebuffer::Framebuffer(
|
|||||||
init(nullptr);
|
init(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Framebuffer::clear(VkCommandBuffer cmd)
|
||||||
|
{
|
||||||
|
image_layout_transition(cmd, image,
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
|
VkClearColorValue color;
|
||||||
|
memset(&color, 0, sizeof(color));
|
||||||
|
|
||||||
|
VkImageSubresourceRange range;
|
||||||
|
memset(&range, 0, sizeof(range));
|
||||||
|
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
range.levelCount = 1;
|
||||||
|
range.layerCount = 1;
|
||||||
|
|
||||||
|
VKFUNC(vkCmdClearColorImage)(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
&color, 1, &range);
|
||||||
|
|
||||||
|
image_layout_transition(cmd, image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Framebuffer::copy(VkCommandBuffer cmd,
|
||||||
|
VkImage src_image, VkImageLayout src_layout)
|
||||||
|
{
|
||||||
|
image_layout_transition(cmd, image,
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
|
VkImageCopy region;
|
||||||
|
memset(®ion, 0, sizeof(region));
|
||||||
|
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
region.srcSubresource.layerCount = 1;
|
||||||
|
region.dstSubresource = region.srcSubresource;
|
||||||
|
region.extent.width = size.width;
|
||||||
|
region.extent.height = size.height;
|
||||||
|
region.extent.depth = 1;
|
||||||
|
|
||||||
|
VKFUNC(vkCmdCopyImage)(cmd,
|
||||||
|
src_image, src_layout,
|
||||||
|
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1, ®ion);
|
||||||
|
|
||||||
|
image_layout_transition(cmd, image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
void Framebuffer::init(DeferredDisposer *disposer)
|
void Framebuffer::init(DeferredDisposer *disposer)
|
||||||
{
|
{
|
||||||
VkMemoryRequirements mem_reqs;
|
VkMemoryRequirements mem_reqs;
|
||||||
@ -1288,7 +1490,8 @@ void Framebuffer::init(DeferredDisposer *disposer)
|
|||||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ enum vulkan_filter_chain_filter
|
|||||||
|
|
||||||
struct vulkan_filter_chain_texture
|
struct vulkan_filter_chain_texture
|
||||||
{
|
{
|
||||||
|
VkImage image;
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VkImageLayout layout;
|
VkImageLayout layout;
|
||||||
unsigned width;
|
unsigned width;
|
||||||
@ -82,6 +83,7 @@ struct vulkan_filter_chain_create_info
|
|||||||
VkPipelineCache pipeline_cache;
|
VkPipelineCache pipeline_cache;
|
||||||
unsigned num_passes;
|
unsigned num_passes;
|
||||||
|
|
||||||
|
VkFormat original_format;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned width, height;
|
unsigned width, height;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user