1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-01-31 20:41: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:
kd-11 2018-06-12 18:46:59 +03:00 committed by kd-11
parent 0d5c071eee
commit 2afcf369ec
17 changed files with 568 additions and 129 deletions

View File

@ -83,7 +83,8 @@ namespace glsl
enum program_domain enum program_domain
{ {
glsl_vertex_program = 0, glsl_vertex_program = 0,
glsl_fragment_program = 1 glsl_fragment_program = 1,
glsl_compute_program = 2
}; };
enum glsl_rules enum glsl_rules

View File

@ -140,7 +140,8 @@ namespace vk
bool compile_glsl_to_spv(std::string& shader, program_domain domain, std::vector<u32>& spv) 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::TProgram program;
glslang::TShader shader_object(lang); glslang::TShader shader_object(lang);

View 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();
}

View File

@ -362,8 +362,11 @@ VKFragmentProgram::~VKFragmentProgram()
void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog) void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
{ {
u32 size; u32 size;
VKFragmentDecompilerThread decompiler(shader, parr, prog, size, *this); std::string source;
VKFragmentDecompilerThread decompiler(source, parr, prog, size, *this);
decompiler.Task(); decompiler.Task();
shader.create(::glsl::program_domain::glsl_fragment_program, source);
for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM]) for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM])
{ {
@ -384,34 +387,13 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
void VKFragmentProgram::Compile() void VKFragmentProgram::Compile()
{ {
fs::create_path(fs::get_config_dir() + "/shaderlog"); 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); fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source());
handle = shader.compile();
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);
} }
void VKFragmentProgram::Delete() void VKFragmentProgram::Delete()
{ {
shader.clear(); shader.destroy();
if (handle)
{
VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkDestroyShaderModule(dev, handle, NULL);
handle = nullptr;
}
} }
void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs) void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)

View File

@ -49,7 +49,7 @@ public:
ParamArray parr; ParamArray parr;
VkShaderModule handle = nullptr; VkShaderModule handle = nullptr;
u32 id; u32 id;
std::string shader; vk::glsl::shader shader;
std::vector<size_t> FragmentConstantOffsetCache; std::vector<size_t> FragmentConstantOffsetCache;
std::array<u32, 4> output_color_masks{ {} }; std::array<u32, 4> output_color_masks{ {} };

View File

@ -2024,6 +2024,8 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources)
m_overlay_manager->dispose(uids_to_dispose); m_overlay_manager->dispose(uids_to_dispose);
} }
vk::reset_compute_tasks();
m_attachment_clear_pass->free_resources(); m_attachment_clear_pass->free_resources();
m_depth_converter->free_resources(); m_depth_converter->free_resources();
m_ui_renderer->free_resources(); m_ui_renderer->free_resources();

View File

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "VKHelpers.h" #include "VKHelpers.h"
#include "VKCompute.h"
#include "Utilities/mutex.h" #include "Utilities/mutex.h"
namespace vk namespace vk
@ -11,6 +12,7 @@ namespace vk
std::unique_ptr<image_view> g_null_image_view; std::unique_ptr<image_view> g_null_image_view;
std::unique_ptr<buffer> g_scratch_buffer; 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<image>> g_typeless_textures;
std::unordered_map<u32, std::unique_ptr<vk::compute_task>> g_compute_tasks;
VkSampler g_null_sampler = nullptr; VkSampler g_null_sampler = nullptr;
@ -195,7 +197,7 @@ namespace vk
// 32M disposable scratch memory // 32M disposable scratch memory
g_scratch_buffer = std::make_unique<vk::buffer>(*g_current_renderer, 32 * 0x100000, 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, 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(); return g_scratch_buffer.get();
@ -211,6 +213,14 @@ namespace vk
g_submit_mutex.unlock(); g_submit_mutex.unlock();
} }
void reset_compute_tasks()
{
for (const auto &p : g_compute_tasks)
{
p.second->free_resources();
}
}
void destroy_global_resources() void destroy_global_resources()
{ {
g_null_texture.reset(); g_null_texture.reset();
@ -223,6 +233,13 @@ namespace vk
vkDestroySampler(*g_current_renderer, g_null_sampler, nullptr); vkDestroySampler(*g_current_renderer, g_null_sampler, nullptr);
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() vk::mem_allocator_base* get_current_mem_allocator()
@ -330,6 +347,21 @@ namespace vk
return g_drv_disable_fence_reset; 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) void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
{ {
//Prepare an image to match the new layout.. //Prepare an image to match the new layout..

View File

@ -13,10 +13,10 @@
#include "Emu/RSX/GSRender.h" #include "Emu/RSX/GSRender.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "VulkanAPI.h" #include "VulkanAPI.h"
#include "VKCommonDecompiler.h"
#include "../GCM.h" #include "../GCM.h"
#include "../Common/TextureUtils.h" #include "../Common/TextureUtils.h"
#include "../Common/ring_buffer_helper.h" #include "../Common/ring_buffer_helper.h"
#include "../Common/GLSLCommon.h"
#include "../rsx_cache.h" #include "../rsx_cache.h"
#include "3rdparty/GPUOpen/include/vk_mem_alloc.h" #include "3rdparty/GPUOpen/include/vk_mem_alloc.h"
@ -110,6 +110,10 @@ namespace vk
void acquire_global_submit_lock(); void acquire_global_submit_lock();
void release_global_submit_lock(); void release_global_submit_lock();
template<class T>
T* get_compute_task();
void reset_compute_tasks();
void destroy_global_resources(); 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, VkImageSubresourceRange range);
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout); 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, void copy_image_typeless(const command_buffer &cmd, const image *src, const image *dst, const areai& src_rect, const areai& dst_rect,
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF); 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, 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); 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, 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); 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, VkImage image, VkImageLayout layout, VkImageSubresourceRange range);
void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image); 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 //Manage 'uininterruptible' state where secondary operations (e.g violation handlers) will have to wait
void enter_uninterruptible(); void enter_uninterruptible();
void leave_uninterruptible(); void leave_uninterruptible();
@ -1021,7 +1027,7 @@ namespace vk
return *pool; return *pool;
} }
operator VkCommandBuffer() operator VkCommandBuffer() const
{ {
return commands; return commands;
} }
@ -2116,13 +2122,13 @@ public:
class descriptor_pool class descriptor_pool
{ {
VkDescriptorPool pool = nullptr; VkDescriptorPool pool = nullptr;
vk::render_device *owner = nullptr; const vk::render_device *owner = nullptr;
public: public:
descriptor_pool() {} descriptor_pool() {}
~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 = {}; VkDescriptorPoolCreateInfo infos = {};
infos.flags = 0; infos.flags = 0;
@ -2426,7 +2432,8 @@ public:
{ {
input_type_uniform_buffer = 0, input_type_uniform_buffer = 0,
input_type_texel_buffer = 1, input_type_texel_buffer = 1,
input_type_texture = 2 input_type_texture = 2,
input_type_storage_buffer = 3
}; };
struct bound_sampler struct bound_sampler
@ -2456,6 +2463,80 @@ public:
std::string name; 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 class program
{ {
std::vector<program_input> uniforms; std::vector<program_input> uniforms;
@ -2473,10 +2554,12 @@ public:
program& load_uniforms(::glsl::program_domain domain, const std::vector<program_input>& inputs); program& load_uniforms(::glsl::program_domain domain, const std::vector<program_input>& inputs);
bool has_uniform(std::string uniform_name); bool has_uniform(std::string uniform_name);
void bind_uniform(VkDescriptorImageInfo image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set); void bind_uniform(const 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 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_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(); u64 get_vertex_input_attributes_mask();
}; };
} }

View File

@ -11,8 +11,8 @@ namespace vk
//TODO: Refactor text print class to inherit from this base class //TODO: Refactor text print class to inherit from this base class
struct overlay_pass struct overlay_pass
{ {
VKVertexProgram m_vertex_shader; vk::glsl::shader m_vertex_shader;
VKFragmentProgram m_fragment_shader; vk::glsl::shader m_fragment_shader;
vk::descriptor_pool m_descriptor_pool; vk::descriptor_pool m_descriptor_pool;
VkDescriptorSet m_descriptor_set = nullptr; VkDescriptorSet m_descriptor_set = nullptr;
@ -149,11 +149,11 @@ namespace vk
{ {
if (!compiled) if (!compiled)
{ {
m_vertex_shader.shader = vs_src; m_vertex_shader.create(::glsl::program_domain::glsl_vertex_program, vs_src);
m_vertex_shader.Compile(); m_vertex_shader.compile();
m_fragment_shader.shader = fs_src; m_fragment_shader.create(::glsl::program_domain::glsl_fragment_program, fs_src);
m_fragment_shader.Compile(); m_fragment_shader.compile();
compiled = true; compiled = true;
} }
@ -161,12 +161,12 @@ namespace vk
VkPipelineShaderStageCreateInfo shader_stages[2] = {}; VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 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[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 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"; shader_stages[1].pName = "main";
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
@ -282,6 +282,8 @@ namespace vk
{ {
if (initialized) if (initialized)
{ {
m_vertex_shader.destroy();
m_fragment_shader.destroy();
m_program_cache.clear(); m_program_cache.clear();
m_sampler.reset(); m_sampler.reset();
@ -434,9 +436,6 @@ namespace vk
renderpass_config.set_depth_mask(true); renderpass_config.set_depth_mask(true);
renderpass_config.enable_depth_test(VK_COMPARE_OP_ALWAYS); 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); 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_SRC_ALPHA, VK_BLEND_FACTOR_SRC_ALPHA,
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
VK_BLEND_OP_ADD, VK_BLEND_OP_ADD); 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, 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_depth_mask(false);
renderpass_config.set_color_mask(true, true, true, true); renderpass_config.set_color_mask(true, true, true, true);
renderpass_config.set_attachment_count(1); renderpass_config.set_attachment_count(1);
m_vertex_shader.id = 100006;
m_fragment_shader.id = 100007;
} }
void update_uniforms(vk::glsl::program* /*program*/) override void update_uniforms(vk::glsl::program* /*program*/) override

View File

@ -48,7 +48,7 @@ namespace vk
return false; 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) for (auto &uniform : uniforms)
{ {
@ -72,19 +72,9 @@ namespace vk
LOG_NOTICE(RSX, "texture not found in program: %s", uniform_name.c_str()); 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 = {}; bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set);
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);
} }
void program::bind_uniform(const VkBufferView &buffer_view, const std::string &binding_name, VkDescriptorSet &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()); 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() u64 program::get_vertex_input_attributes_mask()
{ {
if (vertex_attributes_mask) if (vertex_attributes_mask)

View File

@ -13,8 +13,8 @@ namespace vk
std::unique_ptr<vk::buffer> m_uniforms_buffer; std::unique_ptr<vk::buffer> m_uniforms_buffer;
std::unique_ptr<vk::glsl::program> m_program; std::unique_ptr<vk::glsl::program> m_program;
VKVertexProgram m_vertex_shader; vk::glsl::shader m_vertex_shader;
VKFragmentProgram m_fragment_shader; vk::glsl::shader m_fragment_shader;
vk::descriptor_pool m_descriptor_pool; vk::descriptor_pool m_descriptor_pool;
VkDescriptorSet m_descriptor_set = nullptr; VkDescriptorSet m_descriptor_set = nullptr;
@ -102,23 +102,21 @@ namespace vk
"}\n" "}\n"
}; };
m_vertex_shader.shader = vs; m_vertex_shader.create(::glsl::program_domain::glsl_vertex_program, vs);
m_vertex_shader.id = 100000; m_vertex_shader.compile();
m_vertex_shader.Compile();
m_fragment_shader.shader = fs; m_fragment_shader.create(::glsl::program_domain::glsl_fragment_program, fs);
m_fragment_shader.id = 100001; m_fragment_shader.compile();
m_fragment_shader.Compile();
VkPipelineShaderStageCreateInfo shader_stages[2] = {}; VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 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[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 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"; shader_stages[1].pName = "main";
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
@ -246,6 +244,9 @@ namespace vk
{ {
if (initialized) if (initialized)
{ {
m_vertex_shader.destroy();
m_fragment_shader.destroy();
vkDestroyDescriptorSetLayout(device, m_descriptor_layout, nullptr); vkDestroyDescriptorSetLayout(device, m_descriptor_layout, nullptr);
vkDestroyPipelineLayout(device, m_pipeline_layout, nullptr); vkDestroyPipelineLayout(device, m_pipeline_layout, nullptr);
m_descriptor_pool.destroy(); m_descriptor_pool.destroy();

View File

@ -5,6 +5,7 @@
#include "../RSXTexture.h" #include "../RSXTexture.h"
#include "../rsx_utils.h" #include "../rsx_utils.h"
#include "VKFormats.h" #include "VKFormats.h"
#include "VKCompute.h"
namespace vk namespace vk
{ {
@ -55,24 +56,75 @@ namespace vk
} }
} }
void copy_image_typeless(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, std::pair<bool, u32> get_format_convert_flags(VkFormat format)
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 == 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; return;
} }
auto preferred_src_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; 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; 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) if (src->current_layout != preferred_src_format)
change_image_layout(cmd, src, srcLayout, preferred_src_format, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect)); 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) if (dst->current_layout != preferred_dst_format)
change_image_layout(cmd, dst, dstLayout, preferred_dst_format, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect)); 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(); auto scratch_buf = vk::get_scratch_buffer();
VkBufferImageCopy src_copy{}, dst_copy{}; VkBufferImageCopy src_copy{}, dst_copy{};
@ -86,21 +138,69 @@ namespace vk
for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level) for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level)
{ {
vkCmdCopyImageToBuffer(cmd, src, preferred_src_format, scratch_buf->value, 1, &src_copy); vkCmdCopyImageToBuffer(cmd, src->value, preferred_src_format, scratch_buf->value, 1, &src_copy);
vkCmdCopyBufferToImage(cmd, scratch_buf->value, dst, preferred_dst_format, 1, &dst_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++; src_copy.imageSubresource.mipLevel++;
dst_copy.imageSubresource.mipLevel++; dst_copy.imageSubresource.mipLevel++;
} }
if (srcLayout != preferred_src_format) if (src_layout != preferred_src_format)
change_image_layout(cmd, src, preferred_src_format, srcLayout, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect)); 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) if (dst_layout != preferred_dst_format)
change_image_layout(cmd, dst, preferred_dst_format, dstLayout, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect)); 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, const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask) VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
{ {
@ -150,7 +250,7 @@ namespace vk
} }
void copy_scaled_image(VkCommandBuffer cmd, void copy_scaled_image(VkCommandBuffer cmd,
VkImage & src, VkImage & dst, VkImage src, VkImage dst,
VkImageLayout srcLayout, VkImageLayout dstLayout, VkImageLayout srcLayout, VkImageLayout dstLayout,
u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, 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 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height,

View File

@ -1195,8 +1195,7 @@ namespace vk
src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint); src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint);
src_area.x2 = (u16)(src_area.x2 * 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, 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,
{ 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)); 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.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint);
dst_area.x2 = (u16)(dst_area.x2 * 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, 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,
{ 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)); vk::get_aspect_flags(dst->info.format), vk::get_aspect_flags(format));
} }
@ -1246,8 +1244,7 @@ namespace vk
if (real_dst != dst) if (real_dst != dst)
{ {
auto internal_width = dst->width() * xfer_info.dst_scaling_hint; 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, 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,
{ 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)); vk::get_aspect_flags(real_dst->info.format), vk::get_aspect_flags(dst->info.format));
} }

View File

@ -336,41 +336,23 @@ VKVertexProgram::~VKVertexProgram()
void VKVertexProgram::Decompile(const RSXVertexProgram& prog) void VKVertexProgram::Decompile(const RSXVertexProgram& prog)
{ {
VKVertexDecompilerThread decompiler(prog, shader, parr, *this); std::string source;
VKVertexDecompilerThread decompiler(prog, source, parr, *this);
decompiler.Task(); decompiler.Task();
shader.create(::glsl::program_domain::glsl_vertex_program, source);
} }
void VKVertexProgram::Compile() void VKVertexProgram::Compile()
{ {
fs::create_path(fs::get_config_dir() + "/shaderlog"); 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); fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source());
handle = shader.compile();
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);
} }
void VKVertexProgram::Delete() void VKVertexProgram::Delete()
{ {
shader.clear(); shader.destroy();
if (handle)
{
VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkDestroyShaderModule(dev, handle, nullptr);
handle = nullptr;
}
} }
void VKVertexProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs) void VKVertexProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)

View File

@ -46,7 +46,7 @@ public:
ParamArray parr; ParamArray parr;
VkShaderModule handle = nullptr; VkShaderModule handle = nullptr;
u32 id; u32 id;
std::string shader; vk::glsl::shader shader;
std::vector<vk::glsl::program_input> uniforms; std::vector<vk::glsl::program_input> uniforms;
void Decompile(const RSXVertexProgram& prog); void Decompile(const RSXVertexProgram& prog);

View File

@ -24,6 +24,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" /> <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\VKFormats.h" />
<ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" /> <ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" />
<ClInclude Include="Emu\RSX\VK\VKGSRender.h" /> <ClInclude Include="Emu\RSX\VK\VKGSRender.h" />

View File

@ -43,6 +43,9 @@
<ClInclude Include="Emu\RSX\VK\VKOverlays.h"> <ClInclude Include="Emu\RSX\VK\VKOverlays.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\RSX\VK\VKCompute.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp"> <ClCompile Include="Emu\RSX\VK\VKGSRender.cpp">