(shader vulkan) Cleanups - moving C code out of the C++ file

This commit is contained in:
twinaphex 2020-01-22 10:11:42 +01:00
parent d4a1f2ef85
commit ef27a660a7
5 changed files with 290 additions and 270 deletions

View File

@ -3175,3 +3175,37 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
return true; return true;
} }
void vulkan_initialize_render_pass(VkDevice device, VkFormat format,
VkRenderPass *render_pass)
{
VkRenderPassCreateInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
VkAttachmentReference color_ref = { 0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
VkAttachmentDescription attachment = {0};
VkSubpassDescription subpass = {0};
/* We will always write to the entire framebuffer,
* so we don't really need to clear. */
attachment.format = format;
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
rp_info.attachmentCount = 1;
rp_info.pAttachments = &attachment;
rp_info.subpassCount = 1;
rp_info.pSubpasses = &subpass;
vkCreateRenderPass(device, &rp_info, NULL, render_pass);
}

View File

@ -592,6 +592,9 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
unsigned width, unsigned height, unsigned width, unsigned height,
unsigned swap_interval); unsigned swap_interval);
void vulkan_initialize_render_pass(VkDevice device,
VkFormat format, VkRenderPass *render_pass);
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@ -85,10 +85,10 @@ static void vulkan_init_render_pass(
{ {
VkRenderPassCreateInfo rp_info = { VkRenderPassCreateInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
VkAttachmentDescription attachment = {0};
VkSubpassDescription subpass = {0};
VkAttachmentReference color_ref = { 0, VkAttachmentReference color_ref = { 0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
VkAttachmentDescription attachment = {0};
VkSubpassDescription subpass = {0};
/* Backbuffer format. */ /* Backbuffer format. */
attachment.format = vk->context->swapchain_format; attachment.format = vk->context->swapchain_format;

View File

@ -129,26 +129,6 @@ struct Texture
vulkan_filter_chain_address address; vulkan_filter_chain_address address;
}; };
static vulkan_filter_chain_address wrap_to_address(gfx_wrap_type type)
{
switch (type)
{
case RARCH_WRAP_BORDER:
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER;
case RARCH_WRAP_REPEAT:
return VULKAN_FILTER_CHAIN_ADDRESS_REPEAT;
case RARCH_WRAP_MIRRORED_REPEAT:
return VULKAN_FILTER_CHAIN_ADDRESS_MIRRORED_REPEAT;
case RARCH_WRAP_EDGE:
default:
break;
}
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE;
}
class DeferredDisposer class DeferredDisposer
{ {
public: public:
@ -263,14 +243,14 @@ class Framebuffer
void generate_mips(VkCommandBuffer cmd); void generate_mips(VkCommandBuffer cmd);
private: private:
const VkPhysicalDeviceMemoryProperties &memory_properties;
VkDevice device = VK_NULL_HANDLE;
VkImage image = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkImageView fb_view = VK_NULL_HANDLE;
Size2D size; Size2D size;
VkFormat format; VkFormat format;
unsigned max_levels; unsigned max_levels;
const VkPhysicalDeviceMemoryProperties &memory_properties;
VkDevice device = VK_NULL_HANDLE;
VkImage image = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkImageView fb_view = VK_NULL_HANDLE;
unsigned levels = 0; unsigned levels = 0;
VkFramebuffer framebuffer = VK_NULL_HANDLE; VkFramebuffer framebuffer = VK_NULL_HANDLE;
@ -278,14 +258,12 @@ class Framebuffer
struct struct
{ {
size_t size = 0; size_t size = 0;
uint32_t type = 0; uint32_t type = 0;
VkDeviceMemory memory = VK_NULL_HANDLE; VkDeviceMemory memory = VK_NULL_HANDLE;
} memory; } memory;
void init(DeferredDisposer *disposer); void init(DeferredDisposer *disposer);
void init_framebuffer();
void init_render_pass();
}; };
struct CommonResources struct CommonResources
@ -296,10 +274,10 @@ struct CommonResources
unique_ptr<Buffer> vbo; unique_ptr<Buffer> vbo;
unique_ptr<Buffer> ubo; unique_ptr<Buffer> ubo;
uint8_t *ubo_mapped = nullptr; uint8_t *ubo_mapped = nullptr;
size_t ubo_sync_index_stride = 0; size_t ubo_sync_index_stride = 0;
size_t ubo_offset = 0; size_t ubo_offset = 0;
size_t ubo_alignment = 1; size_t ubo_alignment = 1;
VkSampler samplers[VULKAN_FILTER_CHAIN_COUNT][VULKAN_FILTER_CHAIN_COUNT][VULKAN_FILTER_CHAIN_ADDRESS_COUNT]; VkSampler samplers[VULKAN_FILTER_CHAIN_COUNT][VULKAN_FILTER_CHAIN_COUNT][VULKAN_FILTER_CHAIN_ADDRESS_COUNT];
@ -1192,23 +1170,25 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
if (!image_texture_load(&image, shader->path)) if (!image_texture_load(&image, shader->path))
return {}; return {};
image_info.imageType = VK_IMAGE_TYPE_2D; image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.format = VK_FORMAT_B8G8R8A8_UNORM; image_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_info.extent.width = image.width; image_info.extent.width = image.width;
image_info.extent.height = image.height; image_info.extent.height = image.height;
image_info.extent.depth = 1; image_info.extent.depth = 1;
image_info.mipLevels = shader->mipmap ? num_miplevels(image.width, image.height) : 1; image_info.mipLevels = shader->mipmap ? num_miplevels(image.width, image.height) : 1;
image_info.arrayLayers = 1; image_info.arrayLayers = 1;
image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT; VK_IMAGE_USAGE_TRANSFER_DST_BIT;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkCreateImage(info->device, &image_info, nullptr, &tex); vkCreateImage(info->device, &image_info, nullptr, &tex);
vkGetImageMemoryRequirements(info->device, tex, &mem_reqs); vkGetImageMemoryRequirements(info->device, tex, &mem_reqs);
alloc.allocationSize = mem_reqs.size;
alloc.memoryTypeIndex = vulkan_find_memory_type( alloc.allocationSize = mem_reqs.size;
alloc.memoryTypeIndex = vulkan_find_memory_type(
&*info->memory_properties, &*info->memory_properties,
mem_reqs.memoryTypeBits, mem_reqs.memoryTypeBits,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
@ -1230,9 +1210,10 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
view_info.subresourceRange.layerCount = 1; view_info.subresourceRange.layerCount = 1;
vkCreateImageView(info->device, &view_info, nullptr, &view); vkCreateImageView(info->device, &view_info, nullptr, &view);
buffer = unique_ptr<Buffer>(new Buffer(info->device, *info->memory_properties, buffer =
image.width * image.height * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT)); unique_ptr<Buffer>(new Buffer(info->device, *info->memory_properties,
ptr = buffer->map(); image.width * image.height * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
ptr = buffer->map();
memcpy(ptr, image.pixels, image.width * image.height * sizeof(uint32_t)); memcpy(ptr, image.pixels, image.width * image.height * sizeof(uint32_t));
buffer->unmap(); buffer->unmap();
@ -1242,13 +1223,13 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
0, VK_ACCESS_TRANSFER_WRITE_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0; region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageExtent.width = image.width; region.imageExtent.width = image.width;
region.imageExtent.height = image.height; region.imageExtent.height = image.height;
region.imageExtent.depth = 1; region.imageExtent.depth = 1;
vkCmdCopyBufferToImage(cmd, buffer->get_buffer(), tex, vkCmdCopyBufferToImage(cmd, buffer->get_buffer(), tex,
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@ -1256,11 +1237,11 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
for (i = 1; i < image_info.mipLevels; i++) for (i = 1; i < image_info.mipLevels; i++)
{ {
VkImageBlit blit_region = {}; VkImageBlit blit_region = {};
unsigned src_width = MAX(image.width >> (i - 1), 1u); unsigned src_width = MAX(image.width >> (i - 1), 1u);
unsigned src_height = MAX(image.height >> (i - 1), 1u); unsigned src_height = MAX(image.height >> (i - 1), 1u);
unsigned target_width = MAX(image.width >> i, 1u); unsigned target_width = MAX(image.width >> i, 1u);
unsigned target_height = MAX(image.height >> i, 1u); unsigned target_height = MAX(image.height >> i, 1u);
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit_region.srcSubresource.mipLevel = i - 1; blit_region.srcSubresource.mipLevel = i - 1;
@ -1304,7 +1285,7 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
tex, view, memory, move(buffer), image.width, image.height, tex, view, memory, move(buffer), image.width, image.height,
shader->filter != RARCH_FILTER_NEAREST, shader->filter != RARCH_FILTER_NEAREST,
image_info.mipLevels > 1, image_info.mipLevels > 1,
wrap_to_address(shader->wrap))); vk_wrap_to_address(shader->wrap)));
error: error:
if (image.pixels) if (image.pixels)
@ -1318,9 +1299,6 @@ error:
return {}; return {};
} }
static bool vulkan_filter_chain_load_luts( static bool vulkan_filter_chain_load_luts(
const struct vulkan_filter_chain_create_info *info, const struct vulkan_filter_chain_create_info *info,
vulkan_filter_chain *chain, vulkan_filter_chain *chain,
@ -1374,8 +1352,6 @@ error:
return false; return false;
} }
StaticTexture::StaticTexture(string id, StaticTexture::StaticTexture(string id,
VkDevice device, VkDevice device,
VkImage image, VkImage image,
@ -1393,15 +1369,19 @@ StaticTexture::StaticTexture(string id,
buffer(move(buffer)), buffer(move(buffer)),
id(move(id)) id(move(id))
{ {
texture.filter = linear ? VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST; texture.filter = VULKAN_FILTER_CHAIN_NEAREST;
texture.mip_filter = texture.mip_filter = VULKAN_FILTER_CHAIN_NEAREST;
mipmap && linear ? VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST; texture.address = address;
texture.address = address; texture.texture.image = image;
texture.texture.image = image; texture.texture.view = view;
texture.texture.view = view;
texture.texture.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; texture.texture.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
texture.texture.width = width; texture.texture.width = width;
texture.texture.height = height; texture.texture.height = height;
if (linear)
texture.filter = VULKAN_FILTER_CHAIN_LINEAR;
if (mipmap && linear)
texture.mip_filter = VULKAN_FILTER_CHAIN_LINEAR;
} }
StaticTexture::~StaticTexture() StaticTexture::~StaticTexture()
@ -1420,17 +1400,17 @@ Buffer::Buffer(VkDevice device,
device(device), size(size) device(device), size(size)
{ {
VkMemoryRequirements mem_reqs; VkMemoryRequirements mem_reqs;
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
info.size = size; VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
info.usage = usage;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.size = size;
info.usage = usage;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(device, &info, nullptr, &buffer); vkCreateBuffer(device, &info, nullptr, &buffer);
vkGetBufferMemoryRequirements(device, buffer, &mem_reqs); vkGetBufferMemoryRequirements(device, buffer, &mem_reqs);
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
alloc.allocationSize = mem_reqs.size; alloc.allocationSize = mem_reqs.size;
alloc.memoryTypeIndex = vulkan_find_memory_type( alloc.memoryTypeIndex = vulkan_find_memory_type(
&mem_props, mem_reqs.memoryTypeBits, &mem_props, mem_reqs.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
@ -1444,9 +1424,8 @@ void *Buffer::map()
{ {
if (!mapped) if (!mapped)
{ {
if (vkMapMemory(device, memory, 0, size, 0, &mapped) == VK_SUCCESS) if (vkMapMemory(device, memory, 0, size, 0, &mapped) != VK_SUCCESS)
return mapped; return nullptr;
return nullptr;
} }
return mapped; return mapped;
} }
@ -1482,17 +1461,20 @@ void Pass::set_shader(VkShaderStageFlags stage,
const uint32_t *spirv, const uint32_t *spirv,
size_t spirv_words) size_t spirv_words)
{ {
if (stage == VK_SHADER_STAGE_VERTEX_BIT) switch (stage)
{ {
vertex_shader.clear(); case VK_SHADER_STAGE_VERTEX_BIT:
vertex_shader.insert(end(vertex_shader), vertex_shader.clear();
spirv, spirv + spirv_words); vertex_shader.insert(end(vertex_shader),
} spirv, spirv + spirv_words);
else if (stage == VK_SHADER_STAGE_FRAGMENT_BIT) break;
{ case VK_SHADER_STAGE_FRAGMENT_BIT:
fragment_shader.clear(); fragment_shader.clear();
fragment_shader.insert(end(fragment_shader), fragment_shader.insert(end(fragment_shader),
spirv, spirv + spirv_words); spirv, spirv + spirv_words);
break;
default:
break;
} }
} }
@ -1555,14 +1537,15 @@ Size2D Pass::set_pass_info(
{ {
clear_vk(); clear_vk();
current_viewport = swapchain.viewport; current_viewport = swapchain.viewport;
pass_info = info; pass_info = info;
num_sync_indices = swapchain.num_indices; num_sync_indices = swapchain.num_indices;
sync_index = 0; sync_index = 0;
current_framebuffer_size = get_output_size(max_original, max_source); current_framebuffer_size = get_output_size(max_original, max_source);
swapchain_render_pass = swapchain.render_pass; swapchain_render_pass = swapchain.render_pass;
return current_framebuffer_size; return current_framebuffer_size;
} }
@ -1587,9 +1570,19 @@ bool Pass::init_pipeline_layout()
unsigned i; unsigned i;
vector<VkDescriptorSetLayoutBinding> bindings; vector<VkDescriptorSetLayoutBinding> bindings;
vector<VkDescriptorPoolSize> desc_counts; vector<VkDescriptorPoolSize> desc_counts;
VkPushConstantRange push_range = {};
VkDescriptorSetLayoutCreateInfo set_layout_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
VkPipelineLayoutCreateInfo layout_info = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
VkDescriptorPoolCreateInfo pool_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
VkDescriptorSetAllocateInfo alloc_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
/* Main UBO. */ /* Main UBO. */
VkShaderStageFlags ubo_mask = 0; VkShaderStageFlags ubo_mask = 0;
if (reflection.ubo_stage_mask & SLANG_STAGE_VERTEX_MASK) if (reflection.ubo_stage_mask & SLANG_STAGE_VERTEX_MASK)
ubo_mask |= VK_SHADER_STAGE_VERTEX_BIT; ubo_mask |= VK_SHADER_STAGE_VERTEX_BIT;
if (reflection.ubo_stage_mask & SLANG_STAGE_FRAGMENT_MASK) if (reflection.ubo_stage_mask & SLANG_STAGE_FRAGMENT_MASK)
@ -1608,10 +1601,11 @@ bool Pass::init_pipeline_layout()
{ {
for (auto &texture : semantic) for (auto &texture : semantic)
{ {
VkShaderStageFlags stages = 0;
if (!texture.texture) if (!texture.texture)
continue; continue;
VkShaderStageFlags stages = 0;
if (texture.stage_mask & SLANG_STAGE_VERTEX_MASK) if (texture.stage_mask & SLANG_STAGE_VERTEX_MASK)
stages |= VK_SHADER_STAGE_VERTEX_BIT; stages |= VK_SHADER_STAGE_VERTEX_BIT;
if (texture.stage_mask & SLANG_STAGE_FRAGMENT_MASK) if (texture.stage_mask & SLANG_STAGE_FRAGMENT_MASK)
@ -1624,22 +1618,17 @@ bool Pass::init_pipeline_layout()
} }
} }
VkDescriptorSetLayoutCreateInfo set_layout_info = { set_layout_info.bindingCount = bindings.size();
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; set_layout_info.pBindings = bindings.data();
set_layout_info.bindingCount = bindings.size();
set_layout_info.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(device, if (vkCreateDescriptorSetLayout(device,
&set_layout_info, NULL, &set_layout) != VK_SUCCESS) &set_layout_info, NULL, &set_layout) != VK_SUCCESS)
return false; return false;
VkPipelineLayoutCreateInfo layout_info = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
layout_info.setLayoutCount = 1; layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = &set_layout; layout_info.pSetLayouts = &set_layout;
/* Push constants */ /* Push constants */
VkPushConstantRange push_range = {};
if (reflection.push_constant_stage_mask && reflection.push_constant_size) if (reflection.push_constant_stage_mask && reflection.push_constant_size)
{ {
if (reflection.push_constant_stage_mask & SLANG_STAGE_VERTEX_MASK) if (reflection.push_constant_stage_mask & SLANG_STAGE_VERTEX_MASK)
@ -1650,27 +1639,23 @@ bool Pass::init_pipeline_layout()
RARCH_LOG("[Vulkan]: Push Constant Block: %u bytes.\n", (unsigned int)reflection.push_constant_size); RARCH_LOG("[Vulkan]: Push Constant Block: %u bytes.\n", (unsigned int)reflection.push_constant_size);
layout_info.pushConstantRangeCount = 1; layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = &push_range; layout_info.pPushConstantRanges = &push_range;
push.buffer.resize((reflection.push_constant_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)); push.buffer.resize((reflection.push_constant_size + sizeof(uint32_t) - 1) / sizeof(uint32_t));
} }
push.stages = push_range.stageFlags; push.stages = push_range.stageFlags;
push_range.size = reflection.push_constant_size; push_range.size = reflection.push_constant_size;
if (vkCreatePipelineLayout(device, if (vkCreatePipelineLayout(device,
&layout_info, NULL, &pipeline_layout) != VK_SUCCESS) &layout_info, NULL, &pipeline_layout) != VK_SUCCESS)
return false; return false;
VkDescriptorPoolCreateInfo pool_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
pool_info.maxSets = num_sync_indices; pool_info.maxSets = num_sync_indices;
pool_info.poolSizeCount = desc_counts.size(); pool_info.poolSizeCount = desc_counts.size();
pool_info.pPoolSizes = desc_counts.data(); pool_info.pPoolSizes = desc_counts.data();
if (vkCreateDescriptorPool(device, &pool_info, nullptr, &pool) != VK_SUCCESS) if (vkCreateDescriptorPool(device, &pool_info, nullptr, &pool) != VK_SUCCESS)
return false; return false;
VkDescriptorSetAllocateInfo alloc_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
alloc_info.descriptorPool = pool; alloc_info.descriptorPool = pool;
alloc_info.descriptorSetCount = 1; alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = &set_layout; alloc_info.pSetLayouts = &set_layout;
@ -1685,18 +1670,43 @@ bool Pass::init_pipeline_layout()
bool Pass::init_pipeline() bool Pass::init_pipeline()
{ {
VkPipelineInputAssemblyStateCreateInfo input_assembly = {
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
VkVertexInputAttributeDescription attributes[2] = {{0}};
VkVertexInputBindingDescription binding = {0};
VkPipelineVertexInputStateCreateInfo vertex_input = {
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
VkPipelineRasterizationStateCreateInfo raster = {
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
VkPipelineColorBlendAttachmentState blend_attachment = {0};
VkPipelineColorBlendStateCreateInfo blend = {
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
VkPipelineViewportStateCreateInfo viewport = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
VkPipelineDepthStencilStateCreateInfo depth_stencil = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
VkPipelineMultisampleStateCreateInfo multisample = {
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
VkPipelineDynamicStateCreateInfo dynamic = {
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
static const VkDynamicState dynamics[] = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineShaderStageCreateInfo shader_stages[2] = {
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
};
VkShaderModuleCreateInfo module_info = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
VkGraphicsPipelineCreateInfo pipe = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
if (!init_pipeline_layout()) if (!init_pipeline_layout())
return false; return false;
/* Input assembly */ /* Input assembly */
VkPipelineInputAssemblyStateCreateInfo input_assembly = {
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
/* VAO state */ /* VAO state */
VkVertexInputAttributeDescription attributes[2] = {{0}};
VkVertexInputBindingDescription binding = {0};
attributes[0].location = 0; attributes[0].location = 0;
attributes[0].binding = 0; attributes[0].binding = 0;
attributes[0].format = VK_FORMAT_R32G32_SFLOAT; attributes[0].format = VK_FORMAT_R32G32_SFLOAT;
@ -1710,70 +1720,47 @@ bool Pass::init_pipeline()
binding.stride = 4 * sizeof(float); binding.stride = 4 * sizeof(float);
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
VkPipelineVertexInputStateCreateInfo vertex_input = {
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
vertex_input.vertexBindingDescriptionCount = 1; vertex_input.vertexBindingDescriptionCount = 1;
vertex_input.pVertexBindingDescriptions = &binding; vertex_input.pVertexBindingDescriptions = &binding;
vertex_input.vertexAttributeDescriptionCount = 2; vertex_input.vertexAttributeDescriptionCount = 2;
vertex_input.pVertexAttributeDescriptions = attributes; vertex_input.pVertexAttributeDescriptions = attributes;
/* Raster state */ /* Raster state */
VkPipelineRasterizationStateCreateInfo raster = { raster.polygonMode = VK_POLYGON_MODE_FILL;
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; raster.cullMode = VK_CULL_MODE_NONE;
raster.polygonMode = VK_POLYGON_MODE_FILL; raster.frontFace =
raster.cullMode = VK_CULL_MODE_NONE; VK_FRONT_FACE_COUNTER_CLOCKWISE;
raster.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; raster.depthClampEnable = false;
raster.depthClampEnable = false; raster.rasterizerDiscardEnable = false;
raster.rasterizerDiscardEnable = false; raster.depthBiasEnable = false;
raster.depthBiasEnable = false; raster.lineWidth = 1.0f;
raster.lineWidth = 1.0f;
/* Blend state */ /* Blend state */
VkPipelineColorBlendAttachmentState blend_attachment = {0}; blend_attachment.blendEnable = false;
VkPipelineColorBlendStateCreateInfo blend = { blend_attachment.colorWriteMask = 0xf;
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; blend.attachmentCount = 1;
blend_attachment.blendEnable = false; blend.pAttachments = &blend_attachment;
blend_attachment.colorWriteMask = 0xf;
blend.attachmentCount = 1;
blend.pAttachments = &blend_attachment;
/* Viewport state */ /* Viewport state */
VkPipelineViewportStateCreateInfo viewport = { viewport.viewportCount = 1;
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; viewport.scissorCount = 1;
viewport.viewportCount = 1;
viewport.scissorCount = 1;
/* Depth-stencil state */ /* Depth-stencil state */
VkPipelineDepthStencilStateCreateInfo depth_stencil = { depth_stencil.depthTestEnable = false;
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; depth_stencil.depthWriteEnable = false;
depth_stencil.depthTestEnable = false; depth_stencil.depthBoundsTestEnable = false;
depth_stencil.depthWriteEnable = false; depth_stencil.stencilTestEnable = false;
depth_stencil.depthBoundsTestEnable = false; depth_stencil.minDepthBounds = 0.0f;
depth_stencil.stencilTestEnable = false; depth_stencil.maxDepthBounds = 1.0f;
depth_stencil.minDepthBounds = 0.0f;
depth_stencil.maxDepthBounds = 1.0f;
/* Multisample state */ /* Multisample state */
VkPipelineMultisampleStateCreateInfo multisample = { multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
/* Dynamic state */ /* Dynamic state */
VkPipelineDynamicStateCreateInfo dynamic = {
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
static const VkDynamicState dynamics[] = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
dynamic.pDynamicStates = dynamics; dynamic.pDynamicStates = dynamics;
dynamic.dynamicStateCount = sizeof(dynamics) / sizeof(dynamics[0]); dynamic.dynamicStateCount = sizeof(dynamics) / sizeof(dynamics[0]);
/* Shaders */ /* Shaders */
VkPipelineShaderStageCreateInfo shader_stages[2] = {
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
};
VkShaderModuleCreateInfo module_info = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
module_info.codeSize = vertex_shader.size() * sizeof(uint32_t); module_info.codeSize = vertex_shader.size() * sizeof(uint32_t);
module_info.pCode = vertex_shader.data(); module_info.pCode = vertex_shader.data();
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
@ -1786,8 +1773,6 @@ bool Pass::init_pipeline()
shader_stages[1].pName = "main"; shader_stages[1].pName = "main";
vkCreateShaderModule(device, &module_info, NULL, &shader_stages[1].module); vkCreateShaderModule(device, &module_info, NULL, &shader_stages[1].module);
VkGraphicsPipelineCreateInfo pipe = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
pipe.stageCount = 2; pipe.stageCount = 2;
pipe.pStages = shader_stages; pipe.pStages = shader_stages;
pipe.pVertexInputState = &vertex_input; pipe.pVertexInputState = &vertex_input;
@ -1820,6 +1805,7 @@ CommonResources::CommonResources(VkDevice device,
: device(device) : device(device)
{ {
unsigned i; unsigned i;
VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
/* The final pass uses an MVP designed for [0, 1] range VBO. /* The final pass uses an MVP designed for [0, 1] range VBO.
* For in-between passes, we just go with identity matrices, * For in-between passes, we just go with identity matrices,
* so keep it simple. * so keep it simple.
@ -1838,14 +1824,14 @@ CommonResources::CommonResources(VkDevice device,
1.0f, +1.0f, 1.0f, 1.0f, 1.0f, +1.0f, 1.0f, 1.0f,
}; };
vbo = unique_ptr<Buffer>(new Buffer(device, vbo =
memory_properties, sizeof(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); unique_ptr<Buffer>(new Buffer(device,
memory_properties, sizeof(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
void *ptr = vbo->map(); void *ptr = vbo->map();
memcpy(ptr, vbo_data, sizeof(vbo_data)); memcpy(ptr, vbo_data, sizeof(vbo_data));
vbo->unmap(); vbo->unmap();
VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
info.mipLodBias = 0.0f; info.mipLodBias = 0.0f;
info.maxAnisotropy = 1.0f; info.maxAnisotropy = 1.0f;
info.compareEnable = false; info.compareEnable = false;
@ -1974,9 +1960,9 @@ bool Pass::init_feedback()
bool Pass::build() bool Pass::build()
{ {
unordered_map<string, slang_semantic_map> semantic_map;
unsigned i; unsigned i;
unsigned j = 0; unsigned j = 0;
unordered_map<string, slang_semantic_map> semantic_map;
framebuffer.reset(); framebuffer.reset();
framebuffer_feedback.reset(); framebuffer_feedback.reset();
@ -2026,16 +2012,17 @@ void Pass::set_uniform_buffer(VkDescriptorSet set, unsigned binding,
VkDeviceSize range) VkDeviceSize range)
{ {
VkDescriptorBufferInfo buffer_info; VkDescriptorBufferInfo buffer_info;
buffer_info.buffer = buffer;
buffer_info.offset = offset;
buffer_info.range = range;
VkWriteDescriptorSet write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; VkWriteDescriptorSet write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
buffer_info.buffer = buffer;
buffer_info.offset = offset;
buffer_info.range = range;
write.dstSet = set; write.dstSet = set;
write.dstBinding = binding; write.dstBinding = binding;
write.descriptorCount = 1; write.descriptorCount = 1;
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
write.pBufferInfo = &buffer_info; write.pBufferInfo = &buffer_info;
vkUpdateDescriptorSets(device, 1, &write, 0, NULL); vkUpdateDescriptorSets(device, 1, &write, 0, NULL);
} }
@ -2044,11 +2031,12 @@ void Pass::set_texture(VkDescriptorSet set, unsigned binding,
const Texture &texture) const Texture &texture)
{ {
VkDescriptorImageInfo image_info; VkDescriptorImageInfo image_info;
VkWriteDescriptorSet write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
image_info.sampler = common->samplers[texture.filter][texture.mip_filter][texture.address]; image_info.sampler = common->samplers[texture.filter][texture.mip_filter][texture.address];
image_info.imageView = texture.texture.view; image_info.imageView = texture.texture.view;
image_info.imageLayout = texture.texture.layout; image_info.imageLayout = texture.texture.layout;
VkWriteDescriptorSet write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
write.dstSet = set; write.dstSet = set;
write.dstBinding = binding; write.dstBinding = binding;
write.descriptorCount = 1; write.descriptorCount = 1;
@ -2294,6 +2282,9 @@ void Pass::build_commands(
* the passes that end up on-screen. */ * the passes that end up on-screen. */
if (!final_pass) if (!final_pass)
{ {
VkRenderPassBeginInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
/* Render. */ /* Render. */
vulkan_image_layout_transition_levels(cmd, vulkan_image_layout_transition_levels(cmd,
framebuffer->get_image(), 1, framebuffer->get_image(), 1,
@ -2304,8 +2295,6 @@ void Pass::build_commands(
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
VkRenderPassBeginInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
rp_info.renderPass = framebuffer->get_render_pass(); rp_info.renderPass = framebuffer->get_render_pass();
rp_info.framebuffer = framebuffer->get_framebuffer(); rp_info.framebuffer = framebuffer->get_framebuffer();
rp_info.renderArea.extent.width = current_framebuffer_size.width; rp_info.renderArea.extent.width = current_framebuffer_size.width;
@ -2317,7 +2306,8 @@ void Pass::build_commands(
} }
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_layout,
0, 1, &sets[sync_index], 0, nullptr); 0, 1, &sets[sync_index], 0, nullptr);
if (push.stages != 0) if (push.stages != 0)
@ -2327,10 +2317,12 @@ void Pass::build_commands(
push.buffer.data()); push.buffer.data());
} }
VkDeviceSize offset = final_pass ? 16 * sizeof(float) : 0; {
vkCmdBindVertexBuffers(cmd, 0, 1, VkDeviceSize offset = final_pass ? 16 * sizeof(float) : 0;
&common->vbo->get_buffer(), vkCmdBindVertexBuffers(cmd, 0, 1,
&offset); &common->vbo->get_buffer(),
&offset);
}
if (final_pass) if (final_pass)
{ {
@ -2404,7 +2396,7 @@ Framebuffer::Framebuffer(
{ {
RARCH_LOG("[Vulkan filter chain]: Creating framebuffer %u x %u (max %u level(s)).\n", RARCH_LOG("[Vulkan filter chain]: Creating framebuffer %u x %u (max %u level(s)).\n",
max_size.width, max_size.height, max_levels); max_size.width, max_size.height, max_levels);
init_render_pass(); vulkan_initialize_render_pass(device, format, &render_pass);
init(nullptr); init(nullptr);
} }
@ -2429,9 +2421,12 @@ void Framebuffer::clear(VkCommandBuffer cmd)
vkCmdClearColorImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vkCmdClearColorImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&color, 1, &range); &color, 1, &range);
vulkan_image_layout_transition_levels(cmd, image,VK_REMAINING_MIP_LEVELS, vulkan_image_layout_transition_levels(cmd, image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_REMAINING_MIP_LEVELS,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
} }
@ -2488,6 +2483,9 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd)
for (i = 1; i < levels; i++) for (i = 1; i < levels; i++)
{ {
unsigned src_width, src_height, target_width, target_height;
VkImageBlit blit_region = {};
/* For subsequent passes, we have to transition /* For subsequent passes, we have to transition
* from DST_OPTIMAL to SRC_OPTIMAL, * from DST_OPTIMAL to SRC_OPTIMAL,
* but only do so one mip-level at a time. */ * but only do so one mip-level at a time. */
@ -2509,11 +2507,10 @@ void Framebuffer::generate_mips(VkCommandBuffer cmd)
1, barriers); 1, barriers);
} }
VkImageBlit blit_region = {}; src_width = MAX(size.width >> (i - 1), 1u);
unsigned src_width = MAX(size.width >> (i - 1), 1u); src_height = MAX(size.height >> (i - 1), 1u);
unsigned src_height = MAX(size.height >> (i - 1), 1u); target_width = MAX(size.width >> i, 1u);
unsigned target_width = MAX(size.width >> i, 1u); target_height = MAX(size.height >> i, 1u);
unsigned target_height = MAX(size.height >> i, 1u);
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit_region.srcSubresource.mipLevel = i - 1; blit_region.srcSubresource.mipLevel = i - 1;
@ -2607,7 +2604,11 @@ void Framebuffer::copy(VkCommandBuffer cmd,
void Framebuffer::init(DeferredDisposer *disposer) void Framebuffer::init(DeferredDisposer *disposer)
{ {
VkMemoryRequirements mem_reqs; VkMemoryRequirements mem_reqs;
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
VkImageViewCreateInfo view_info = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
info.imageType = VK_IMAGE_TYPE_2D; info.imageType = VK_IMAGE_TYPE_2D;
info.format = format; info.format = format;
info.extent.width = size.width; info.extent.width = size.width;
@ -2618,19 +2619,18 @@ void Framebuffer::init(DeferredDisposer *disposer)
info.samples = VK_SAMPLE_COUNT_1_BIT; info.samples = VK_SAMPLE_COUNT_1_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL; info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT; VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
levels = info.mipLevels; levels = info.mipLevels;
vkCreateImage(device, &info, nullptr, &image); vkCreateImage(device, &info, nullptr, &image);
vkGetImageMemoryRequirements(device, image, &mem_reqs); vkGetImageMemoryRequirements(device, image, &mem_reqs);
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
alloc.allocationSize = mem_reqs.size; alloc.allocationSize = mem_reqs.size;
alloc.memoryTypeIndex = find_memory_type_fallback( alloc.memoryTypeIndex = find_memory_type_fallback(
memory_properties, mem_reqs.memoryTypeBits, memory_properties, mem_reqs.memoryTypeBits,
@ -2657,8 +2657,6 @@ void Framebuffer::init(DeferredDisposer *disposer)
vkBindImageMemory(device, image, memory.memory, 0); vkBindImageMemory(device, image, memory.memory, 0);
VkImageViewCreateInfo view_info = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.format = format; view_info.format = format;
view_info.image = image; view_info.image = image;
@ -2676,54 +2674,19 @@ void Framebuffer::init(DeferredDisposer *disposer)
view_info.subresourceRange.levelCount = 1; view_info.subresourceRange.levelCount = 1;
vkCreateImageView(device, &view_info, nullptr, &fb_view); vkCreateImageView(device, &view_info, nullptr, &fb_view);
init_framebuffer(); /* Initialize framebuffer */
} {
VkFramebufferCreateInfo info = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
info.renderPass = render_pass;
info.attachmentCount = 1;
info.pAttachments = &fb_view;
info.width = size.width;
info.height = size.height;
info.layers = 1;
void Framebuffer::init_render_pass() vkCreateFramebuffer(device, &info, nullptr, &framebuffer);
{ }
VkRenderPassCreateInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
VkAttachmentReference color_ref = { 0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
/* We will always write to the entire framebuffer,
* so we don't really need to clear. */
VkAttachmentDescription attachment = {0};
attachment.format = format;
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {0};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
rp_info.attachmentCount = 1;
rp_info.pAttachments = &attachment;
rp_info.subpassCount = 1;
rp_info.pSubpasses = &subpass;
vkCreateRenderPass(device, &rp_info, nullptr, &render_pass);
}
void Framebuffer::init_framebuffer()
{
VkFramebufferCreateInfo info = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
info.renderPass = render_pass;
info.attachmentCount = 1;
info.pAttachments = &fb_view;
info.width = size.width;
info.height = size.height;
info.layers = 1;
vkCreateFramebuffer(device, &info, nullptr, &framebuffer);
} }
void Framebuffer::set_size(DeferredDisposer &disposer, const Size2D &size, VkFormat format) void Framebuffer::set_size(DeferredDisposer &disposer, const Size2D &size, VkFormat format)
@ -2792,8 +2755,9 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_default(
vulkan_filter_chain_filter filter) vulkan_filter_chain_filter filter)
{ {
struct vulkan_filter_chain_pass_info pass_info; struct vulkan_filter_chain_pass_info pass_info;
auto tmpinfo = *info; auto tmpinfo = *info;
tmpinfo.num_passes = 1;
tmpinfo.num_passes = 1;
unique_ptr<vulkan_filter_chain> chain{ new vulkan_filter_chain(tmpinfo) }; unique_ptr<vulkan_filter_chain> chain{ new vulkan_filter_chain(tmpinfo) };
if (!chain) if (!chain)
@ -2971,7 +2935,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
param.initial = meta_param.initial; param.initial = meta_param.initial;
param.minimum = meta_param.minimum; param.minimum = meta_param.minimum;
param.maximum = meta_param.maximum; param.maximum = meta_param.maximum;
param.step = meta_param.step; param.step = meta_param.step;
chain->add_parameter(i, shader->num_parameters, meta_param.id); chain->add_parameter(i, shader->num_parameters, meta_param.id);
shader->num_parameters++; shader->num_parameters++;
} }
@ -3004,7 +2968,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
pass->filter == RARCH_FILTER_LINEAR ? VULKAN_FILTER_CHAIN_LINEAR : pass->filter == RARCH_FILTER_LINEAR ? VULKAN_FILTER_CHAIN_LINEAR :
VULKAN_FILTER_CHAIN_NEAREST; VULKAN_FILTER_CHAIN_NEAREST;
} }
pass_info.address = wrap_to_address(pass->wrap); pass_info.address = vk_wrap_to_address(pass->wrap);
pass_info.max_levels = 1; pass_info.max_levels = 1;
/* TODO: Expose max_levels in slangp. /* TODO: Expose max_levels in slangp.
@ -3025,18 +2989,16 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
if (!pass->fbo.valid) if (!pass->fbo.valid)
{ {
pass_info.scale_type_x = i + 1 == shader->passes pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_SOURCE;
? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_SOURCE;
: VULKAN_FILTER_CHAIN_SCALE_SOURCE; pass_info.scale_x = 1.0f;
pass_info.scale_type_y = i + 1 == shader->passes pass_info.scale_y = 1.0f;
? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT
: VULKAN_FILTER_CHAIN_SCALE_SOURCE;
pass_info.scale_x = 1.0f;
pass_info.scale_y = 1.0f;
if (i + 1 == shader->passes) if (i + 1 == shader->passes)
{ {
pass_info.rt_format = tmpinfo.swapchain.format; pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
pass_info.rt_format = tmpinfo.swapchain.format;
if (explicit_format) if (explicit_format)
RARCH_WARN("[slang]: Using explicit format for last pass in chain," RARCH_WARN("[slang]: Using explicit format for last pass in chain,"
@ -3044,7 +3006,8 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
} }
else else
{ {
pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format); pass_info.rt_format = glslang_format_to_vk(
output.meta.rt_format);
RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n",
glslang_format_to_string(output.meta.rt_format), i); glslang_format_to_string(output.meta.rt_format), i);
} }
@ -3058,24 +3021,25 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
else if (pass->fbo.fp_fbo) else if (pass->fbo.fp_fbo)
output.meta.rt_format = SLANG_FORMAT_R16G16B16A16_SFLOAT; output.meta.rt_format = SLANG_FORMAT_R16G16B16A16_SFLOAT;
pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format); pass_info.rt_format = glslang_format_to_vk(output.meta.rt_format);
RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n",
glslang_format_to_string(output.meta.rt_format), i); glslang_format_to_string(output.meta.rt_format), i);
switch (pass->fbo.type_x) switch (pass->fbo.type_x)
{ {
case RARCH_SCALE_INPUT: case RARCH_SCALE_INPUT:
pass_info.scale_x = pass->fbo.scale_x; pass_info.scale_x = pass->fbo.scale_x;
pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_SOURCE; pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_SOURCE;
break; break;
case RARCH_SCALE_ABSOLUTE: case RARCH_SCALE_ABSOLUTE:
pass_info.scale_x = float(pass->fbo.abs_x); pass_info.scale_x = float(pass->fbo.abs_x);
pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_ABSOLUTE; pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_ABSOLUTE;
break; break;
case RARCH_SCALE_VIEWPORT: case RARCH_SCALE_VIEWPORT:
pass_info.scale_x = pass->fbo.scale_x; pass_info.scale_x = pass->fbo.scale_x;
pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT; pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
break; break;
} }
@ -3083,17 +3047,17 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
switch (pass->fbo.type_y) switch (pass->fbo.type_y)
{ {
case RARCH_SCALE_INPUT: case RARCH_SCALE_INPUT:
pass_info.scale_y = pass->fbo.scale_y; pass_info.scale_y = pass->fbo.scale_y;
pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_SOURCE; pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_SOURCE;
break; break;
case RARCH_SCALE_ABSOLUTE: case RARCH_SCALE_ABSOLUTE:
pass_info.scale_y = float(pass->fbo.abs_y); pass_info.scale_y = float(pass->fbo.abs_y);
pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_ABSOLUTE; pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_ABSOLUTE;
break; break;
case RARCH_SCALE_VIEWPORT: case RARCH_SCALE_VIEWPORT:
pass_info.scale_y = pass->fbo.scale_y; pass_info.scale_y = pass->fbo.scale_y;
pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT; pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
break; break;
} }

View File

@ -111,6 +111,25 @@ struct vulkan_filter_chain_create_info
struct vulkan_filter_chain_swapchain_info swapchain; struct vulkan_filter_chain_swapchain_info swapchain;
}; };
static INLINE enum vulkan_filter_chain_address vk_wrap_to_address(enum gfx_wrap_type type)
{
switch (type)
{
case RARCH_WRAP_BORDER:
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER;
case RARCH_WRAP_REPEAT:
return VULKAN_FILTER_CHAIN_ADDRESS_REPEAT;
case RARCH_WRAP_MIRRORED_REPEAT:
return VULKAN_FILTER_CHAIN_ADDRESS_MIRRORED_REPEAT;
case RARCH_WRAP_EDGE:
default:
break;
}
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE;
}
vulkan_filter_chain_t *vulkan_filter_chain_new( vulkan_filter_chain_t *vulkan_filter_chain_new(
const struct vulkan_filter_chain_create_info *info); const struct vulkan_filter_chain_create_info *info);
void vulkan_filter_chain_free(vulkan_filter_chain_t *chain); void vulkan_filter_chain_free(vulkan_filter_chain_t *chain);