1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

vulkan: Implement overlay shader passes

- Implements vk::overlay_pass and vk::depth_convert_pass
- Also added a sanity check in RSX core for depth replace shaders
This commit is contained in:
kd-11 2017-11-18 00:51:38 +03:00
parent 680ca1d12a
commit ccc0383f75
6 changed files with 462 additions and 85 deletions

View File

@ -116,7 +116,7 @@ namespace gl
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(depth_target ? GL_TRUE : GL_FALSE);
// AMD driver bug, disabling depth test doesnt work when doing depth replace (gl_FragDepth writes still go through the depth test)
// Disabling depth test will also disable depth writes which is not desired
glDepthFunc(GL_ALWAYS);
glEnable(GL_DEPTH_TEST);

View File

@ -1417,6 +1417,16 @@ namespace rsx
}
result.set_texture_dimension(texture_dimensions);
//Sanity checks
if (result.ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
{
//Check that the depth stage is not disabled
if (!rsx::method_registers.depth_test_enabled())
{
LOG_ERROR(RSX, "FS exports depth component but depth test is disabled (INVALID_OPERATION)");
}
}
}
void thread::get_current_fragment_program_legacy(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info)

View File

@ -644,6 +644,9 @@ VKGSRender::VKGSRender() : GSRender()
m_text_writer->init(*m_device, m_memory_type_mapping, m_render_passes[idx]);
}
m_depth_converter.reset(new vk::depth_convert_pass());
m_depth_converter->create(*m_device);
m_prog_buffer.reset(new VKProgramBuffer(m_render_passes.data()));
if (g_cfg.video.disable_vertex_cache)
@ -754,6 +757,10 @@ VKGSRender::~VKGSRender()
//Overlay text handler
m_text_writer.reset();
//RGBA->depth cast helper
m_depth_converter->destroy();
m_depth_converter.reset();
//Pipeline descriptors
vkDestroyPipelineLayout(*m_device, pipeline_layout, nullptr);
vkDestroyDescriptorSetLayout(*m_device, descriptor_layouts, nullptr);
@ -1246,6 +1253,96 @@ void VKGSRender::end()
std::chrono::time_point<steady_clock> program_stop = steady_clock::now();
m_setup_time += std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count();
textures_start = program_stop;
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (m_program->has_uniform("tex" + std::to_string(i)))
{
if (!rsx::method_registers.fragment_textures[i].enabled())
{
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
auto image_ptr = sampler_state->image_handle;
if (!image_ptr && sampler_state->external_subresource_desc.external_handle)
{
//Requires update, copy subresource
image_ptr = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
}
if (!image_ptr)
{
LOG_ERROR(RSX, "Texture upload failed to texture index %d. Binding null sampler.", i);
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
m_program->bind_uniform({ fs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
}
}
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
if (m_program->has_uniform("vtex" + std::to_string(i)))
{
if (!rsx::method_registers.vertex_textures[i].enabled())
{
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
auto image_ptr = sampler_state->image_handle;
if (!image_ptr && sampler_state->external_subresource_desc.external_handle)
{
image_ptr = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
m_vertex_textures_dirty[i] = true;
}
if (!image_ptr)
{
LOG_ERROR(RSX, "Texture upload failed to vtexture index %d. Binding null sampler.", i);
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
}
}
textures_end = steady_clock::now();
m_textures_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
//While vertex upload is an interruptible process, if we made it this far, there's no need to sync anything that occurs past this point
//Only textures are synchronized tightly with the GPU and they have been read back above
vk::enter_uninterruptible();
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
//Check for data casts
if (ds && ds->old_contents)
{
if (ds->old_contents->info.format == VK_FORMAT_B8G8R8A8_UNORM)
{
auto rp = vk::get_render_pass_location(VK_FORMAT_UNDEFINED, ds->info.format, 0);
auto render_pass = m_render_passes[rp];
m_depth_converter->run(*m_current_command_buffer, ds->width(), ds->height(), ds, ds->old_contents->get_view(), render_pass, m_framebuffers_to_clean);
ds->old_contents = nullptr;
ds->dirty = false;
}
else if (!g_cfg.video.strict_rendering_mode)
{
//Clear this to avoid dereferencing stale ptr
ds->old_contents = nullptr;
}
}
if (g_cfg.video.strict_rendering_mode)
{
auto copy_rtt_contents = [&](vk::render_target* surface)
@ -1295,82 +1392,12 @@ void VKGSRender::end()
}
}
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
if (ds && ds->old_contents)
{
if (ds->old_contents != nullptr)
copy_rtt_contents(ds);
copy_rtt_contents(ds);
}
}
textures_start = steady_clock::now();
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (m_program->has_uniform("tex" + std::to_string(i)))
{
if (!rsx::method_registers.fragment_textures[i].enabled())
{
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
auto image_ptr = sampler_state->image_handle;
if (!image_ptr && sampler_state->external_subresource_desc.external_handle)
{
//Requires update, copy subresource
image_ptr = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
}
if (!image_ptr)
{
LOG_ERROR(RSX, "Texture upload failed to texture index %d. Binding null sampler.", i);
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
m_program->bind_uniform({ fs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), m_current_frame->descriptor_set);
}
}
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
if (m_program->has_uniform("vtex" + std::to_string(i)))
{
if (!rsx::method_registers.vertex_textures[i].enabled())
{
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
auto image_ptr = sampler_state->image_handle;
if (!image_ptr && sampler_state->external_subresource_desc.external_handle)
{
image_ptr = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
m_vertex_textures_dirty[i] = true;
}
if (!image_ptr)
{
LOG_ERROR(RSX, "Texture upload failed to vtexture index %d. Binding null sampler.", i);
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
continue;
}
m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), m_current_frame->descriptor_set);
}
}
textures_end = steady_clock::now();
m_textures_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
//While vertex upload is an interruptible process, if we made it this far, there's no need to sync anything that occurs past this point
//Only textures are synchronized tightly with the GPU and they have been read back above
vk::enter_uninterruptible();
update_draw_state();
begin_render_pass();
@ -1383,20 +1410,17 @@ void VKGSRender::end()
buffers_to_clear.reserve(4);
const auto targets = rsx::utility::get_rtt_indexes(rsx::method_registers.surface_color_target());
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil))
if (ds && ds->dirty)
{
if (ds->dirty)
{
//Clear this surface before drawing on it
VkClearValue depth_clear_value;
depth_clear_value.depthStencil.depth = 1.f;
depth_clear_value.depthStencil.stencil = 255;
//Clear this surface before drawing on it
VkClearValue depth_clear_value;
depth_clear_value.depthStencil.depth = 1.f;
depth_clear_value.depthStencil.stencil = 255;
VkClearAttachment clear_desc = { ds->attachment_aspect_flag, 0, depth_clear_value };
buffers_to_clear.push_back(clear_desc);
VkClearAttachment clear_desc = { ds->attachment_aspect_flag, 0, depth_clear_value };
buffers_to_clear.push_back(clear_desc);
ds->dirty = false;
}
ds->dirty = false;
}
for (int index = 0; index < targets.size(); ++index)
@ -1939,6 +1963,8 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources)
m_text_writer->reset_descriptors();
}
m_depth_converter->free_resources();
ctx->buffer_views_to_clean.clear();
ctx->samplers_to_clean.clear();

View File

@ -5,6 +5,7 @@
#include "VKRenderTargets.h"
#include "VKFormats.h"
#include "VKTextOut.h"
#include "VKOverlays.h"
#include "restore_new.h"
#include "define_new_memleakdetect.h"
#include "VKProgramBuffer.h"
@ -134,6 +135,7 @@ private:
std::unique_ptr<vk::buffer_view> null_buffer_view;
std::unique_ptr<vk::text_writer> m_text_writer;
std::unique_ptr<vk::depth_convert_pass> m_depth_converter;
std::mutex m_sampler_mutex;
u64 surface_store_tag = 0;

View File

@ -2,11 +2,348 @@
#include "VKHelpers.h"
#include "VKVertexProgram.h"
#include "VKFragmentProgram.h"
#include "VKRenderTargets.h"
namespace vk
{
//TODO: Refactor text print class to inherit from this base class
struct overlay_pass
{
//TODO
VKVertexProgram m_vertex_shader;
VKFragmentProgram m_fragment_shader;
vk::descriptor_pool m_descriptor_pool;
VkDescriptorSet m_descriptor_set = nullptr;
VkDescriptorSetLayout m_descriptor_layout = nullptr;
VkPipelineLayout m_pipeline_layout = nullptr;
u32 m_used_descriptors = 0;
std::unordered_map<VkRenderPass, std::unique_ptr<vk::glsl::program>> m_program_cache;
std::unique_ptr<vk::sampler> m_sampler;
std::unique_ptr<vk::framebuffer> m_draw_fbo;
vk::render_device* m_device = nullptr;
std::string vs_src;
std::string fs_src;
struct
{
int color_attachments = 0;
bool write_color = true;
bool write_depth = true;
bool no_depth_test = true;
}
renderpass_config;
bool initialized = false;
bool compiled = false;
void init_descriptors()
{
VkDescriptorPoolSize descriptor_pools[1] =
{
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 120 },
};
//Reserve descriptor pools
m_descriptor_pool.create(*m_device, descriptor_pools, 1);
VkDescriptorSetLayoutBinding bindings[1] = {};
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bindings[0].descriptorCount = 1;
bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
bindings[0].binding = 0;
VkDescriptorSetLayoutCreateInfo infos = {};
infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
infos.pBindings = bindings;
infos.bindingCount = 1;
CHECK_RESULT(vkCreateDescriptorSetLayout(*m_device, &infos, nullptr, &m_descriptor_layout));
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = &m_descriptor_layout;
CHECK_RESULT(vkCreatePipelineLayout(*m_device, &layout_info, nullptr, &m_pipeline_layout));
}
vk::glsl::program* build_pipeline(VkRenderPass render_pass)
{
if (!compiled)
{
m_vertex_shader.shader = vs_src;
m_vertex_shader.Compile();
m_fragment_shader.shader = fs_src;
m_fragment_shader.Compile();
compiled = true;
}
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader_stages[0].module = m_vertex_shader.handle;
shader_stages[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = m_fragment_shader.handle;
shader_stages[1].pName = "main";
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
VkPipelineDynamicStateCreateInfo dynamic_state_info = {};
dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
dynamic_state_info.pDynamicStates = dynamic_state_descriptors;
VkPipelineVertexInputStateCreateInfo vi = {};
vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
VkPipelineViewportStateCreateInfo vp = {};
vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vp.scissorCount = 1;
vp.viewportCount = 1;
VkPipelineMultisampleStateCreateInfo ms = {};
ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms.pSampleMask = NULL;
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineInputAssemblyStateCreateInfo ia = {};
ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
VkPipelineRasterizationStateCreateInfo rs = {};
rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rs.lineWidth = 1.f;
rs.polygonMode = VK_POLYGON_MODE_FILL;
VkPipelineColorBlendAttachmentState att = {};
if (renderpass_config.write_color)
att.colorWriteMask = 0xf;
VkPipelineColorBlendStateCreateInfo cs = {};
cs.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
cs.attachmentCount = renderpass_config.color_attachments;
cs.pAttachments = &att;
VkPipelineDepthStencilStateCreateInfo ds = {};
ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
ds.depthWriteEnable = renderpass_config.write_depth? VK_TRUE: VK_FALSE;
ds.depthTestEnable = VK_TRUE;
ds.depthCompareOp = VK_COMPARE_OP_ALWAYS;
VkPipeline pipeline;
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pVertexInputState = &vi;
info.pInputAssemblyState = &ia;
info.pRasterizationState = &rs;
info.pColorBlendState = &cs;
info.pMultisampleState = &ms;
info.pViewportState = &vp;
info.pDepthStencilState = &ds;
info.stageCount = 2;
info.pStages = shader_stages;
info.pDynamicState = &dynamic_state_info;
info.layout = m_pipeline_layout;
info.basePipelineIndex = -1;
info.basePipelineHandle = VK_NULL_HANDLE;
info.renderPass = render_pass;
CHECK_RESULT(vkCreateGraphicsPipelines(*m_device, nullptr, 1, &info, NULL, &pipeline));
const std::vector<vk::glsl::program_input> unused;
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_texture, {}, {}, 0, "fs0"});
auto program = std::make_unique<vk::glsl::program>(*m_device, pipeline, unused, fs_inputs);
auto result = program.get();
m_program_cache[render_pass] = std::move(program);
return result;
}
void load_program(vk::command_buffer cmd, VkRenderPass pass, vk::image_view *src)
{
vk::glsl::program *program = nullptr;
auto found = m_program_cache.find(pass);
if (found != m_program_cache.end())
program = found->second.get();
else
program = build_pipeline(pass);
verify(HERE), m_used_descriptors < 120;
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.descriptorPool = m_descriptor_pool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = &m_descriptor_layout;
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, &m_descriptor_set));
m_used_descriptors++;
if (!m_sampler)
{
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,
VK_FALSE, 0.f, 1.f, 0.f, 0.f, VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
}
VkDescriptorImageInfo info = { m_sampler->value, src->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
program->bind_uniform(info, "fs0", m_descriptor_set);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, program->pipeline);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, &m_descriptor_set, 0, nullptr);
}
void create(vk::render_device &dev)
{
if (!initialized)
{
m_device = &dev;
init_descriptors();
initialized = true;
}
}
void destroy()
{
if (initialized)
{
m_program_cache.clear();
m_sampler.reset();
vkDestroyDescriptorSetLayout(*m_device, m_descriptor_layout, nullptr);
vkDestroyPipelineLayout(*m_device, m_pipeline_layout, nullptr);
m_descriptor_pool.destroy();
initialized = false;
}
}
void free_resources()
{
if (m_used_descriptors == 0)
return;
vkResetDescriptorPool(*m_device, m_descriptor_pool, 0);
m_used_descriptors = 0;
}
vk::framebuffer* get_framebuffer(vk::image* target, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
{
std::vector<vk::image*> test = {target};
for (auto It = framebuffer_resources.begin(); It != framebuffer_resources.end(); It++)
{
auto fbo = It->get();
if (fbo->matches(test, target->width(), target->height()))
{
fbo->deref_count = 0;
return fbo;
}
}
//No match, create new fbo and add to the list
std::vector<std::unique_ptr<vk::image_view>> views;
VkComponentMapping mapping = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
switch (target->info.format)
{
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; //We are only writing to depth
break;
}
auto view = std::make_unique<vk::image_view>(*m_device, target->value, VK_IMAGE_VIEW_TYPE_2D, target->info.format, mapping, range);
views.push_back(std::move(view));
auto fbo = std::make_unique<vk::framebuffer_holder>(*m_device, render_pass, target->width(), target->height(), std::move(views));
auto result = fbo.get();
framebuffer_resources.push_back(std::move(fbo));
return result;
}
void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, vk::image_view* src, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
{
vk::framebuffer *fbo = get_framebuffer(target, render_pass, framebuffer_resources);
VkViewport vp{};
vp.width = (f32)w;
vp.height = (f32)h;
vp.minDepth = 0.f;
vp.maxDepth = 1.f;
vkCmdSetViewport(cmd, 0, 1, &vp);
VkRect2D vs = { { 0, 0 },{ 0u + w, 0u + h } };
vkCmdSetScissor(cmd, 0, 1, &vs);
load_program(cmd, render_pass, src);
VkRenderPassBeginInfo rp_begin = {};
rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_begin.renderPass = render_pass;
rp_begin.framebuffer = fbo->value;
rp_begin.renderArea.offset.x = 0;
rp_begin.renderArea.offset.y = 0;
rp_begin.renderArea.extent.width = w;
rp_begin.renderArea.extent.height = h;
vkCmdBeginRenderPass(cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
vkCmdDraw(cmd, 4, 1, 0, 0);
vkCmdEndRenderPass(cmd);
}
};
struct depth_convert_pass : public overlay_pass
{
depth_convert_pass()
{
vs_src =
{
"#version 450\n"
"#extension GL_ARB_separate_shader_objects : enable\n"
"layout(location=0) out vec2 tc0;\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"
" gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n"
" tc0 = coords[gl_VertexIndex % 4];\n"
"}\n"
};
fs_src =
{
"#version 420\n"
"#extension GL_ARB_separate_shader_objects : enable\n"
"layout(set=0, binding=0) uniform sampler2D fs0;\n"
"layout(location=0) in vec2 tc0;\n"
"\n"
"void main()\n"
"{\n"
" vec4 rgba_in = texture(fs0, tc0);\n"
" uint raw_value = uint(rgba_in.b * 255.) | (uint(rgba_in.g * 255.) << 8) | (uint(rgba_in.r * 255.) << 16);\n"
" gl_FragDepth = float(raw_value) / 16777215.;\n"
" //gl_FragDepth = rgba_in.r * 0.99609 + rgba_in.g * 0.00389 + rgba_in.b * 0.00002;\n"
"}\n"
};
renderpass_config.write_color = false;
m_vertex_shader.id = 100002;
m_fragment_shader.id = 100003;
}
};
}

View File

@ -103,9 +103,11 @@ namespace vk
};
m_vertex_shader.shader = vs;
m_vertex_shader.id = 100000;
m_vertex_shader.Compile();
m_fragment_shader.shader = fs;
m_fragment_shader.id = 100001;
m_fragment_shader.Compile();
VkPipelineShaderStageCreateInfo shader_stages[2] = {};