mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 12:31:45 +01:00
vk: Add synchronous compute pipelines
- Compute is now used to assist in some parts of blit operations, since there are no format conversions with vulkan like OGL does - TODO: Integrate this into all types of GPU memory conversion operations instead of downloading to CPU then converting
This commit is contained in:
parent
0d5c071eee
commit
2afcf369ec
@ -83,7 +83,8 @@ namespace glsl
|
||||
enum program_domain
|
||||
{
|
||||
glsl_vertex_program = 0,
|
||||
glsl_fragment_program = 1
|
||||
glsl_fragment_program = 1,
|
||||
glsl_compute_program = 2
|
||||
};
|
||||
|
||||
enum glsl_rules
|
||||
|
@ -140,7 +140,8 @@ namespace vk
|
||||
|
||||
bool compile_glsl_to_spv(std::string& shader, program_domain domain, std::vector<u32>& spv)
|
||||
{
|
||||
EShLanguage lang = (domain == glsl_fragment_program) ? EShLangFragment : EShLangVertex;
|
||||
EShLanguage lang = (domain == glsl_fragment_program) ? EShLangFragment :
|
||||
(domain == glsl_vertex_program)? EShLangVertex : EShLangCompute;
|
||||
|
||||
glslang::TProgram program;
|
||||
glslang::TShader shader_object(lang);
|
||||
|
256
rpcs3/Emu/RSX/VK/VKCompute.h
Normal file
256
rpcs3/Emu/RSX/VK/VKCompute.h
Normal file
@ -0,0 +1,256 @@
|
||||
#pragma once
|
||||
#include "VKHelpers.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
struct compute_task
|
||||
{
|
||||
std::string m_src;
|
||||
vk::glsl::shader m_shader;
|
||||
std::unique_ptr<vk::glsl::program> m_program;
|
||||
|
||||
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;
|
||||
|
||||
bool initialized = false;
|
||||
u32 optimal_group_size = 64;
|
||||
|
||||
void init_descriptors()
|
||||
{
|
||||
VkDescriptorPoolSize descriptor_pool_sizes[1] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 120 },
|
||||
};
|
||||
|
||||
//Reserve descriptor pools
|
||||
m_descriptor_pool.create(*get_current_renderer(), descriptor_pool_sizes, 1);
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings(1);
|
||||
|
||||
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[0].descriptorCount = 1;
|
||||
bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
bindings[0].binding = 0;
|
||||
bindings[0].pImmutableSamplers = nullptr;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo infos = {};
|
||||
infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
infos.pBindings = bindings.data();
|
||||
infos.bindingCount = bindings.size();
|
||||
|
||||
CHECK_RESULT(vkCreateDescriptorSetLayout(*get_current_renderer(), &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(*get_current_renderer(), &layout_info, nullptr, &m_pipeline_layout));
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
init_descriptors();
|
||||
|
||||
switch (vk::get_driver_vendor())
|
||||
{
|
||||
case vk::driver_vendor::unknown:
|
||||
// Probably intel
|
||||
case vk::driver_vendor::NVIDIA:
|
||||
optimal_group_size = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
m_shader.destroy();
|
||||
m_program.reset();
|
||||
|
||||
vkDestroyDescriptorSetLayout(*get_current_renderer(), m_descriptor_layout, nullptr);
|
||||
vkDestroyPipelineLayout(*get_current_renderer(), m_pipeline_layout, nullptr);
|
||||
m_descriptor_pool.destroy();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void free_resources()
|
||||
{
|
||||
if (m_used_descriptors == 0)
|
||||
return;
|
||||
|
||||
vkResetDescriptorPool(*get_current_renderer(), m_descriptor_pool, 0);
|
||||
m_used_descriptors = 0;
|
||||
}
|
||||
|
||||
virtual void bind_resources()
|
||||
{}
|
||||
|
||||
void load_program(const vk::command_buffer& cmd)
|
||||
{
|
||||
if (!m_program)
|
||||
{
|
||||
m_shader.create(::glsl::program_domain::glsl_compute_program, m_src);
|
||||
auto handle = m_shader.compile();
|
||||
|
||||
VkPipelineShaderStageCreateInfo shader_stage{};
|
||||
shader_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shader_stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
shader_stage.module = handle;
|
||||
shader_stage.pName = "main";
|
||||
|
||||
VkComputePipelineCreateInfo info{};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
info.stage = shader_stage;
|
||||
info.layout = m_pipeline_layout;
|
||||
info.basePipelineIndex = -1;
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
|
||||
VkPipeline pipeline;
|
||||
vkCreateComputePipelines(*get_current_renderer(), nullptr, 1, &info, nullptr, &pipeline);
|
||||
|
||||
std::vector<vk::glsl::program_input> inputs;
|
||||
m_program = std::make_unique<vk::glsl::program>(*get_current_renderer(), pipeline, inputs, inputs);
|
||||
}
|
||||
|
||||
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(*get_current_renderer(), &alloc_info, &m_descriptor_set));
|
||||
m_used_descriptors++;
|
||||
|
||||
bind_resources();
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_program->pipeline);
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline_layout, 0, 1, &m_descriptor_set, 0, nullptr);
|
||||
}
|
||||
|
||||
virtual void run(const vk::command_buffer& cmd, u32 num_invocations)
|
||||
{
|
||||
load_program(cmd);
|
||||
vkCmdDispatch(cmd, num_invocations, 1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct cs_shuffle_base : compute_task
|
||||
{
|
||||
vk::buffer* m_data;
|
||||
u32 kernel_size = 1;
|
||||
|
||||
void build(const char* function_name, u32 _kernel_size)
|
||||
{
|
||||
kernel_size = _kernel_size;
|
||||
|
||||
m_src =
|
||||
{
|
||||
"#version 430\n"
|
||||
"layout(local_size_x=%ws, local_size_y=1, local_size_z=1) in;\n"
|
||||
"layout(std430, set=0, binding=0) buffer ssbo{ uint data[]; };\n\n"
|
||||
"\n"
|
||||
"#define KERNEL_SIZE %ks\n"
|
||||
"#define bswap_u16(bits) (bits & 0xFF) << 8 | (bits & 0xFF00) >> 8 | (bits & 0xFF0000) << 8 | (bits & 0xFF000000) >> 8\n"
|
||||
"#define bswap_u32(bits) (bits & 0xFF) << 24 | (bits & 0xFF00) << 8 | (bits & 0xFF0000) >> 8 | (bits & 0xFF000000) >> 24\n"
|
||||
"#define bswap_u16_u32(bits) (bits & 0xFFFF) << 16 | (bits & 0xFFFF0000) >> 16\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" uint index = gl_GlobalInvocationID.x * KERNEL_SIZE;\n"
|
||||
" for (uint loop = 0; loop < KERNEL_SIZE; ++loop)\n"
|
||||
" {\n"
|
||||
" uint value = data[index];\n"
|
||||
" data[index] = %f(value);\n"
|
||||
" index++;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const std::pair<std::string, std::string> syntax_replace[] =
|
||||
{
|
||||
{ "%ws", std::to_string(optimal_group_size) },
|
||||
{ "%ks", std::to_string(kernel_size) },
|
||||
{ "%f", function_name }
|
||||
};
|
||||
|
||||
m_src = fmt::replace_all(m_src, syntax_replace);
|
||||
}
|
||||
|
||||
void bind_resources() override
|
||||
{
|
||||
m_program->bind_buffer({ m_data->value, 0, VK_WHOLE_SIZE }, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_descriptor_set);
|
||||
}
|
||||
|
||||
void run(const vk::command_buffer& cmd, vk::buffer* data, u32 mem_size)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
const auto num_bytes_per_invocation = optimal_group_size * kernel_size * 4;
|
||||
const auto num_invocations = align(mem_size, 256) / num_bytes_per_invocation;
|
||||
compute_task::run(cmd, num_invocations);
|
||||
}
|
||||
};
|
||||
|
||||
struct cs_shuffle_16 : cs_shuffle_base
|
||||
{
|
||||
vk::buffer* m_data;
|
||||
|
||||
// byteswap ushort
|
||||
cs_shuffle_16()
|
||||
{
|
||||
cs_shuffle_base::build("bswap_u16", 32);
|
||||
}
|
||||
};
|
||||
|
||||
struct cs_shuffle_32 : cs_shuffle_base
|
||||
{
|
||||
// byteswap_ulong
|
||||
cs_shuffle_32()
|
||||
{
|
||||
cs_shuffle_base::build("bswap_u32", 32);
|
||||
}
|
||||
};
|
||||
|
||||
struct cs_shuffle_32_16 : cs_shuffle_base
|
||||
{
|
||||
// byteswap_ulong + byteswap_ushort
|
||||
cs_shuffle_32_16()
|
||||
{
|
||||
cs_shuffle_base::build("bswap_u16_u32", 32);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Replace with a proper manager
|
||||
extern std::unordered_map<u32, std::unique_ptr<vk::compute_task>> g_compute_tasks;
|
||||
|
||||
template<class T>
|
||||
T* get_compute_task()
|
||||
{
|
||||
u32 index = id_manager::typeinfo::get_index<T>();
|
||||
auto &e = g_compute_tasks[index];
|
||||
|
||||
if (!e)
|
||||
{
|
||||
e = std::make_unique<T>();
|
||||
e->create();
|
||||
}
|
||||
|
||||
return static_cast<T*>(e.get());
|
||||
}
|
||||
|
||||
void reset_compute_tasks();
|
||||
}
|
@ -362,8 +362,11 @@ VKFragmentProgram::~VKFragmentProgram()
|
||||
void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
|
||||
{
|
||||
u32 size;
|
||||
VKFragmentDecompilerThread decompiler(shader, parr, prog, size, *this);
|
||||
std::string source;
|
||||
VKFragmentDecompilerThread decompiler(source, parr, prog, size, *this);
|
||||
decompiler.Task();
|
||||
|
||||
shader.create(::glsl::program_domain::glsl_fragment_program, source);
|
||||
|
||||
for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
@ -384,34 +387,13 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
|
||||
void VKFragmentProgram::Compile()
|
||||
{
|
||||
fs::create_path(fs::get_config_dir() + "/shaderlog");
|
||||
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
|
||||
|
||||
std::vector<u32> spir_v;
|
||||
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_fragment_program, spir_v))
|
||||
fmt::throw_exception("Failed to compile fragment shader" HERE);
|
||||
|
||||
//Create the object and compile
|
||||
VkShaderModuleCreateInfo fs_info;
|
||||
fs_info.codeSize = spir_v.size() * sizeof(u32);
|
||||
fs_info.pNext = nullptr;
|
||||
fs_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
fs_info.pCode = (uint32_t*)spir_v.data();
|
||||
fs_info.flags = 0;
|
||||
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkCreateShaderModule(dev, &fs_info, nullptr, &handle);
|
||||
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source());
|
||||
handle = shader.compile();
|
||||
}
|
||||
|
||||
void VKFragmentProgram::Delete()
|
||||
{
|
||||
shader.clear();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkDestroyShaderModule(dev, handle, NULL);
|
||||
handle = nullptr;
|
||||
}
|
||||
shader.destroy();
|
||||
}
|
||||
|
||||
void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
ParamArray parr;
|
||||
VkShaderModule handle = nullptr;
|
||||
u32 id;
|
||||
std::string shader;
|
||||
vk::glsl::shader shader;
|
||||
std::vector<size_t> FragmentConstantOffsetCache;
|
||||
|
||||
std::array<u32, 4> output_color_masks{ {} };
|
||||
|
@ -2024,6 +2024,8 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources)
|
||||
m_overlay_manager->dispose(uids_to_dispose);
|
||||
}
|
||||
|
||||
vk::reset_compute_tasks();
|
||||
|
||||
m_attachment_clear_pass->free_resources();
|
||||
m_depth_converter->free_resources();
|
||||
m_ui_renderer->free_resources();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "VKHelpers.h"
|
||||
#include "VKCompute.h"
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
namespace vk
|
||||
@ -11,6 +12,7 @@ namespace vk
|
||||
std::unique_ptr<image_view> g_null_image_view;
|
||||
std::unique_ptr<buffer> g_scratch_buffer;
|
||||
std::unordered_map<u32, std::unique_ptr<image>> g_typeless_textures;
|
||||
std::unordered_map<u32, std::unique_ptr<vk::compute_task>> g_compute_tasks;
|
||||
|
||||
VkSampler g_null_sampler = nullptr;
|
||||
|
||||
@ -195,7 +197,7 @@ namespace vk
|
||||
// 32M disposable scratch memory
|
||||
g_scratch_buffer = std::make_unique<vk::buffer>(*g_current_renderer, 32 * 0x100000,
|
||||
g_current_renderer->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0);
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0);
|
||||
}
|
||||
|
||||
return g_scratch_buffer.get();
|
||||
@ -211,6 +213,14 @@ namespace vk
|
||||
g_submit_mutex.unlock();
|
||||
}
|
||||
|
||||
void reset_compute_tasks()
|
||||
{
|
||||
for (const auto &p : g_compute_tasks)
|
||||
{
|
||||
p.second->free_resources();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_global_resources()
|
||||
{
|
||||
g_null_texture.reset();
|
||||
@ -223,6 +233,13 @@ namespace vk
|
||||
vkDestroySampler(*g_current_renderer, g_null_sampler, nullptr);
|
||||
|
||||
g_null_sampler = nullptr;
|
||||
|
||||
for (const auto& p : g_compute_tasks)
|
||||
{
|
||||
p.second->destroy();
|
||||
}
|
||||
|
||||
g_compute_tasks.clear();
|
||||
}
|
||||
|
||||
vk::mem_allocator_base* get_current_mem_allocator()
|
||||
@ -330,6 +347,21 @@ namespace vk
|
||||
return g_drv_disable_fence_reset;
|
||||
}
|
||||
|
||||
void insert_buffer_memory_barrier(VkCommandBuffer cmd, VkBuffer buffer, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src_mask, VkAccessFlags dst_mask)
|
||||
{
|
||||
VkBufferMemoryBarrier barrier = {};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||
barrier.buffer = buffer;
|
||||
barrier.offset = 0;
|
||||
barrier.size = VK_WHOLE_SIZE;
|
||||
barrier.srcAccessMask = src_mask;
|
||||
barrier.dstAccessMask = dst_mask;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
|
||||
vkCmdPipelineBarrier(cmd, src_stage, dst_stage, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||
}
|
||||
|
||||
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
|
||||
{
|
||||
//Prepare an image to match the new layout..
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Emu/System.h"
|
||||
#include "VulkanAPI.h"
|
||||
#include "VKCommonDecompiler.h"
|
||||
#include "../GCM.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "../Common/ring_buffer_helper.h"
|
||||
#include "../Common/GLSLCommon.h"
|
||||
#include "../rsx_cache.h"
|
||||
|
||||
#include "3rdparty/GPUOpen/include/vk_mem_alloc.h"
|
||||
@ -110,6 +110,10 @@ namespace vk
|
||||
void acquire_global_submit_lock();
|
||||
void release_global_submit_lock();
|
||||
|
||||
template<class T>
|
||||
T* get_compute_task();
|
||||
void reset_compute_tasks();
|
||||
|
||||
void destroy_global_resources();
|
||||
|
||||
/**
|
||||
@ -126,15 +130,15 @@ namespace vk
|
||||
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout, VkImageSubresourceRange range);
|
||||
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout);
|
||||
|
||||
void copy_image_typeless(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
void copy_image_typeless(const command_buffer &cmd, const image *src, const image *dst, const areai& src_rect, const areai& dst_rect,
|
||||
u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF);
|
||||
|
||||
void copy_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
void copy_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF);
|
||||
|
||||
void copy_scaled_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
void copy_scaled_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height, u32 mipmaps,
|
||||
VkImageAspectFlags aspect, bool compatible_formats, VkFilter filter = VK_FILTER_LINEAR, VkFormat src_format = VK_FORMAT_UNDEFINED, VkFormat dst_format = VK_FORMAT_UNDEFINED);
|
||||
|
||||
@ -145,6 +149,8 @@ namespace vk
|
||||
void insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout layout, VkImageSubresourceRange range);
|
||||
void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image);
|
||||
|
||||
void insert_buffer_memory_barrier(VkCommandBuffer cmd, VkBuffer buffer, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src_mask, VkAccessFlags dst_mask);
|
||||
|
||||
//Manage 'uininterruptible' state where secondary operations (e.g violation handlers) will have to wait
|
||||
void enter_uninterruptible();
|
||||
void leave_uninterruptible();
|
||||
@ -1021,7 +1027,7 @@ namespace vk
|
||||
return *pool;
|
||||
}
|
||||
|
||||
operator VkCommandBuffer()
|
||||
operator VkCommandBuffer() const
|
||||
{
|
||||
return commands;
|
||||
}
|
||||
@ -2116,13 +2122,13 @@ public:
|
||||
class descriptor_pool
|
||||
{
|
||||
VkDescriptorPool pool = nullptr;
|
||||
vk::render_device *owner = nullptr;
|
||||
const vk::render_device *owner = nullptr;
|
||||
|
||||
public:
|
||||
descriptor_pool() {}
|
||||
~descriptor_pool() {}
|
||||
|
||||
void create(vk::render_device &dev, VkDescriptorPoolSize *sizes, u32 size_descriptors_count)
|
||||
void create(const vk::render_device &dev, VkDescriptorPoolSize *sizes, u32 size_descriptors_count)
|
||||
{
|
||||
VkDescriptorPoolCreateInfo infos = {};
|
||||
infos.flags = 0;
|
||||
@ -2426,7 +2432,8 @@ public:
|
||||
{
|
||||
input_type_uniform_buffer = 0,
|
||||
input_type_texel_buffer = 1,
|
||||
input_type_texture = 2
|
||||
input_type_texture = 2,
|
||||
input_type_storage_buffer = 3
|
||||
};
|
||||
|
||||
struct bound_sampler
|
||||
@ -2456,6 +2463,80 @@ public:
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class shader
|
||||
{
|
||||
::glsl::program_domain type = ::glsl::program_domain::glsl_vertex_program;
|
||||
VkShaderModule m_handle = VK_NULL_HANDLE;
|
||||
std::string m_source;
|
||||
std::vector<u32> m_compiled;
|
||||
|
||||
public:
|
||||
shader()
|
||||
{}
|
||||
|
||||
~shader()
|
||||
{}
|
||||
|
||||
void create(::glsl::program_domain domain, const std::string& source)
|
||||
{
|
||||
type = domain;
|
||||
m_source = source;
|
||||
}
|
||||
|
||||
VkShaderModule compile()
|
||||
{
|
||||
verify(HERE), m_handle == VK_NULL_HANDLE;
|
||||
|
||||
if (!vk::compile_glsl_to_spv(m_source, type, m_compiled))
|
||||
{
|
||||
std::string shader_type = type == ::glsl::program_domain::glsl_vertex_program ? "vertex" :
|
||||
type == ::glsl::program_domain::glsl_fragment_program ? "fragment" : "compute";
|
||||
|
||||
fmt::throw_exception("Failed to compile %s shader" HERE, shader_type);
|
||||
}
|
||||
|
||||
VkShaderModuleCreateInfo vs_info;
|
||||
vs_info.codeSize = m_compiled.size() * sizeof(u32);
|
||||
vs_info.pNext = nullptr;
|
||||
vs_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
vs_info.pCode = (uint32_t*)m_compiled.data();
|
||||
vs_info.flags = 0;
|
||||
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkCreateShaderModule(dev, &vs_info, nullptr, &m_handle);
|
||||
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_source.clear();
|
||||
m_compiled.clear();
|
||||
|
||||
if (m_handle)
|
||||
{
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkDestroyShaderModule(dev, m_handle, nullptr);
|
||||
m_handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& get_source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
const std::vector<u32> get_compiled() const
|
||||
{
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
VkShaderModule get_handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
};
|
||||
|
||||
class program
|
||||
{
|
||||
std::vector<program_input> uniforms;
|
||||
@ -2473,10 +2554,12 @@ public:
|
||||
program& load_uniforms(::glsl::program_domain domain, const std::vector<program_input>& inputs);
|
||||
|
||||
bool has_uniform(std::string uniform_name);
|
||||
void bind_uniform(VkDescriptorImageInfo image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(VkDescriptorBufferInfo buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(const VkDescriptorImageInfo &image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(const VkBufferView &buffer_view, const std::string &binding_name, VkDescriptorSet &descriptor_set);
|
||||
|
||||
void bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set);
|
||||
|
||||
u64 get_vertex_input_attributes_mask();
|
||||
};
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ namespace vk
|
||||
//TODO: Refactor text print class to inherit from this base class
|
||||
struct overlay_pass
|
||||
{
|
||||
VKVertexProgram m_vertex_shader;
|
||||
VKFragmentProgram m_fragment_shader;
|
||||
vk::glsl::shader m_vertex_shader;
|
||||
vk::glsl::shader m_fragment_shader;
|
||||
|
||||
vk::descriptor_pool m_descriptor_pool;
|
||||
VkDescriptorSet m_descriptor_set = nullptr;
|
||||
@ -149,11 +149,11 @@ namespace vk
|
||||
{
|
||||
if (!compiled)
|
||||
{
|
||||
m_vertex_shader.shader = vs_src;
|
||||
m_vertex_shader.Compile();
|
||||
m_vertex_shader.create(::glsl::program_domain::glsl_vertex_program, vs_src);
|
||||
m_vertex_shader.compile();
|
||||
|
||||
m_fragment_shader.shader = fs_src;
|
||||
m_fragment_shader.Compile();
|
||||
m_fragment_shader.create(::glsl::program_domain::glsl_fragment_program, fs_src);
|
||||
m_fragment_shader.compile();
|
||||
|
||||
compiled = true;
|
||||
}
|
||||
@ -161,12 +161,12 @@ namespace vk
|
||||
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].module = m_vertex_shader.get_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].module = m_fragment_shader.get_handle();
|
||||
shader_stages[1].pName = "main";
|
||||
|
||||
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
||||
@ -282,6 +282,8 @@ namespace vk
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
m_vertex_shader.destroy();
|
||||
m_fragment_shader.destroy();
|
||||
m_program_cache.clear();
|
||||
m_sampler.reset();
|
||||
|
||||
@ -434,9 +436,6 @@ namespace vk
|
||||
renderpass_config.set_depth_mask(true);
|
||||
renderpass_config.enable_depth_test(VK_COMPARE_OP_ALWAYS);
|
||||
renderpass_config.enable_stencil_test(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_COMPARE_OP_ALWAYS, 0xFF, 0xFF);
|
||||
|
||||
m_vertex_shader.id = 100002;
|
||||
m_fragment_shader.id = 100003;
|
||||
}
|
||||
};
|
||||
|
||||
@ -521,9 +520,6 @@ namespace vk
|
||||
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
VK_BLEND_OP_ADD, VK_BLEND_OP_ADD);
|
||||
|
||||
m_vertex_shader.id = 100004;
|
||||
m_fragment_shader.id = 100005;
|
||||
}
|
||||
|
||||
vk::image_view* upload_simple_texture(vk::render_device &dev, vk::command_buffer &cmd,
|
||||
@ -784,9 +780,6 @@ namespace vk
|
||||
renderpass_config.set_depth_mask(false);
|
||||
renderpass_config.set_color_mask(true, true, true, true);
|
||||
renderpass_config.set_attachment_count(1);
|
||||
|
||||
m_vertex_shader.id = 100006;
|
||||
m_fragment_shader.id = 100007;
|
||||
}
|
||||
|
||||
void update_uniforms(vk::glsl::program* /*program*/) override
|
||||
|
@ -48,7 +48,7 @@ namespace vk
|
||||
return false;
|
||||
}
|
||||
|
||||
void program::bind_uniform(VkDescriptorImageInfo image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set)
|
||||
void program::bind_uniform(const VkDescriptorImageInfo &image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set)
|
||||
{
|
||||
for (auto &uniform : uniforms)
|
||||
{
|
||||
@ -72,19 +72,9 @@ namespace vk
|
||||
LOG_NOTICE(RSX, "texture not found in program: %s", uniform_name.c_str());
|
||||
}
|
||||
|
||||
void program::bind_uniform(VkDescriptorBufferInfo buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set)
|
||||
void program::bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set)
|
||||
{
|
||||
VkWriteDescriptorSet descriptor_writer = {};
|
||||
descriptor_writer.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_writer.dstSet = descriptor_set;
|
||||
descriptor_writer.descriptorCount = 1;
|
||||
descriptor_writer.pBufferInfo = &buffer_descriptor;
|
||||
descriptor_writer.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptor_writer.dstArrayElement = 0;
|
||||
descriptor_writer.dstBinding = binding_point;
|
||||
|
||||
vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr);
|
||||
attribute_location_mask |= (1ull << binding_point);
|
||||
bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set);
|
||||
}
|
||||
|
||||
void program::bind_uniform(const VkBufferView &buffer_view, const std::string &binding_name, VkDescriptorSet &descriptor_set)
|
||||
@ -111,6 +101,21 @@ namespace vk
|
||||
LOG_NOTICE(RSX, "vertex buffer not found in program: %s", binding_name.c_str());
|
||||
}
|
||||
|
||||
void program::bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set)
|
||||
{
|
||||
VkWriteDescriptorSet descriptor_writer = {};
|
||||
descriptor_writer.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_writer.dstSet = descriptor_set;
|
||||
descriptor_writer.descriptorCount = 1;
|
||||
descriptor_writer.pBufferInfo = &buffer_descriptor;
|
||||
descriptor_writer.descriptorType = type;
|
||||
descriptor_writer.dstArrayElement = 0;
|
||||
descriptor_writer.dstBinding = binding_point;
|
||||
|
||||
vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr);
|
||||
attribute_location_mask |= (1ull << binding_point);
|
||||
}
|
||||
|
||||
u64 program::get_vertex_input_attributes_mask()
|
||||
{
|
||||
if (vertex_attributes_mask)
|
||||
|
@ -13,8 +13,8 @@ namespace vk
|
||||
std::unique_ptr<vk::buffer> m_uniforms_buffer;
|
||||
|
||||
std::unique_ptr<vk::glsl::program> m_program;
|
||||
VKVertexProgram m_vertex_shader;
|
||||
VKFragmentProgram m_fragment_shader;
|
||||
vk::glsl::shader m_vertex_shader;
|
||||
vk::glsl::shader m_fragment_shader;
|
||||
|
||||
vk::descriptor_pool m_descriptor_pool;
|
||||
VkDescriptorSet m_descriptor_set = nullptr;
|
||||
@ -102,23 +102,21 @@ namespace vk
|
||||
"}\n"
|
||||
};
|
||||
|
||||
m_vertex_shader.shader = vs;
|
||||
m_vertex_shader.id = 100000;
|
||||
m_vertex_shader.Compile();
|
||||
m_vertex_shader.create(::glsl::program_domain::glsl_vertex_program, vs);
|
||||
m_vertex_shader.compile();
|
||||
|
||||
m_fragment_shader.shader = fs;
|
||||
m_fragment_shader.id = 100001;
|
||||
m_fragment_shader.Compile();
|
||||
m_fragment_shader.create(::glsl::program_domain::glsl_fragment_program, fs);
|
||||
m_fragment_shader.compile();
|
||||
|
||||
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].module = m_vertex_shader.get_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].module = m_fragment_shader.get_handle();
|
||||
shader_stages[1].pName = "main";
|
||||
|
||||
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
||||
@ -246,6 +244,9 @@ namespace vk
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
m_vertex_shader.destroy();
|
||||
m_fragment_shader.destroy();
|
||||
|
||||
vkDestroyDescriptorSetLayout(device, m_descriptor_layout, nullptr);
|
||||
vkDestroyPipelineLayout(device, m_pipeline_layout, nullptr);
|
||||
m_descriptor_pool.destroy();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "../RSXTexture.h"
|
||||
#include "../rsx_utils.h"
|
||||
#include "VKFormats.h"
|
||||
#include "VKCompute.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
@ -55,24 +56,75 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
void copy_image_typeless(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
std::pair<bool, u32> get_format_convert_flags(VkFormat format)
|
||||
{
|
||||
if (src == dst)
|
||||
switch (format)
|
||||
{
|
||||
copy_image(cmd, src, dst, srcLayout, dstLayout, src_rect, dst_rect, mipmaps, src_aspect, dst_aspect, src_transfer_mask, dst_transfer_mask);
|
||||
//8-bit
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
case VK_FORMAT_R8G8_SNORM:
|
||||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
return{ false, 1 };
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
return{ true, 4 };
|
||||
//16-bit
|
||||
case VK_FORMAT_R16_UINT:
|
||||
case VK_FORMAT_R16_SFLOAT:
|
||||
case VK_FORMAT_R16_UNORM:
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
case VK_FORMAT_R16G16_SFLOAT:
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
|
||||
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
||||
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
|
||||
return{ true, 2 };
|
||||
//32-bit
|
||||
case VK_FORMAT_R32_UINT:
|
||||
case VK_FORMAT_R32_SFLOAT:
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
return{ true, 4 };
|
||||
//DXT
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC2_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC3_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC2_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC3_SRGB_BLOCK:
|
||||
return{ false, 1 };
|
||||
//Depth
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
return{ true, 2 };
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
return{ true, 4 };
|
||||
}
|
||||
|
||||
fmt::throw_exception("Unknown vkFormat 0x%x" HERE, (u32)format);
|
||||
}
|
||||
|
||||
void copy_image_typeless(const vk::command_buffer& cmd, const vk::image* src, const vk::image* dst, const areai& src_rect, const areai& dst_rect,
|
||||
u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect, VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
{
|
||||
if (src->info.format == dst->info.format)
|
||||
{
|
||||
copy_image(cmd, src->value, dst->value, src->current_layout, dst->current_layout, src_rect, dst_rect, mipmaps, src_aspect, dst_aspect, src_transfer_mask, dst_transfer_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
auto preferred_src_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
auto preferred_dst_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
const auto src_layout = src->current_layout;
|
||||
const auto dst_layout = dst->current_layout;
|
||||
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, srcLayout, preferred_src_format, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
if (src->current_layout != preferred_src_format)
|
||||
change_image_layout(cmd, src->value, src_layout, preferred_src_format, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format)
|
||||
change_image_layout(cmd, dst, dstLayout, preferred_dst_format, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
if (dst->current_layout != preferred_dst_format)
|
||||
change_image_layout(cmd, dst->value, dst_layout, preferred_dst_format, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
|
||||
auto scratch_buf = vk::get_scratch_buffer();
|
||||
VkBufferImageCopy src_copy{}, dst_copy{};
|
||||
@ -86,21 +138,69 @@ namespace vk
|
||||
|
||||
for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level)
|
||||
{
|
||||
vkCmdCopyImageToBuffer(cmd, src, preferred_src_format, scratch_buf->value, 1, &src_copy);
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, dst, preferred_dst_format, 1, &dst_copy);
|
||||
vkCmdCopyImageToBuffer(cmd, src->value, preferred_src_format, scratch_buf->value, 1, &src_copy);
|
||||
|
||||
const auto src_convert = get_format_convert_flags(src->info.format);
|
||||
const auto dst_convert = get_format_convert_flags(dst->info.format);
|
||||
|
||||
if (src_convert.first || dst_convert.first)
|
||||
{
|
||||
if (src_convert.first == dst_convert.first &&
|
||||
src_convert.second == dst_convert.second)
|
||||
{
|
||||
// NOP, the two operations will cancel out
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_buffer_memory_barrier(cmd, scratch_buf->value, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||
|
||||
vk::cs_shuffle_base *shuffle_kernel = nullptr;
|
||||
if (src_convert.first && dst_convert.first)
|
||||
{
|
||||
shuffle_kernel = vk::get_compute_task<vk::cs_shuffle_32_16>();
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto block_size = src_convert.first ? src_convert.second : dst_convert.second;
|
||||
if (block_size == 4)
|
||||
{
|
||||
shuffle_kernel = vk::get_compute_task<vk::cs_shuffle_32>();
|
||||
}
|
||||
else if (block_size == 2)
|
||||
{
|
||||
shuffle_kernel = vk::get_compute_task<vk::cs_shuffle_16>();
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Unreachable" HERE);
|
||||
}
|
||||
}
|
||||
|
||||
const auto elem_size = vk::get_format_texel_width(src->info.format);
|
||||
const auto length = elem_size * src_copy.imageExtent.width * src_copy.imageExtent.height;
|
||||
|
||||
shuffle_kernel->run(cmd, scratch_buf, length);
|
||||
|
||||
insert_buffer_memory_barrier(cmd, scratch_buf->value, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, dst->value, preferred_dst_format, 1, &dst_copy);
|
||||
|
||||
src_copy.imageSubresource.mipLevel++;
|
||||
dst_copy.imageSubresource.mipLevel++;
|
||||
}
|
||||
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, preferred_src_format, srcLayout, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
if (src_layout != preferred_src_format)
|
||||
change_image_layout(cmd, src->value, preferred_src_format, src_layout, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format)
|
||||
change_image_layout(cmd, dst, preferred_dst_format, dstLayout, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
if (dst_layout != preferred_dst_format)
|
||||
change_image_layout(cmd, dst->value, preferred_dst_format, dst_layout, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
}
|
||||
|
||||
void copy_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
void copy_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
{
|
||||
@ -150,7 +250,7 @@ namespace vk
|
||||
}
|
||||
|
||||
void copy_scaled_image(VkCommandBuffer cmd,
|
||||
VkImage & src, VkImage & dst,
|
||||
VkImage src, VkImage dst,
|
||||
VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height,
|
||||
u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height,
|
||||
|
@ -1195,8 +1195,7 @@ namespace vk
|
||||
src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint);
|
||||
src_area.x2 = (u16)(src_area.x2 * xfer_info.src_scaling_hint);
|
||||
|
||||
vk::copy_image_typeless(*commands, src->value, real_src->value, src->current_layout, real_src->current_layout,
|
||||
{ 0, 0, (s32)src->width(), (s32)src->height() }, { 0, 0, (s32)internal_width, (s32)src->height() }, 1,
|
||||
vk::copy_image_typeless(*commands, src, real_src, { 0, 0, (s32)src->width(), (s32)src->height() }, { 0, 0, (s32)internal_width, (s32)src->height() }, 1,
|
||||
vk::get_aspect_flags(src->info.format), vk::get_aspect_flags(format));
|
||||
}
|
||||
|
||||
@ -1210,8 +1209,7 @@ namespace vk
|
||||
dst_area.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint);
|
||||
dst_area.x2 = (u16)(dst_area.x2 * xfer_info.dst_scaling_hint);
|
||||
|
||||
vk::copy_image_typeless(*commands, dst->value, real_dst->value, dst->current_layout, real_dst->current_layout,
|
||||
{ 0, 0, (s32)dst->width(), (s32)dst->height() }, { 0, 0, (s32)internal_width, (s32)dst->height() }, 1,
|
||||
vk::copy_image_typeless(*commands, dst, real_dst, { 0, 0, (s32)dst->width(), (s32)dst->height() }, { 0, 0, (s32)internal_width, (s32)dst->height() }, 1,
|
||||
vk::get_aspect_flags(dst->info.format), vk::get_aspect_flags(format));
|
||||
}
|
||||
|
||||
@ -1246,8 +1244,7 @@ namespace vk
|
||||
if (real_dst != dst)
|
||||
{
|
||||
auto internal_width = dst->width() * xfer_info.dst_scaling_hint;
|
||||
vk::copy_image_typeless(*commands, real_dst->value, dst->value, real_dst->current_layout, dst->current_layout,
|
||||
{ 0, 0, (s32)internal_width, (s32)dst->height() }, { 0, 0, (s32)dst->width(), (s32)dst->height() }, 1,
|
||||
vk::copy_image_typeless(*commands, real_dst, dst, { 0, 0, (s32)internal_width, (s32)dst->height() }, { 0, 0, (s32)dst->width(), (s32)dst->height() }, 1,
|
||||
vk::get_aspect_flags(real_dst->info.format), vk::get_aspect_flags(dst->info.format));
|
||||
}
|
||||
|
||||
|
@ -336,41 +336,23 @@ VKVertexProgram::~VKVertexProgram()
|
||||
|
||||
void VKVertexProgram::Decompile(const RSXVertexProgram& prog)
|
||||
{
|
||||
VKVertexDecompilerThread decompiler(prog, shader, parr, *this);
|
||||
std::string source;
|
||||
VKVertexDecompilerThread decompiler(prog, source, parr, *this);
|
||||
decompiler.Task();
|
||||
|
||||
shader.create(::glsl::program_domain::glsl_vertex_program, source);
|
||||
}
|
||||
|
||||
void VKVertexProgram::Compile()
|
||||
{
|
||||
fs::create_path(fs::get_config_dir() + "/shaderlog");
|
||||
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
|
||||
|
||||
std::vector<u32> spir_v;
|
||||
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_vertex_program, spir_v))
|
||||
fmt::throw_exception("Failed to compile vertex shader" HERE);
|
||||
|
||||
VkShaderModuleCreateInfo vs_info;
|
||||
vs_info.codeSize = spir_v.size() * sizeof(u32);
|
||||
vs_info.pNext = nullptr;
|
||||
vs_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
vs_info.pCode = (uint32_t*)spir_v.data();
|
||||
vs_info.flags = 0;
|
||||
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkCreateShaderModule(dev, &vs_info, nullptr, &handle);
|
||||
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source());
|
||||
handle = shader.compile();
|
||||
}
|
||||
|
||||
void VKVertexProgram::Delete()
|
||||
{
|
||||
shader.clear();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkDestroyShaderModule(dev, handle, nullptr);
|
||||
|
||||
handle = nullptr;
|
||||
}
|
||||
shader.destroy();
|
||||
}
|
||||
|
||||
void VKVertexProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
ParamArray parr;
|
||||
VkShaderModule handle = nullptr;
|
||||
u32 id;
|
||||
std::string shader;
|
||||
vk::glsl::shader shader;
|
||||
std::vector<vk::glsl::program_input> uniforms;
|
||||
|
||||
void Decompile(const RSXVertexProgram& prog);
|
||||
|
@ -24,6 +24,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKCompute.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKFormats.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKGSRender.h" />
|
||||
|
@ -43,6 +43,9 @@
|
||||
<ClInclude Include="Emu\RSX\VK\VKOverlays.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\VK\VKCompute.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user