mirror of
https://github.com/libretro/RetroArch
synced 2025-04-15 23:42:30 +00:00
Merge branch 'master' of git://github.com/libretro/RetroArch
This commit is contained in:
commit
4259ea3d06
@ -173,15 +173,17 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
VkFormat format,
|
||||
const void *initial, const VkComponentMapping *swizzle, enum vk_texture_type type)
|
||||
{
|
||||
VkDevice device = vk->context->device;
|
||||
struct vk_texture tex;
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkSubresourceLayout layout;
|
||||
VkDevice device = vk->context->device;
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
|
||||
VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT };
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkSubresourceLayout layout;
|
||||
VkCommandBufferAllocateInfo cmd_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
|
||||
memset(&tex, 0, sizeof(tex));
|
||||
|
||||
@ -364,12 +366,12 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
|
||||
if (initial && type == VULKAN_TEXTURE_STREAMED)
|
||||
{
|
||||
unsigned x, y;
|
||||
uint8_t *dst = NULL;
|
||||
const uint8_t *src = NULL;
|
||||
void *ptr = NULL;
|
||||
unsigned bpp = vulkan_format_to_bpp(tex.format);
|
||||
unsigned stride = tex.width * bpp;
|
||||
unsigned x, y;
|
||||
uint8_t *dst;
|
||||
const uint8_t *src;
|
||||
void *ptr;
|
||||
|
||||
vkMapMemory(device, tex.memory, tex.offset, tex.size, 0, &ptr);
|
||||
|
||||
@ -382,20 +384,16 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
}
|
||||
else if (initial && type == VULKAN_TEXTURE_STATIC)
|
||||
{
|
||||
VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkImageCopy region;
|
||||
|
||||
VkCommandBuffer staging;
|
||||
unsigned bpp = vulkan_format_to_bpp(tex.format);
|
||||
struct vk_texture tmp = vulkan_create_texture(vk, NULL,
|
||||
width, height, format, initial, NULL, VULKAN_TEXTURE_STAGING);
|
||||
|
||||
info.commandPool = vk->staging_pool;
|
||||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
info.commandBufferCount = 1;
|
||||
vkAllocateCommandBuffers(vk->context->device, &info, &staging);
|
||||
cmd_info.commandPool = vk->staging_pool;
|
||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cmd_info.commandBufferCount = 1;
|
||||
vkAllocateCommandBuffers(vk->context->device, &cmd_info, &staging);
|
||||
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkBeginCommandBuffer(staging, &begin_info);
|
||||
@ -426,8 +424,10 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
1, ®ion);
|
||||
|
||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_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_TOP_OF_PIPE_BIT);
|
||||
|
||||
@ -437,8 +437,10 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
|
||||
slock_lock(vk->context->queue_lock);
|
||||
vkQueueSubmit(vk->context->queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
/* TODO: Very crude, but texture uploads only happen during init,
|
||||
* so waiting for GPU to complete transfer and blocking isn't a big deal. */
|
||||
|
||||
/* TODO: Very crude, but texture uploads only happen
|
||||
* during init, so waiting for GPU to complete transfer
|
||||
* and blocking isn't a big deal. */
|
||||
vkQueueWaitIdle(vk->context->queue);
|
||||
slock_unlock(vk->context->queue_lock);
|
||||
|
||||
@ -500,7 +502,8 @@ static void vulkan_write_quad_descriptors(VkDevice device,
|
||||
void vulkan_transition_texture(vk_t *vk, struct vk_texture *texture)
|
||||
{
|
||||
/* Transition to GENERAL layout for linear streamed textures.
|
||||
* We're using linear textures here, so only GENERAL layout is supported.
|
||||
* We're using linear textures here, so only
|
||||
* GENERAL layout is supported.
|
||||
*/
|
||||
if (texture->layout == VK_IMAGE_LAYOUT_PREINITIALIZED)
|
||||
{
|
||||
@ -517,7 +520,9 @@ static void vulkan_check_dynamic_state(vk_t *vk)
|
||||
{
|
||||
if (vk->tracker.dirty & VULKAN_DIRTY_DYNAMIC_BIT)
|
||||
{
|
||||
const VkRect2D sci = {{ vk->vp.x, vk->vp.y }, { vk->vp.width, vk->vp.height }};
|
||||
const VkRect2D sci = {
|
||||
{ vk->vp.x, vk->vp.y },
|
||||
{ vk->vp.width, vk->vp.height }};
|
||||
vkCmdSetViewport(vk->cmd, 0, 1, &vk->vk_vp);
|
||||
vkCmdSetScissor(vk->cmd, 0, 1, &sci);
|
||||
|
||||
@ -531,7 +536,8 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
|
||||
if (call->pipeline != vk->tracker.pipeline)
|
||||
{
|
||||
vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, call->pipeline);
|
||||
vkCmdBindPipeline(vk->cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, call->pipeline);
|
||||
vk->tracker.pipeline = call->pipeline;
|
||||
|
||||
/* Changing pipeline invalidates dynamic state. */
|
||||
@ -544,9 +550,9 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
{
|
||||
VkDescriptorSet set;
|
||||
|
||||
if (memcmp(call->mvp, &vk->tracker.mvp, sizeof(*call->mvp)) ||
|
||||
call->texture->view != vk->tracker.view ||
|
||||
call->sampler != vk->tracker.sampler)
|
||||
if (memcmp(call->mvp, &vk->tracker.mvp, sizeof(*call->mvp))
|
||||
|| (call->texture->view != vk->tracker.view)
|
||||
|| (call->sampler != vk->tracker.sampler))
|
||||
{
|
||||
/* Upload UBO */
|
||||
struct vk_buffer_range range;
|
||||
@ -555,7 +561,8 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
return;
|
||||
memcpy(range.data, call->mvp, sizeof(*call->mvp));
|
||||
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device, &vk->chain->descriptor_manager);
|
||||
set = vulkan_descriptor_manager_alloc(
|
||||
vk->context->device, &vk->chain->descriptor_manager);
|
||||
vulkan_write_quad_descriptors(vk->context->device,
|
||||
set,
|
||||
range.buffer,
|
||||
@ -588,7 +595,8 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
|
||||
if (quad->pipeline != vk->tracker.pipeline)
|
||||
{
|
||||
vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, quad->pipeline);
|
||||
vkCmdBindPipeline(vk->cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, quad->pipeline);
|
||||
vk->tracker.pipeline = quad->pipeline;
|
||||
|
||||
/* Changing pipeline invalidates dynamic state. */
|
||||
@ -605,9 +613,9 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
sizeof(*quad->mvp), &range))
|
||||
return;
|
||||
|
||||
if (memcmp(quad->mvp, &vk->tracker.mvp, sizeof(*quad->mvp)) ||
|
||||
quad->texture->view != vk->tracker.view ||
|
||||
quad->sampler != vk->tracker.sampler)
|
||||
if (memcmp(quad->mvp, &vk->tracker.mvp, sizeof(*quad->mvp))
|
||||
|| quad->texture->view != vk->tracker.view
|
||||
|| quad->sampler != vk->tracker.sampler)
|
||||
{
|
||||
/* Upload UBO */
|
||||
struct vk_buffer_range range;
|
||||
@ -616,7 +624,9 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
return;
|
||||
memcpy(range.data, quad->mvp, sizeof(*quad->mvp));
|
||||
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device, &vk->chain->descriptor_manager);
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device,
|
||||
&vk->chain->descriptor_manager);
|
||||
|
||||
vulkan_write_quad_descriptors(vk->context->device,
|
||||
set,
|
||||
range.buffer,
|
||||
@ -655,10 +665,15 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
vkCmdDraw(vk->cmd, 6, 1, 0, 0);
|
||||
}
|
||||
|
||||
void vulkan_image_layout_transition(vk_t *vk, VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages)
|
||||
void vulkan_image_layout_transition(
|
||||
vk_t *vk,
|
||||
VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout,
|
||||
VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess,
|
||||
VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages,
|
||||
VkPipelineStageFlags dstStages)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
|
||||
@ -698,15 +713,18 @@ struct vk_buffer vulkan_create_buffer(const struct vulkan_context *context,
|
||||
vkGetBufferMemoryRequirements(context->device, buffer.buffer, &mem_reqs);
|
||||
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(&context->memory_properties,
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(
|
||||
&context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
vkAllocateMemory(context->device, &alloc, NULL, &buffer.memory);
|
||||
vkBindBufferMemory(context->device, buffer.buffer, buffer.memory, 0);
|
||||
|
||||
buffer.size = alloc.allocationSize;
|
||||
|
||||
vkMapMemory(context->device, buffer.memory, 0, buffer.size, 0, &buffer.mapped);
|
||||
vkMapMemory(context->device,
|
||||
buffer.memory, 0, buffer.size, 0, &buffer.mapped);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -718,14 +736,18 @@ void vulkan_destroy_buffer(VkDevice device, struct vk_buffer *buffer)
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
}
|
||||
|
||||
static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(VkDevice device,
|
||||
static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(
|
||||
VkDevice device,
|
||||
const struct vk_descriptor_manager *manager)
|
||||
{
|
||||
unsigned i;
|
||||
VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorSetAllocateInfo alloc_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
|
||||
struct vk_descriptor_pool *pool = (struct vk_descriptor_pool*)calloc(1, sizeof(*pool));
|
||||
struct vk_descriptor_pool *pool =
|
||||
(struct vk_descriptor_pool*)calloc(1, sizeof(*pool));
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
@ -745,7 +767,8 @@ static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(VkDevice device,
|
||||
return pool;
|
||||
}
|
||||
|
||||
VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, struct vk_descriptor_manager *manager)
|
||||
VkDescriptorSet vulkan_descriptor_manager_alloc(
|
||||
VkDevice device, struct vk_descriptor_manager *manager)
|
||||
{
|
||||
if (manager->count < VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS)
|
||||
return manager->current->sets[manager->count++];
|
||||
@ -771,8 +794,11 @@ void vulkan_descriptor_manager_restart(struct vk_descriptor_manager *manager)
|
||||
manager->count = 0;
|
||||
}
|
||||
|
||||
struct vk_descriptor_manager vulkan_create_descriptor_manager(VkDevice device,
|
||||
const VkDescriptorPoolSize *sizes, unsigned num_sizes, VkDescriptorSetLayout set_layout)
|
||||
struct vk_descriptor_manager vulkan_create_descriptor_manager(
|
||||
VkDevice device,
|
||||
const VkDescriptorPoolSize *sizes,
|
||||
unsigned num_sizes,
|
||||
VkDescriptorSetLayout set_layout)
|
||||
{
|
||||
struct vk_descriptor_manager manager;
|
||||
memset(&manager, 0, sizeof(manager));
|
||||
@ -786,7 +812,8 @@ struct vk_descriptor_manager vulkan_create_descriptor_manager(VkDevice device,
|
||||
return manager;
|
||||
}
|
||||
|
||||
void vulkan_destroy_descriptor_manager(VkDevice device, struct vk_descriptor_manager *manager)
|
||||
void vulkan_destroy_descriptor_manager(VkDevice device,
|
||||
struct vk_descriptor_manager *manager)
|
||||
{
|
||||
struct vk_descriptor_pool *node = manager->head;
|
||||
|
||||
@ -794,7 +821,8 @@ void vulkan_destroy_descriptor_manager(VkDevice device, struct vk_descriptor_man
|
||||
{
|
||||
struct vk_descriptor_pool *next = node->next;
|
||||
|
||||
vkFreeDescriptorSets(device, node->pool, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS, node->sets);
|
||||
vkFreeDescriptorSets(device, node->pool,
|
||||
VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS, node->sets);
|
||||
vkDestroyDescriptorPool(device, node->pool, NULL);
|
||||
|
||||
free(node);
|
||||
@ -810,7 +838,8 @@ static void vulkan_buffer_chain_step(struct vk_buffer_chain *chain)
|
||||
chain->offset = 0;
|
||||
}
|
||||
|
||||
static bool vulkan_buffer_chain_suballoc(struct vk_buffer_chain *chain, size_t size, struct vk_buffer_range *range)
|
||||
static bool vulkan_buffer_chain_suballoc(struct vk_buffer_chain *chain,
|
||||
size_t size, struct vk_buffer_range *range)
|
||||
{
|
||||
VkDeviceSize next_offset = chain->offset + size;
|
||||
if (next_offset <= chain->current->buffer.size)
|
||||
@ -818,10 +847,12 @@ static bool vulkan_buffer_chain_suballoc(struct vk_buffer_chain *chain, size_t s
|
||||
range->data = (uint8_t*)chain->current->buffer.mapped + chain->offset;
|
||||
range->buffer = chain->current->buffer.buffer;
|
||||
range->offset = chain->offset;
|
||||
chain->offset = (next_offset + chain->alignment - 1) & ~(chain->alignment - 1);
|
||||
chain->offset = (next_offset + chain->alignment - 1)
|
||||
& ~(chain->alignment - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -829,7 +860,8 @@ static struct vk_buffer_node *vulkan_buffer_chain_alloc_node(
|
||||
const struct vulkan_context *context,
|
||||
size_t size, VkBufferUsageFlags usage)
|
||||
{
|
||||
struct vk_buffer_node *node = (struct vk_buffer_node*)calloc(1, sizeof(*node));
|
||||
struct vk_buffer_node *node = (struct vk_buffer_node*)
|
||||
calloc(1, sizeof(*node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
@ -841,7 +873,8 @@ struct vk_buffer_chain vulkan_buffer_chain_init(VkDeviceSize block_size,
|
||||
VkDeviceSize alignment,
|
||||
VkBufferUsageFlags usage)
|
||||
{
|
||||
struct vk_buffer_chain chain = { block_size, alignment, 0, usage, NULL, NULL };
|
||||
struct vk_buffer_chain chain = {
|
||||
block_size, alignment, 0, usage, NULL, NULL };
|
||||
return chain;
|
||||
}
|
||||
|
||||
@ -852,7 +885,8 @@ void vulkan_buffer_chain_discard(struct vk_buffer_chain *chain)
|
||||
}
|
||||
|
||||
bool vulkan_buffer_chain_alloc(const struct vulkan_context *context,
|
||||
struct vk_buffer_chain *chain, size_t size, struct vk_buffer_range *range)
|
||||
struct vk_buffer_chain *chain,
|
||||
size_t size, struct vk_buffer_range *range)
|
||||
{
|
||||
if (!chain->head)
|
||||
{
|
||||
@ -878,7 +912,8 @@ bool vulkan_buffer_chain_alloc(const struct vulkan_context *context,
|
||||
}
|
||||
|
||||
/* We have to allocate a new node, might allocate larger
|
||||
* buffer here than block_size in case we have a very large allocation. */
|
||||
* buffer here than block_size in case we have
|
||||
* a very large allocation. */
|
||||
if (size < chain->block_size)
|
||||
size = chain->block_size;
|
||||
|
||||
|
@ -52,11 +52,14 @@
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
#include <formats/image.h>
|
||||
#include <boolean.h>
|
||||
#include <retro_inline.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include "boolean.h"
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
#include <gfx/scaler/scaler.h>
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <formats/image.h>
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../../performance.h"
|
||||
#include "../../libretro.h"
|
||||
@ -66,8 +69,6 @@
|
||||
#include "../video_context_driver.h"
|
||||
#include "libretro_vulkan.h"
|
||||
#include "../drivers_shader/shader_vulkan.h"
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <gfx/scaler/scaler.h>
|
||||
|
||||
enum vk_texture_type
|
||||
{
|
||||
@ -132,10 +133,14 @@ typedef struct gfx_ctx_vulkan_data
|
||||
{
|
||||
vulkan_context_t context;
|
||||
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR
|
||||
fpGetPhysicalDeviceSurfaceSupportKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
|
||||
fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
|
||||
fpGetPhysicalDeviceSurfaceFormatsKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
|
||||
fpGetPhysicalDeviceSurfacePresentModesKHR;
|
||||
PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
|
||||
PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
|
||||
PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
|
||||
@ -451,7 +456,8 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad);
|
||||
*/
|
||||
void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call);
|
||||
|
||||
void vulkan_image_layout_transition(vk_t *vk, VkCommandBuffer cmd, VkImage image,
|
||||
void vulkan_image_layout_transition(vk_t *vk,
|
||||
VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages);
|
||||
|
@ -72,8 +72,10 @@ static const gfx_ctx_driver_t *vulkan_get_context(vk_t *vk)
|
||||
static void vulkan_init_render_pass(vk_t *vk)
|
||||
{
|
||||
VkAttachmentDescription attachment = {0};
|
||||
VkRenderPassCreateInfo rp_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
|
||||
VkAttachmentReference color_ref = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
|
||||
VkRenderPassCreateInfo rp_info = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
|
||||
VkAttachmentReference color_ref = { 0,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
|
||||
VkSubpassDescription subpass = {0};
|
||||
|
||||
/* Backbuffer format. */
|
||||
@ -88,7 +90,8 @@ static void vulkan_init_render_pass(vk_t *vk)
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
|
||||
/* The image layout will be attachment_optimal when we're executing the renderpass. */
|
||||
/* The image layout will be attachment_optimal
|
||||
* when we're executing the renderpass. */
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
@ -104,7 +107,8 @@ static void vulkan_init_render_pass(vk_t *vk)
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
|
||||
vkCreateRenderPass(vk->context->device, &rp_info, NULL, &vk->render_pass);
|
||||
vkCreateRenderPass(vk->context->device,
|
||||
&rp_info, NULL, &vk->render_pass);
|
||||
}
|
||||
|
||||
static void vulkan_init_framebuffers(vk_t *vk)
|
||||
@ -114,8 +118,10 @@ static void vulkan_init_framebuffers(vk_t *vk)
|
||||
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
{
|
||||
VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkFramebufferCreateInfo info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
VkImageViewCreateInfo view = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkFramebufferCreateInfo info = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
|
||||
vk->swapchain[i].backbuffer.image = vk->context->swapchain_images[i];
|
||||
|
||||
@ -151,8 +157,10 @@ static void vulkan_init_framebuffers(vk_t *vk)
|
||||
|
||||
static void vulkan_init_pipeline_layout(vk_t *vk)
|
||||
{
|
||||
VkDescriptorSetLayoutCreateInfo set_layout_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
VkPipelineLayoutCreateInfo layout_info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
VkDescriptorSetLayoutCreateInfo set_layout_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
VkPipelineLayoutCreateInfo layout_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
VkDescriptorSetLayoutBinding bindings[2] = {{0}};
|
||||
|
||||
bindings[0].binding = 0;
|
||||
@ -170,34 +178,46 @@ static void vulkan_init_pipeline_layout(vk_t *vk)
|
||||
set_layout_info.bindingCount = 2;
|
||||
set_layout_info.pBindings = bindings;
|
||||
|
||||
vkCreateDescriptorSetLayout(vk->context->device, &set_layout_info, NULL, &vk->pipelines.set_layout);
|
||||
vkCreateDescriptorSetLayout(vk->context->device,
|
||||
&set_layout_info, NULL, &vk->pipelines.set_layout);
|
||||
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = &vk->pipelines.set_layout;
|
||||
|
||||
vkCreatePipelineLayout(vk->context->device, &layout_info, NULL, &vk->pipelines.layout);
|
||||
vkCreatePipelineLayout(vk->context->device,
|
||||
&layout_info, NULL, &vk->pipelines.layout);
|
||||
}
|
||||
|
||||
static void vulkan_init_pipelines(vk_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
VkPipelineRasterizationStateCreateInfo raster = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
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 };
|
||||
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 };
|
||||
|
||||
VkPipelineShaderStageCreateInfo shader_stages[2] = {
|
||||
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
|
||||
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
|
||||
};
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||
VkShaderModuleCreateInfo module_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
|
||||
VkGraphicsPipelineCreateInfo pipe = {
|
||||
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||
VkShaderModuleCreateInfo module_info = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
|
||||
VkVertexInputAttributeDescription attributes[3] = {{0}};
|
||||
VkVertexInputBindingDescription binding = {0};
|
||||
|
||||
@ -286,12 +306,15 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
module_info.pCode = (const uint32_t*)alpha_blend_vert_spv;
|
||||
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
shader_stages[0].pName = "main";
|
||||
vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[0].module);
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[0].module);
|
||||
|
||||
module_info.codeSize = alpha_blend_frag_spv_len;
|
||||
module_info.pCode = (const uint32_t*)alpha_blend_frag_spv;
|
||||
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shader_stages[1].pName = "main";
|
||||
vkCreateShaderModule(vk->context->device, &module_info, NULL, &shader_stages[1].module);
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
blend_attachment.blendEnable = true;
|
||||
blend_attachment.colorWriteMask = 0xf;
|
||||
@ -326,17 +349,22 @@ static void vulkan_init_command_buffers(vk_t *vk)
|
||||
unsigned i;
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
{
|
||||
VkCommandPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
|
||||
VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
VkCommandPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
|
||||
VkCommandBufferAllocateInfo info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
|
||||
pool_info.queueFamilyIndex = vk->context->graphics_queue_index;
|
||||
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
vkCreateCommandPool(vk->context->device, &pool_info, NULL, &vk->swapchain[i].cmd_pool);
|
||||
pool_info.flags =
|
||||
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
vkCreateCommandPool(vk->context->device,
|
||||
&pool_info, NULL, &vk->swapchain[i].cmd_pool);
|
||||
|
||||
info.commandPool = vk->swapchain[i].cmd_pool;
|
||||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
info.commandBufferCount = 1;
|
||||
vkAllocateCommandBuffers(vk->context->device, &info, &vk->swapchain[i].cmd);
|
||||
vkAllocateCommandBuffers(vk->context->device,
|
||||
&info, &vk->swapchain[i].cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,8 +384,8 @@ static void vulkan_init_samplers(vk_t *vk)
|
||||
info.maxLod = 0.0f;
|
||||
info.unnormalizedCoordinates = false;
|
||||
info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
|
||||
vkCreateSampler(vk->context->device, &info, NULL, &vk->samplers.nearest);
|
||||
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
info.minFilter = VK_FILTER_LINEAR;
|
||||
vkCreateSampler(vk->context->device, &info, NULL, &vk->samplers.linear);
|
||||
@ -396,7 +424,8 @@ static void vulkan_deinit_buffers(vk_t *vk)
|
||||
static void vulkan_init_descriptor_pool(vk_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
static const VkDescriptorPoolSize pool_sizes[2] = {
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 },
|
||||
@ -404,7 +433,8 @@ static void vulkan_init_descriptor_pool(vk_t *vk)
|
||||
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
{
|
||||
vk->swapchain[i].descriptor_manager = vulkan_create_descriptor_manager(vk->context->device,
|
||||
vk->swapchain[i].descriptor_manager =
|
||||
vulkan_create_descriptor_manager(vk->context->device,
|
||||
pool_sizes, 2, vk->pipelines.set_layout);
|
||||
}
|
||||
}
|
||||
@ -413,7 +443,8 @@ static void vulkan_deinit_descriptor_pool(vk_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
vulkan_destroy_descriptor_manager(vk->context->device, &vk->swapchain[i].descriptor_manager);
|
||||
vulkan_destroy_descriptor_manager(vk->context->device,
|
||||
&vk->swapchain[i].descriptor_manager);
|
||||
}
|
||||
|
||||
static void vulkan_init_textures(vk_t *vk)
|
||||
@ -426,7 +457,8 @@ static void vulkan_init_textures(vk_t *vk)
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
{
|
||||
vk->swapchain[i].texture = vulkan_create_texture(vk, NULL,
|
||||
vk->tex_w, vk->tex_h, vk->tex_fmt, NULL, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
vk->tex_w, vk->tex_h, vk->tex_fmt,
|
||||
NULL, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
vulkan_map_persistent_texture(vk->context->device,
|
||||
&vk->swapchain[i].texture);
|
||||
|
||||
@ -463,14 +495,17 @@ static void vulkan_deinit_command_buffers(vk_t *vk)
|
||||
vkFreeCommandBuffers(vk->context->device,
|
||||
vk->swapchain[i].cmd_pool, 1, &vk->swapchain[i].cmd);
|
||||
|
||||
vkDestroyCommandPool(vk->context->device, vk->swapchain[i].cmd_pool, NULL);
|
||||
vkDestroyCommandPool(vk->context->device,
|
||||
vk->swapchain[i].cmd_pool, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void vulkan_deinit_pipeline_layout(vk_t *vk)
|
||||
{
|
||||
vkDestroyPipelineLayout(vk->context->device, vk->pipelines.layout, NULL);
|
||||
vkDestroyDescriptorSetLayout(vk->context->device, vk->pipelines.set_layout, NULL);
|
||||
vkDestroyPipelineLayout(vk->context->device,
|
||||
vk->pipelines.layout, NULL);
|
||||
vkDestroyDescriptorSetLayout(vk->context->device,
|
||||
vk->pipelines.set_layout, NULL);
|
||||
}
|
||||
|
||||
static void vulkan_deinit_pipelines(vk_t *vk)
|
||||
@ -511,7 +546,10 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
|
||||
info.swapchain.render_pass = vk->render_pass;
|
||||
info.swapchain.num_indices = vk->context->num_swapchain_images;
|
||||
|
||||
vk->filter_chain = vulkan_filter_chain_create_default(&info, vk->video.smooth ? VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST);
|
||||
vk->filter_chain = vulkan_filter_chain_create_default(&info,
|
||||
vk->video.smooth ?
|
||||
VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST);
|
||||
|
||||
if (!vk->filter_chain)
|
||||
{
|
||||
RARCH_ERR("Failed to create filter chain.\n");
|
||||
@ -589,36 +627,44 @@ static void vulkan_init_resources(vk_t *vk)
|
||||
|
||||
static void vulkan_init_static_resources(vk_t *vk)
|
||||
{
|
||||
VkCommandPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
|
||||
unsigned i;
|
||||
uint32_t blank[4 * 4];
|
||||
|
||||
VkCommandPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
|
||||
/* Create the pipeline cache. */
|
||||
VkPipelineCacheCreateInfo cache = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
|
||||
vkCreatePipelineCache(vk->context->device, &cache, NULL, &vk->pipelines.cache);
|
||||
VkPipelineCacheCreateInfo cache = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
|
||||
|
||||
vkCreatePipelineCache(vk->context->device,
|
||||
&cache, NULL, &vk->pipelines.cache);
|
||||
|
||||
pool_info.queueFamilyIndex = vk->context->graphics_queue_index;
|
||||
vkCreateCommandPool(vk->context->device, &pool_info, NULL, &vk->staging_pool);
|
||||
vkCreateCommandPool(vk->context->device,
|
||||
&pool_info, NULL, &vk->staging_pool);
|
||||
|
||||
for (i = 0; i < 4 * 4; i++)
|
||||
blank[i] = -1u;
|
||||
|
||||
vk->display.blank_texture = vulkan_create_texture(vk, NULL,
|
||||
4, 4, VK_FORMAT_B8G8R8A8_UNORM, blank, NULL, VULKAN_TEXTURE_STATIC);
|
||||
4, 4, VK_FORMAT_B8G8R8A8_UNORM,
|
||||
blank, NULL, VULKAN_TEXTURE_STATIC);
|
||||
}
|
||||
|
||||
static void vulkan_deinit_static_resources(vk_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
vkDestroyPipelineCache(vk->context->device, vk->pipelines.cache, NULL);
|
||||
vulkan_destroy_texture(vk->context->device, &vk->display.blank_texture);
|
||||
vkDestroyPipelineCache(vk->context->device,
|
||||
vk->pipelines.cache, NULL);
|
||||
vulkan_destroy_texture(vk->context->device,
|
||||
&vk->display.blank_texture);
|
||||
vkDestroyCommandPool(vk->context->device, vk->staging_pool, NULL);
|
||||
free(vk->hw.cmd);
|
||||
free(vk->hw.wait_dst_stages);
|
||||
|
||||
for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++)
|
||||
if (vk->readback.staging[i].memory != VK_NULL_HANDLE)
|
||||
vulkan_destroy_texture(vk->context->device, &vk->readback.staging[i]);
|
||||
vulkan_destroy_texture(vk->context->device,
|
||||
&vk->readback.staging[i]);
|
||||
}
|
||||
|
||||
static void vulkan_deinit_resources(vk_t *vk)
|
||||
@ -688,8 +734,8 @@ static void vulkan_set_image(void *handle,
|
||||
uint32_t num_semaphores,
|
||||
const VkSemaphore *semaphores)
|
||||
{
|
||||
vk_t *vk = (vk_t*)handle;
|
||||
unsigned i;
|
||||
vk_t *vk = (vk_t*)handle;
|
||||
|
||||
vk->hw.image = image;
|
||||
vk->hw.num_semaphores = num_semaphores;
|
||||
@ -697,9 +743,12 @@ static void vulkan_set_image(void *handle,
|
||||
|
||||
if (num_semaphores > 0)
|
||||
{
|
||||
vk->hw.wait_dst_stages = (VkPipelineStageFlags*)realloc(vk->hw.wait_dst_stages,
|
||||
vk->hw.wait_dst_stages = (VkPipelineStageFlags*)
|
||||
realloc(vk->hw.wait_dst_stages,
|
||||
sizeof(VkPipelineStageFlags) * vk->hw.num_semaphores);
|
||||
retro_assert(vk->hw.wait_dst_stages); /* If this fails, we're screwed anyways. */
|
||||
|
||||
/* If this fails, we're screwed anyways. */
|
||||
retro_assert(vk->hw.wait_dst_stages);
|
||||
|
||||
for (i = 0; i < vk->hw.num_semaphores; i++)
|
||||
vk->hw.wait_dst_stages[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
@ -722,7 +771,9 @@ static void vulkan_set_command_buffers(void *handle, uint32_t num_cmd,
|
||||
{
|
||||
vk->hw.cmd = (VkCommandBuffer*)realloc(vk->hw.cmd,
|
||||
sizeof(VkCommandBuffer) * required_capacity);
|
||||
retro_assert(vk->hw.cmd); /* If this fails, we're just screwed. */
|
||||
|
||||
/* If this fails, we're just screwed. */
|
||||
retro_assert(vk->hw.cmd);
|
||||
vk->hw.capacity_cmd = required_capacity;
|
||||
}
|
||||
|
||||
@ -805,13 +856,15 @@ static void vulkan_init_readback(vk_t *vk)
|
||||
static void *vulkan_init(const video_info_t *video, const input_driver_t **input,
|
||||
void **input_data)
|
||||
{
|
||||
unsigned win_width, win_height, temp_width = 0, temp_height = 0;
|
||||
const gfx_ctx_driver_t *ctx_driver = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
gfx_ctx_mode_t mode;
|
||||
gfx_ctx_input_t inp;
|
||||
unsigned interval;
|
||||
|
||||
unsigned win_width;
|
||||
unsigned win_height;
|
||||
unsigned temp_width = 0;
|
||||
unsigned temp_height = 0;
|
||||
const gfx_ctx_driver_t *ctx_driver = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
vk_t *vk = (vk_t*)calloc(1, sizeof(*vk));
|
||||
if (!vk)
|
||||
return NULL;
|
||||
@ -867,8 +920,10 @@ static void *vulkan_init(const video_info_t *video, const input_driver_t **input
|
||||
|
||||
vk->vsync = video->vsync;
|
||||
vk->fullscreen = video->fullscreen;
|
||||
vk->tex_w = vk->tex_h = RARCH_SCALE_BASE * video->input_scale;
|
||||
vk->tex_fmt = video->rgb32 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
vk->tex_w = RARCH_SCALE_BASE * video->input_scale;
|
||||
vk->tex_h = RARCH_SCALE_BASE * video->input_scale;
|
||||
vk->tex_fmt = video->rgb32
|
||||
? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
vk->keep_aspect = video->force_aspect;
|
||||
|
||||
/* Set the viewport to fix recording, since it needs to know
|
||||
@ -931,9 +986,9 @@ static void vulkan_check_swapchain(vk_t *vk)
|
||||
|
||||
static void vulkan_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
unsigned interval;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned interval;
|
||||
|
||||
if (!vk)
|
||||
return;
|
||||
@ -951,9 +1006,11 @@ static void vulkan_set_nonblock_state(void *data, bool state)
|
||||
static bool vulkan_alive(void *data)
|
||||
{
|
||||
gfx_ctx_size_t size_data;
|
||||
unsigned temp_width = 0, temp_height = 0;
|
||||
unsigned temp_width = 0;
|
||||
unsigned temp_height = 0;
|
||||
bool ret = false;
|
||||
bool quit = false, resize = false;
|
||||
bool quit = false;
|
||||
bool resize = false;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
|
||||
video_driver_get_size(&temp_width, &temp_height);
|
||||
@ -998,7 +1055,8 @@ static bool vulkan_has_windowed(void *data)
|
||||
return gfx_ctx_ctl(GFX_CTL_HAS_WINDOWED, NULL);
|
||||
}
|
||||
|
||||
static bool vulkan_set_shader(void *data, enum rarch_shader_type type, const char *path)
|
||||
static bool vulkan_set_shader(void *data,
|
||||
enum rarch_shader_type type, const char *path)
|
||||
{
|
||||
vk_t *vk = (vk_t*)data;
|
||||
if (!vk)
|
||||
@ -1030,7 +1088,8 @@ static bool vulkan_set_shader(void *data, enum rarch_shader_type type, const cha
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vulkan_set_projection(vk_t *vk, struct gfx_ortho *ortho, bool allow_rotate)
|
||||
static void vulkan_set_projection(vk_t *vk,
|
||||
struct gfx_ortho *ortho, bool allow_rotate)
|
||||
{
|
||||
math_matrix_4x4 rot;
|
||||
|
||||
@ -1060,7 +1119,8 @@ static void vulkan_set_rotation(void *data, unsigned rotation)
|
||||
vulkan_set_projection(vk, &ortho, true);
|
||||
}
|
||||
|
||||
static void vulkan_set_video_mode(void *data, unsigned width, unsigned height,
|
||||
static void vulkan_set_video_mode(void *data,
|
||||
unsigned width, unsigned height,
|
||||
bool fullscreen)
|
||||
{
|
||||
(void)data;
|
||||
@ -1078,7 +1138,8 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width,
|
||||
{
|
||||
gfx_ctx_aspect_t aspect_data;
|
||||
unsigned width, height;
|
||||
int x = 0, y = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
float device_aspect = (float)viewport_width / viewport_height;
|
||||
struct gfx_ortho ortho = {0, 1, 0, 1, -1, 1};
|
||||
settings_t *settings = config_get_ptr();
|
||||
@ -1129,13 +1190,15 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width,
|
||||
}
|
||||
else if (device_aspect > desired_aspect)
|
||||
{
|
||||
delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f;
|
||||
delta = (desired_aspect / device_aspect - 1.0f)
|
||||
/ 2.0f + 0.5f;
|
||||
x = (int)roundf(viewport_width * (0.5f - delta));
|
||||
viewport_width = (unsigned)roundf(2.0f * viewport_width * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f;
|
||||
delta = (device_aspect / desired_aspect - 1.0f)
|
||||
/ 2.0f + 0.5f;
|
||||
y = (int)roundf(viewport_height * (0.5f - delta));
|
||||
viewport_height = (unsigned)roundf(2.0f * viewport_height * delta);
|
||||
}
|
||||
@ -1148,7 +1211,8 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width,
|
||||
}
|
||||
else
|
||||
{
|
||||
vk->vp.x = vk->vp.y = 0;
|
||||
vk->vp.x = 0;
|
||||
vk->vp.y = 0;
|
||||
vk->vp.width = viewport_width;
|
||||
vk->vp.height = viewport_height;
|
||||
}
|
||||
@ -1238,19 +1302,23 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
uint64_t frame_count,
|
||||
unsigned pitch, const char *msg)
|
||||
{
|
||||
struct vk_per_frame *chain;
|
||||
unsigned width, height;
|
||||
VkClearValue clear_value;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
static struct retro_perf_counter frame_run = {0};
|
||||
static struct retro_perf_counter copy_frame = {0};
|
||||
static struct retro_perf_counter swapbuffers = {0};
|
||||
static struct retro_perf_counter queue_submit = {0};
|
||||
struct vk_per_frame *chain;
|
||||
unsigned width, height;
|
||||
VkClearValue clear_value;
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkRenderPassBeginInfo rp_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
unsigned frame_index = vk->context->current_swapchain_index;
|
||||
VkCommandBufferBeginInfo begin_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkRenderPassBeginInfo rp_info = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
unsigned frame_index =
|
||||
vk->context->current_swapchain_index;
|
||||
|
||||
rarch_perf_init(&frame_run, "frame_run");
|
||||
rarch_perf_init(©_frame, "copy_frame");
|
||||
@ -1284,7 +1352,8 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
const uint8_t *src = (const uint8_t*)frame;
|
||||
unsigned bpp = vk->video.rgb32 ? 4 : 2;
|
||||
|
||||
if (chain->texture.width != frame_width || chain->texture.height != frame_height)
|
||||
if ( chain->texture.width != frame_width
|
||||
|| chain->texture.height != frame_height)
|
||||
{
|
||||
chain->texture = vulkan_create_texture(vk, &chain->texture,
|
||||
frame_width, frame_height, chain->texture.format, NULL, NULL,
|
||||
@ -1305,7 +1374,8 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
if (chain->texture.stride == pitch && pitch == frame_width * bpp)
|
||||
memcpy(dst, src, frame_width * frame_height * bpp);
|
||||
else
|
||||
for (y = 0; y < frame_height; y++, dst += chain->texture.stride, src += pitch)
|
||||
for (y = 0; y < frame_height; y++,
|
||||
dst += chain->texture.stride, src += pitch)
|
||||
memcpy(dst, src, frame_width * bpp);
|
||||
}
|
||||
|
||||
@ -1373,7 +1443,8 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
|
||||
vulkan_set_viewport(vk, width, height, false, true);
|
||||
|
||||
vulkan_filter_chain_build_offscreen_passes(vk->filter_chain, vk->cmd, &vk->vk_vp);
|
||||
vulkan_filter_chain_build_offscreen_passes(
|
||||
vk->filter_chain, vk->cmd, &vk->vk_vp);
|
||||
|
||||
/* Render to backbuffer. */
|
||||
clear_value.color.float32[0] = 0.0f;
|
||||
@ -1450,32 +1521,46 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
|
||||
if (vk->readback.pending || vk->readback.streamed)
|
||||
{
|
||||
/* We cannot safely read back from an image which has already been presented
|
||||
* as we need to maintain the PRESENT_SRC_KHR layout.
|
||||
/* We cannot safely read back from an image which
|
||||
* has already been presented as we need to
|
||||
* maintain the PRESENT_SRC_KHR layout.
|
||||
*
|
||||
* If we're reading back, perform the readback before presenting.
|
||||
*/
|
||||
vulkan_image_layout_transition(vk, vk->cmd, chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
vulkan_image_layout_transition(vk,
|
||||
vk->cmd, chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
vulkan_readback(vk);
|
||||
|
||||
/* Prepare for presentation after transfers are complete. */
|
||||
vulkan_image_layout_transition(vk, vk->cmd, chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_MEMORY_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
vulkan_image_layout_transition(vk, vk->cmd,
|
||||
chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_ACCESS_MEMORY_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
|
||||
vk->readback.pending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prepare backbuffer for presentation. */
|
||||
vulkan_image_layout_transition(vk, vk->cmd, chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
vulkan_image_layout_transition(vk, vk->cmd,
|
||||
chain->backbuffer.image,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_MEMORY_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
}
|
||||
|
||||
vkEndCommandBuffer(vk->cmd);
|
||||
@ -1505,14 +1590,18 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
submit_info.pWaitDstStageMask = vk->hw.wait_dst_stages;
|
||||
}
|
||||
|
||||
submit_info.signalSemaphoreCount = vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE ? 1 : 0;
|
||||
submit_info.pSignalSemaphores = &vk->context->swapchain_semaphores[frame_index];
|
||||
submit_info.signalSemaphoreCount =
|
||||
vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE ? 1 : 0;
|
||||
submit_info.pSignalSemaphores =
|
||||
&vk->context->swapchain_semaphores[frame_index];
|
||||
|
||||
retro_perf_stop(&frame_run);
|
||||
|
||||
retro_perf_start(&queue_submit);
|
||||
|
||||
slock_lock(vk->context->queue_lock);
|
||||
vkQueueSubmit(vk->context->queue, 1, &submit_info, vk->context->swapchain_fences[frame_index]);
|
||||
vkQueueSubmit(vk->context->queue, 1,
|
||||
&submit_info, vk->context->swapchain_fences[frame_index]);
|
||||
slock_unlock(vk->context->queue_lock);
|
||||
retro_perf_stop(&queue_submit);
|
||||
|
||||
@ -1564,7 +1653,8 @@ static void vulkan_set_aspect_ratio(void *data, unsigned aspect_ratio_idx)
|
||||
if (cmd != RARCH_DISPLAY_CTL_NONE)
|
||||
video_driver_ctl(cmd, NULL);
|
||||
|
||||
video_driver_set_aspect_ratio_value(aspectratio_lut[aspect_ratio_idx].value);
|
||||
video_driver_set_aspect_ratio_value(
|
||||
aspectratio_lut[aspect_ratio_idx].value);
|
||||
|
||||
if (!vk)
|
||||
return;
|
||||
@ -1595,10 +1685,11 @@ static struct video_shader *vulkan_get_current_shader(void *data)
|
||||
return vulkan_filter_chain_get_preset(vk->filter_chain);
|
||||
}
|
||||
|
||||
static bool vulkan_get_current_sw_framebuffer(void *data, struct retro_framebuffer *framebuffer)
|
||||
static bool vulkan_get_current_sw_framebuffer(void *data,
|
||||
struct retro_framebuffer *framebuffer)
|
||||
{
|
||||
vk_t *vk = (vk_t*)data;
|
||||
struct vk_per_frame *chain;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
vk->chain = &vk->swapchain[vk->context->current_swapchain_index];
|
||||
chain = vk->chain;
|
||||
|
||||
@ -1620,10 +1711,12 @@ static bool vulkan_get_current_sw_framebuffer(void *data, struct retro_framebuff
|
||||
|
||||
framebuffer->data = chain->texture.mapped;
|
||||
framebuffer->pitch = chain->texture.stride;
|
||||
framebuffer->format = vk->video.rgb32 ? RETRO_PIXEL_FORMAT_XRGB8888 : RETRO_PIXEL_FORMAT_RGB565;
|
||||
framebuffer->format = vk->video.rgb32
|
||||
? RETRO_PIXEL_FORMAT_XRGB8888 : RETRO_PIXEL_FORMAT_RGB565;
|
||||
|
||||
framebuffer->memory_flags = 0;
|
||||
if (vk->context->memory_properties.memoryTypes[chain->texture.memory_type].propertyFlags &
|
||||
if (vk->context->memory_properties.memoryTypes[
|
||||
chain->texture.memory_type].propertyFlags &
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
|
||||
{
|
||||
framebuffer->memory_flags |= RETRO_MEMORY_TYPE_CACHED;
|
||||
@ -1632,7 +1725,8 @@ static bool vulkan_get_current_sw_framebuffer(void *data, struct retro_framebuff
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vulkan_get_hw_render_interface(void *data, const struct retro_hw_render_interface **iface)
|
||||
static bool vulkan_get_hw_render_interface(void *data,
|
||||
const struct retro_hw_render_interface **iface)
|
||||
{
|
||||
vk_t *vk = (vk_t*)data;
|
||||
*iface = (const struct retro_hw_render_interface*)&vk->hw.iface;
|
||||
@ -1644,13 +1738,12 @@ static void vulkan_set_texture_frame(void *data,
|
||||
const void *frame, bool rgb32, unsigned width, unsigned height,
|
||||
float alpha)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
unsigned x, y;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
unsigned index = vk->context->current_swapchain_index;
|
||||
struct vk_texture *texture = &vk->menu.textures[index];
|
||||
struct vk_texture *texture_optimal = &vk->menu.textures_optimal[index];
|
||||
|
||||
uint8_t *ptr;
|
||||
unsigned x, y;
|
||||
const VkComponentMapping br_swizzle = {
|
||||
VK_COMPONENT_SWIZZLE_B,
|
||||
VK_COMPONENT_SWIZZLE_G,
|
||||
@ -1719,8 +1812,6 @@ static uintptr_t vulkan_load_texture(void *video_data, void *data,
|
||||
{
|
||||
vk_t *vk = (vk_t*)video_data;
|
||||
struct texture_image *image = (struct texture_image*)data;
|
||||
(void)threaded; /* Pfft. */
|
||||
|
||||
struct vk_texture *texture = (struct vk_texture*)calloc(1, sizeof(*texture));
|
||||
if (!texture)
|
||||
return 0;
|
||||
@ -1787,8 +1878,8 @@ static void vulkan_get_poke_interface(void *data,
|
||||
|
||||
static void vulkan_viewport_info(void *data, struct video_viewport *vp)
|
||||
{
|
||||
vk_t *vk = (vk_t*)data;
|
||||
unsigned width, height;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
|
||||
video_driver_get_size(&width, &height);
|
||||
|
||||
@ -1851,7 +1942,8 @@ static bool vulkan_read_viewport(void *data, uint8_t *buffer)
|
||||
{
|
||||
unsigned x, y;
|
||||
const uint8_t *src = (const uint8_t*)staging->mapped;
|
||||
buffer += 3 * (vk->vp.height - 1) * vk->vp.width;
|
||||
buffer += 3 * (vk->vp.height - 1)
|
||||
* vk->vp.width;
|
||||
|
||||
for (y = 0; y < vk->vp.height; y++,
|
||||
src += staging->stride, buffer -= 3 * vk->vp.width)
|
||||
@ -1899,16 +1991,18 @@ static void vulkan_overlay_free(vk_t *vk)
|
||||
free(vk->overlay.vertex);
|
||||
for (i = 0; i < vk->overlay.count; i++)
|
||||
if (vk->overlay.images[i].memory != VK_NULL_HANDLE)
|
||||
vulkan_destroy_texture(vk->context->device, &vk->overlay.images[i]);
|
||||
vulkan_destroy_texture(vk->context->device,
|
||||
&vk->overlay.images[i]);
|
||||
|
||||
memset(&vk->overlay, 0, sizeof(vk->overlay));
|
||||
}
|
||||
|
||||
static void vulkan_overlay_set_alpha(void *data, unsigned image, float mod)
|
||||
static void vulkan_overlay_set_alpha(void *data,
|
||||
unsigned image, float mod)
|
||||
{
|
||||
vk_t *vk = (vk_t*)data;
|
||||
struct vk_vertex *pv;
|
||||
unsigned i;
|
||||
struct vk_vertex *pv;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
|
||||
if (!vk)
|
||||
return;
|
||||
@ -1944,7 +2038,8 @@ static void vulkan_render_overlay(vk_t *vk)
|
||||
4 * sizeof(struct vk_vertex), &range))
|
||||
break;
|
||||
|
||||
memcpy(range.data, &vk->overlay.vertex[i * 4], 4 * sizeof(struct vk_vertex));
|
||||
memcpy(range.data, &vk->overlay.vertex[i * 4],
|
||||
4 * sizeof(struct vk_vertex));
|
||||
|
||||
memset(&call, 0, sizeof(call));
|
||||
call.pipeline = vk->display.pipelines[3]; /* Strip with blend */
|
||||
@ -1964,11 +2059,13 @@ static void vulkan_overlay_vertex_geom(void *data, unsigned image,
|
||||
float x, float y,
|
||||
float w, float h)
|
||||
{
|
||||
struct vk_vertex *pv = NULL;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
if (!vk)
|
||||
return;
|
||||
|
||||
struct vk_vertex *pv = &vk->overlay.vertex[4 * image];
|
||||
pv = &vk->overlay.vertex[4 * image];
|
||||
|
||||
pv[0].x = x;
|
||||
pv[0].y = y;
|
||||
pv[1].x = x;
|
||||
@ -1983,11 +2080,13 @@ static void vulkan_overlay_tex_geom(void *data, unsigned image,
|
||||
float x, float y,
|
||||
float w, float h)
|
||||
{
|
||||
struct vk_vertex *pv = NULL;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
if (!vk)
|
||||
return;
|
||||
|
||||
struct vk_vertex *pv = &vk->overlay.vertex[4 * image];
|
||||
pv = &vk->overlay.vertex[4 * image];
|
||||
|
||||
pv[0].tex_x = x;
|
||||
pv[0].tex_y = y;
|
||||
pv[1].tex_x = x;
|
||||
@ -2001,9 +2100,10 @@ static void vulkan_overlay_tex_geom(void *data, unsigned image,
|
||||
static bool vulkan_overlay_load(void *data,
|
||||
const void *image_data, unsigned num_images)
|
||||
{
|
||||
const struct texture_image *images = (const struct texture_image*)image_data;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
unsigned i, j;
|
||||
const struct texture_image *images =
|
||||
(const struct texture_image*)image_data;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
static const struct vk_color white = {
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
};
|
||||
@ -2016,12 +2116,15 @@ static bool vulkan_overlay_load(void *data,
|
||||
slock_unlock(vk->context->queue_lock);
|
||||
vulkan_overlay_free(vk);
|
||||
|
||||
vk->overlay.images = (struct vk_texture*)calloc(num_images, sizeof(*vk->overlay.images));
|
||||
vk->overlay.images = (struct vk_texture*)
|
||||
calloc(num_images, sizeof(*vk->overlay.images));
|
||||
|
||||
if (!vk->overlay.images)
|
||||
goto error;
|
||||
vk->overlay.count = num_images;
|
||||
|
||||
vk->overlay.vertex = (struct vk_vertex*)calloc(4 * num_images, sizeof(*vk->overlay.vertex));
|
||||
vk->overlay.vertex = (struct vk_vertex*)
|
||||
calloc(4 * num_images, sizeof(*vk->overlay.vertex));
|
||||
if (!vk->overlay.vertex)
|
||||
goto error;
|
||||
|
||||
|
@ -801,21 +801,23 @@ static bool gfx_ctx_x_bind_api(void *data, enum gfx_ctx_api api,
|
||||
|
||||
g_major = major;
|
||||
g_minor = minor;
|
||||
g_api = api;
|
||||
|
||||
#ifdef HAVE_VULKAN
|
||||
if (api == GFX_CTX_VULKAN_API)
|
||||
switch (api)
|
||||
{
|
||||
g_api = api;
|
||||
case GFX_CTX_OPENGL_API:
|
||||
#ifdef HAVE_OPENGL
|
||||
g_api = GFX_CTX_OPENGL_API;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
#ifdef HAVE_OPENGLES2
|
||||
{
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
const char *exts = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
|
||||
bool ret = api == GFX_CTX_OPENGL_ES_API &&
|
||||
exts && strstr(exts, "GLX_EXT_create_context_es2_profile");
|
||||
bool ret = exts && strstr(exts,
|
||||
"GLX_EXT_create_context_es2_profile");
|
||||
XCloseDisplay(dpy);
|
||||
if (ret && g_major < 3)
|
||||
{
|
||||
@ -824,10 +826,23 @@ static bool gfx_ctx_x_bind_api(void *data, enum gfx_ctx_api api,
|
||||
}
|
||||
g_api = GFX_CTX_OPENGL_ES_API;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
g_api = GFX_CTX_OPENGL_API;
|
||||
return api == GFX_CTX_OPENGL_API;
|
||||
break;
|
||||
#endif
|
||||
case GFX_CTX_VULKAN_API:
|
||||
#ifdef HAVE_VULKAN
|
||||
g_api = api;
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_x_show_mouse(void *data, bool state)
|
||||
|
@ -28,7 +28,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
static uint32_t find_memory_type(const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
static uint32_t find_memory_type(
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
uint32_t device_reqs, uint32_t host_reqs)
|
||||
{
|
||||
uint32_t i;
|
||||
@ -43,7 +44,8 @@ static uint32_t find_memory_type(const VkPhysicalDeviceMemoryProperties &mem_pro
|
||||
abort();
|
||||
}
|
||||
|
||||
static uint32_t find_memory_type_fallback(const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
static uint32_t find_memory_type_fallback(
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
uint32_t device_reqs, uint32_t host_reqs)
|
||||
{
|
||||
uint32_t i;
|
||||
@ -113,7 +115,8 @@ class DeferredDisposer
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer(VkDevice device, const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
Buffer(VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
size_t size, VkBufferUsageFlags usage);
|
||||
~Buffer();
|
||||
|
||||
@ -133,7 +136,8 @@ class Buffer
|
||||
class Framebuffer
|
||||
{
|
||||
public:
|
||||
Framebuffer(VkDevice device, const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
Framebuffer(VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
const Size2D &max_size, VkFormat format);
|
||||
|
||||
~Framebuffer();
|
||||
@ -174,7 +178,8 @@ class Framebuffer
|
||||
class Pass
|
||||
{
|
||||
public:
|
||||
Pass(VkDevice device, const VkPhysicalDeviceMemoryProperties &memory_properties,
|
||||
Pass(VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &memory_properties,
|
||||
VkPipelineCache cache, unsigned num_sync_indices, bool final_pass) :
|
||||
device(device),
|
||||
memory_properties(memory_properties),
|
||||
@ -239,7 +244,8 @@ class Pass
|
||||
unsigned sync_index;
|
||||
bool final_pass;
|
||||
|
||||
Size2D get_output_size(const Size2D &original_size, const Size2D &max_source) const;
|
||||
Size2D get_output_size(const Size2D &original_size,
|
||||
const Size2D &max_source) const;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
||||
@ -302,17 +308,20 @@ struct vulkan_filter_chain
|
||||
return shader_preset.get();
|
||||
}
|
||||
|
||||
void set_pass_info(unsigned pass, const vulkan_filter_chain_pass_info &info);
|
||||
void set_pass_info(unsigned pass,
|
||||
const vulkan_filter_chain_pass_info &info);
|
||||
void set_shader(unsigned pass, VkShaderStageFlags stage,
|
||||
const uint32_t *spirv, size_t spirv_words);
|
||||
|
||||
bool init();
|
||||
bool update_swapchain_info(const vulkan_filter_chain_swapchain_info &info);
|
||||
bool update_swapchain_info(
|
||||
const vulkan_filter_chain_swapchain_info &info);
|
||||
|
||||
void notify_sync_index(unsigned index);
|
||||
void set_input_texture(const vulkan_filter_chain_texture &texture);
|
||||
void build_offscreen_passes(VkCommandBuffer cmd, const VkViewport &vp);
|
||||
void build_viewport_pass(VkCommandBuffer cmd, const VkViewport &vp, const float *mvp);
|
||||
void build_viewport_pass(VkCommandBuffer cmd,
|
||||
const VkViewport &vp, const float *mvp);
|
||||
|
||||
private:
|
||||
VkDevice device;
|
||||
@ -338,7 +347,8 @@ struct vulkan_filter_chain
|
||||
void set_swapchain_info(const vulkan_filter_chain_swapchain_info &info);
|
||||
};
|
||||
|
||||
vulkan_filter_chain::vulkan_filter_chain(const vulkan_filter_chain_create_info &info)
|
||||
vulkan_filter_chain::vulkan_filter_chain(
|
||||
const vulkan_filter_chain_create_info &info)
|
||||
: device(info.device),
|
||||
memory_properties(*info.memory_properties),
|
||||
cache(info.pipeline_cache)
|
||||
@ -353,7 +363,8 @@ vulkan_filter_chain::~vulkan_filter_chain()
|
||||
flush();
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::set_swapchain_info(const vulkan_filter_chain_swapchain_info &info)
|
||||
void vulkan_filter_chain::set_swapchain_info(
|
||||
const vulkan_filter_chain_swapchain_info &info)
|
||||
{
|
||||
swapchain_info = info;
|
||||
set_num_sync_indices(info.num_indices);
|
||||
@ -389,7 +400,8 @@ void vulkan_filter_chain::set_num_passes(unsigned num_passes)
|
||||
}
|
||||
}
|
||||
|
||||
bool vulkan_filter_chain::update_swapchain_info(const vulkan_filter_chain_swapchain_info &info)
|
||||
bool vulkan_filter_chain::update_swapchain_info(
|
||||
const vulkan_filter_chain_swapchain_info &info)
|
||||
{
|
||||
flush();
|
||||
set_swapchain_info(info);
|
||||
@ -402,13 +414,17 @@ void vulkan_filter_chain::set_pass_info(unsigned pass,
|
||||
pass_info[pass] = info;
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::set_shader(unsigned pass, VkShaderStageFlags stage,
|
||||
const uint32_t *spirv, size_t spirv_words)
|
||||
void vulkan_filter_chain::set_shader(
|
||||
unsigned pass,
|
||||
VkShaderStageFlags stage,
|
||||
const uint32_t *spirv,
|
||||
size_t spirv_words)
|
||||
{
|
||||
passes[pass]->set_shader(stage, spirv, spirv_words);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::set_input_texture(const vulkan_filter_chain_texture &texture)
|
||||
void vulkan_filter_chain::set_input_texture(
|
||||
const vulkan_filter_chain_texture &texture)
|
||||
{
|
||||
input_texture = texture;
|
||||
}
|
||||
@ -436,7 +452,8 @@ bool vulkan_filter_chain::init()
|
||||
for (unsigned i = 0; i < passes.size(); i++)
|
||||
{
|
||||
auto &pass = passes[i];
|
||||
source = pass->set_pass_info(max_input_size, source, swapchain_info, pass_info[i]);
|
||||
source = pass->set_pass_info(max_input_size,
|
||||
source, swapchain_info, pass_info[i]);
|
||||
if (!pass->build())
|
||||
return false;
|
||||
}
|
||||
@ -447,11 +464,14 @@ bool vulkan_filter_chain::init()
|
||||
void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd,
|
||||
const VkViewport &vp)
|
||||
{
|
||||
unsigned i;
|
||||
DeferredDisposer disposer(deferred_calls[current_sync_index]);
|
||||
const Texture original = { input_texture, passes.front()->get_source_filter() };
|
||||
Texture source = { input_texture, passes.front()->get_source_filter() };
|
||||
const Texture original = {
|
||||
input_texture, passes.front()->get_source_filter() };
|
||||
Texture source = {
|
||||
input_texture, passes.front()->get_source_filter() };
|
||||
|
||||
for (unsigned i = 0; i < passes.size() - 1; i++)
|
||||
for (i = 0; i < passes.size() - 1; i++)
|
||||
{
|
||||
passes[i]->build_commands(disposer, cmd,
|
||||
original, source, vp, nullptr);
|
||||
@ -465,12 +485,13 @@ void vulkan_filter_chain::build_offscreen_passes(VkCommandBuffer cmd,
|
||||
}
|
||||
}
|
||||
|
||||
void vulkan_filter_chain::build_viewport_pass(VkCommandBuffer cmd, const VkViewport &vp, const float *mvp)
|
||||
void vulkan_filter_chain::build_viewport_pass(
|
||||
VkCommandBuffer cmd, const VkViewport &vp, const float *mvp)
|
||||
{
|
||||
DeferredDisposer disposer(deferred_calls[current_sync_index]);
|
||||
|
||||
const Texture original = { input_texture, passes.front()->get_source_filter() };
|
||||
Texture source;
|
||||
DeferredDisposer disposer(deferred_calls[current_sync_index]);
|
||||
const Texture original = {
|
||||
input_texture, passes.front()->get_source_filter() };
|
||||
|
||||
if (passes.size() == 1)
|
||||
source = { input_texture, passes.back()->get_source_filter() };
|
||||
@ -488,7 +509,8 @@ void vulkan_filter_chain::build_viewport_pass(VkCommandBuffer cmd, const VkViewp
|
||||
original, source, vp, mvp);
|
||||
}
|
||||
|
||||
Buffer::Buffer(VkDevice device, const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
Buffer::Buffer(VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
size_t size, VkBufferUsageFlags usage) :
|
||||
device(device), size(size)
|
||||
{
|
||||
@ -504,8 +526,10 @@ Buffer::Buffer(VkDevice device, const VkPhysicalDeviceMemoryProperties &mem_prop
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
|
||||
alloc.memoryTypeIndex = find_memory_type(mem_props, mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
alloc.memoryTypeIndex = find_memory_type(
|
||||
mem_props, mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
|
||||
vkAllocateMemory(device, &alloc, NULL, &memory);
|
||||
vkBindBufferMemory(device, buffer, memory, 0);
|
||||
@ -545,16 +569,19 @@ void Pass::set_shader(VkShaderStageFlags stage,
|
||||
if (stage == VK_SHADER_STAGE_VERTEX_BIT)
|
||||
{
|
||||
vertex_shader.clear();
|
||||
vertex_shader.insert(end(vertex_shader), spirv, spirv + spirv_words);
|
||||
vertex_shader.insert(end(vertex_shader),
|
||||
spirv, spirv + spirv_words);
|
||||
}
|
||||
else if (stage == VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
{
|
||||
fragment_shader.clear();
|
||||
fragment_shader.insert(end(fragment_shader), spirv, spirv + spirv_words);
|
||||
fragment_shader.insert(end(fragment_shader),
|
||||
spirv, spirv + spirv_words);
|
||||
}
|
||||
}
|
||||
|
||||
Size2D Pass::get_output_size(const Size2D &original, const Size2D &source) const
|
||||
Size2D Pass::get_output_size(const Size2D &original,
|
||||
const Size2D &source) const
|
||||
{
|
||||
float width, height;
|
||||
switch (pass_info.scale_type_x)
|
||||
@ -670,28 +697,34 @@ bool Pass::init_pipeline_layout()
|
||||
desc_counts.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 });
|
||||
desc_counts.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 });
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo set_layout_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
VkDescriptorSetLayoutCreateInfo set_layout_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
set_layout_info.bindingCount = bindings.size();
|
||||
set_layout_info.pBindings = bindings.data();
|
||||
|
||||
if (vkCreateDescriptorSetLayout(device, &set_layout_info, NULL, &set_layout) != VK_SUCCESS)
|
||||
if (vkCreateDescriptorSetLayout(device,
|
||||
&set_layout_info, NULL, &set_layout) != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
VkPipelineLayoutCreateInfo layout_info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
VkPipelineLayoutCreateInfo layout_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = &set_layout;
|
||||
|
||||
if (vkCreatePipelineLayout(device, &layout_info, NULL, &pipeline_layout) != VK_SUCCESS)
|
||||
if (vkCreatePipelineLayout(device,
|
||||
&layout_info, NULL, &pipeline_layout) != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
pool_info.maxSets = num_sync_indices;
|
||||
pool_info.poolSizeCount = desc_counts.size();
|
||||
pool_info.pPoolSizes = desc_counts.data();
|
||||
if (vkCreateDescriptorPool(device, &pool_info, nullptr, &pool) != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
VkDescriptorSetAllocateInfo alloc_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
alloc_info.descriptorPool = pool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &set_layout;
|
||||
@ -709,7 +742,8 @@ bool Pass::init_pipeline()
|
||||
return false;
|
||||
|
||||
// Input assembly
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
|
||||
// VAO state
|
||||
@ -729,14 +763,16 @@ bool Pass::init_pipeline()
|
||||
binding.stride = 4 * sizeof(float);
|
||||
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
vertex_input.vertexBindingDescriptionCount = 1;
|
||||
vertex_input.pVertexBindingDescriptions = &binding;
|
||||
vertex_input.vertexAttributeDescriptionCount = 2;
|
||||
vertex_input.pVertexAttributeDescriptions = attributes;
|
||||
|
||||
// Raster state
|
||||
VkPipelineRasterizationStateCreateInfo raster = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
||||
VkPipelineRasterizationStateCreateInfo raster = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
||||
raster.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
raster.cullMode = VK_CULL_MODE_NONE;
|
||||
raster.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
@ -747,19 +783,22 @@ bool Pass::init_pipeline()
|
||||
|
||||
// Blend state
|
||||
VkPipelineColorBlendAttachmentState blend_attachment = {0};
|
||||
VkPipelineColorBlendStateCreateInfo blend = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
||||
VkPipelineColorBlendStateCreateInfo blend = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
||||
blend_attachment.blendEnable = false;
|
||||
blend_attachment.colorWriteMask = 0xf;
|
||||
blend.attachmentCount = 1;
|
||||
blend.pAttachments = &blend_attachment;
|
||||
|
||||
// Viewport state
|
||||
VkPipelineViewportStateCreateInfo viewport = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||
VkPipelineViewportStateCreateInfo viewport = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||
viewport.viewportCount = 1;
|
||||
viewport.scissorCount = 1;
|
||||
|
||||
// Depth-stencil state
|
||||
VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
||||
VkPipelineDepthStencilStateCreateInfo depth_stencil = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
||||
depth_stencil.depthTestEnable = false;
|
||||
depth_stencil.depthWriteEnable = false;
|
||||
depth_stencil.depthBoundsTestEnable = false;
|
||||
@ -768,12 +807,15 @@ bool Pass::init_pipeline()
|
||||
depth_stencil.maxDepthBounds = 1.0f;
|
||||
|
||||
// Multisample state
|
||||
VkPipelineMultisampleStateCreateInfo multisample = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
VkPipelineMultisampleStateCreateInfo multisample = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
// Dynamic state
|
||||
VkPipelineDynamicStateCreateInfo dynamic = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||
static const VkDynamicState dynamics[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||
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.dynamicStateCount = sizeof(dynamics) / sizeof(dynamics[0]);
|
||||
|
||||
@ -783,7 +825,8 @@ bool Pass::init_pipeline()
|
||||
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO },
|
||||
};
|
||||
|
||||
VkShaderModuleCreateInfo module_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
|
||||
VkShaderModuleCreateInfo module_info = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
|
||||
module_info.codeSize = vertex_shader.size() * sizeof(uint32_t);
|
||||
module_info.pCode = vertex_shader.data();
|
||||
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
@ -796,7 +839,8 @@ bool Pass::init_pipeline()
|
||||
shader_stages[1].pName = "main";
|
||||
vkCreateShaderModule(device, &module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||
VkGraphicsPipelineCreateInfo pipe = {
|
||||
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||
pipe.stageCount = 2;
|
||||
pipe.pStages = shader_stages;
|
||||
pipe.pVertexInputState = &vertex_input;
|
||||
@ -807,10 +851,12 @@ bool Pass::init_pipeline()
|
||||
pipe.pViewportState = &viewport;
|
||||
pipe.pDepthStencilState = &depth_stencil;
|
||||
pipe.pDynamicState = &dynamic;
|
||||
pipe.renderPass = final_pass ? swapchain_render_pass : framebuffer->get_render_pass();
|
||||
pipe.renderPass = final_pass ? swapchain_render_pass :
|
||||
framebuffer->get_render_pass();
|
||||
pipe.layout = pipeline_layout;
|
||||
|
||||
if (vkCreateGraphicsPipelines(device, cache, 1, &pipe, NULL, &pipeline) != VK_SUCCESS)
|
||||
if (vkCreateGraphicsPipelines(device,
|
||||
cache, 1, &pipe, NULL, &pipeline) != VK_SUCCESS)
|
||||
{
|
||||
vkDestroyShaderModule(device, shader_stages[0].module, NULL);
|
||||
vkDestroyShaderModule(device, shader_stages[1].module, NULL);
|
||||
@ -839,13 +885,15 @@ bool Pass::init_samplers()
|
||||
info.unnormalizedCoordinates = false;
|
||||
info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
|
||||
if (vkCreateSampler(device, &info, NULL, &samplers[VULKAN_FILTER_CHAIN_NEAREST]) != VK_SUCCESS)
|
||||
if (vkCreateSampler(device,
|
||||
&info, NULL, &samplers[VULKAN_FILTER_CHAIN_NEAREST]) != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
info.minFilter = VK_FILTER_LINEAR;
|
||||
|
||||
if (vkCreateSampler(device, &info, NULL, &samplers[VULKAN_FILTER_CHAIN_LINEAR]) != VK_SUCCESS)
|
||||
if (vkCreateSampler(device,
|
||||
&info, NULL, &samplers[VULKAN_FILTER_CHAIN_LINEAR]) != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -853,6 +901,7 @@ bool Pass::init_samplers()
|
||||
|
||||
bool Pass::init_buffers()
|
||||
{
|
||||
unsigned i;
|
||||
// The final pass uses an MVP designed for [0, 1] range VBO.
|
||||
// For in-between passes, we just go with identity matrices, so keep it simple.
|
||||
float pos_min = final_pass ? 0.0f : -1.0f;
|
||||
@ -865,9 +914,11 @@ bool Pass::init_buffers()
|
||||
};
|
||||
|
||||
ubos.clear();
|
||||
for (unsigned i = 0; i < num_sync_indices; i++)
|
||||
ubos.emplace_back(new Buffer(device, memory_properties, sizeof(UBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
|
||||
vbo = unique_ptr<Buffer>(new Buffer(device, memory_properties, sizeof(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
|
||||
for (i = 0; i < num_sync_indices; i++)
|
||||
ubos.emplace_back(new Buffer(device,
|
||||
memory_properties, sizeof(UBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
|
||||
vbo = unique_ptr<Buffer>(new Buffer(device,
|
||||
memory_properties, sizeof(vbo_data), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
|
||||
|
||||
void *ptr = vbo->map();
|
||||
memcpy(ptr, vbo_data, sizeof(vbo_data));
|
||||
@ -880,7 +931,8 @@ bool Pass::build()
|
||||
if (!final_pass)
|
||||
{
|
||||
framebuffer = unique_ptr<Framebuffer>(
|
||||
new Framebuffer(device, memory_properties, current_framebuffer_size,
|
||||
new Framebuffer(device, memory_properties,
|
||||
current_framebuffer_size,
|
||||
pass_info.rt_format));
|
||||
}
|
||||
|
||||
@ -966,7 +1018,8 @@ void Pass::update_descriptor_set(
|
||||
const Texture &original,
|
||||
const Texture &source)
|
||||
{
|
||||
set_uniform_buffer(sets[sync_index], 0, ubos[sync_index]->get_buffer(), 0, sizeof(UBO));
|
||||
set_uniform_buffer(sets[sync_index], 0,
|
||||
ubos[sync_index]->get_buffer(), 0, sizeof(UBO));
|
||||
set_texture(sets[sync_index], 1, original);
|
||||
set_texture(sets[sync_index], 2, source);
|
||||
}
|
||||
@ -984,7 +1037,8 @@ void Pass::build_commands(
|
||||
{ original.texture.width, original.texture.height },
|
||||
{ source.texture.width, source.texture.height });
|
||||
|
||||
if (size.width != current_framebuffer_size.width || size.height != current_framebuffer_size.height)
|
||||
if ( size.width != current_framebuffer_size.width
|
||||
|| size.height != current_framebuffer_size.height)
|
||||
{
|
||||
if (framebuffer)
|
||||
framebuffer->set_size(disposer, size);
|
||||
@ -997,25 +1051,35 @@ void Pass::build_commands(
|
||||
memcpy(u->MVP, mvp, sizeof(float) * 16);
|
||||
else
|
||||
build_identity_matrix(u->MVP);
|
||||
build_vec4(u->output_size, current_framebuffer_size.width, current_framebuffer_size.height);
|
||||
build_vec4(u->original_size, original.texture.width, original.texture.height);
|
||||
build_vec4(u->source_size, source.texture.width, source.texture.height);
|
||||
build_vec4(u->output_size,
|
||||
current_framebuffer_size.width,
|
||||
current_framebuffer_size.height);
|
||||
build_vec4(u->original_size,
|
||||
original.texture.width, original.texture.height);
|
||||
build_vec4(u->source_size,
|
||||
source.texture.width, source.texture.height);
|
||||
ubos[sync_index]->unmap();
|
||||
|
||||
update_descriptor_set(original, source);
|
||||
|
||||
// The final pass is always executed inside another render pass since
|
||||
// the frontend will want to overlay various things on top for the passes that end
|
||||
// up on-screen.
|
||||
// The final pass is always executed inside
|
||||
// another render pass since the frontend will
|
||||
// want to overlay various things on top for
|
||||
// the passes that end up on-screen.
|
||||
if (!final_pass)
|
||||
{
|
||||
// Render.
|
||||
image_layout_transition(device, cmd, framebuffer->get_image(),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
image_layout_transition(device, cmd,
|
||||
framebuffer->get_image(),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
|
||||
VkRenderPassBeginInfo rp_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||
VkRenderPassBeginInfo rp_info = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||
VkClearValue clear_value;
|
||||
clear_value.color.float32[0] = 0.0f;
|
||||
clear_value.color.float32[1] = 0.0f;
|
||||
@ -1040,8 +1104,14 @@ void Pass::build_commands(
|
||||
if (final_pass)
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{ int32_t(current_viewport.x), int32_t(current_viewport.y) },
|
||||
{ uint32_t(current_viewport.width), uint32_t(current_viewport.height) },
|
||||
{
|
||||
int32_t(current_viewport.x),
|
||||
int32_t(current_viewport.y)
|
||||
},
|
||||
{
|
||||
uint32_t(current_viewport.width),
|
||||
uint32_t(current_viewport.height)
|
||||
},
|
||||
};
|
||||
vkCmdSetViewport(cmd, 0, 1, ¤t_viewport);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
@ -1050,12 +1120,16 @@ void Pass::build_commands(
|
||||
{
|
||||
const VkViewport vp = {
|
||||
0.0f, 0.0f,
|
||||
float(current_framebuffer_size.width), float(current_framebuffer_size.height),
|
||||
float(current_framebuffer_size.width),
|
||||
float(current_framebuffer_size.height),
|
||||
0.0f, 1.0f
|
||||
};
|
||||
const VkRect2D sci = {
|
||||
{ 0, 0 },
|
||||
{ current_framebuffer_size.width, current_framebuffer_size.height },
|
||||
{
|
||||
current_framebuffer_size.width,
|
||||
current_framebuffer_size.height
|
||||
},
|
||||
};
|
||||
|
||||
vkCmdSetViewport(cmd, 0, 1, &vp);
|
||||
@ -1069,27 +1143,37 @@ void Pass::build_commands(
|
||||
vkCmdEndRenderPass(cmd);
|
||||
|
||||
// Barrier to sync with next pass.
|
||||
image_layout_transition(device, cmd, framebuffer->get_image(),
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
image_layout_transition(
|
||||
device,
|
||||
cmd,
|
||||
framebuffer->get_image(),
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
Framebuffer::Framebuffer(VkDevice device, const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
Framebuffer::Framebuffer(
|
||||
VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
const Size2D &max_size, VkFormat format) :
|
||||
device(device),
|
||||
memory_properties(mem_props),
|
||||
size(max_size),
|
||||
format(format)
|
||||
{
|
||||
RARCH_LOG("[Vulkan filter chain]: Creating framebuffer %u x %u.\n", max_size.width, max_size.height);
|
||||
RARCH_LOG("[Vulkan filter chain]: Creating framebuffer %u x %u.\n",
|
||||
max_size.width, max_size.height);
|
||||
init_render_pass();
|
||||
init(nullptr);
|
||||
}
|
||||
|
||||
void Framebuffer::init(DeferredDisposer *disposer)
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
info.imageType = VK_IMAGE_TYPE_2D;
|
||||
info.format = format;
|
||||
@ -1100,17 +1184,18 @@ void Framebuffer::init(DeferredDisposer *disposer)
|
||||
info.arrayLayers = 1;
|
||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
vkCreateImage(device, &info, nullptr, &image);
|
||||
|
||||
VkMemoryRequirements mem_reqs;
|
||||
vkGetImageMemoryRequirements(device, image, &mem_reqs);
|
||||
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = find_memory_type_fallback(memory_properties, mem_reqs.memoryTypeBits,
|
||||
alloc.memoryTypeIndex = find_memory_type_fallback(
|
||||
memory_properties, mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
// Can reuse already allocated memory.
|
||||
@ -1132,7 +1217,8 @@ void Framebuffer::init(DeferredDisposer *disposer)
|
||||
|
||||
vkBindImageMemory(device, image, memory.memory, 0);
|
||||
|
||||
VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkImageViewCreateInfo view_info = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view_info.format = format;
|
||||
view_info.image = image;
|
||||
@ -1152,8 +1238,10 @@ void Framebuffer::init(DeferredDisposer *disposer)
|
||||
|
||||
void Framebuffer::init_render_pass()
|
||||
{
|
||||
VkRenderPassCreateInfo rp_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
|
||||
VkAttachmentReference color_ref = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
|
||||
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.
|
||||
@ -1183,7 +1271,8 @@ void Framebuffer::init_render_pass()
|
||||
|
||||
void Framebuffer::init_framebuffer()
|
||||
{
|
||||
VkFramebufferCreateInfo info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
VkFramebufferCreateInfo info = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
info.renderPass = render_pass;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &view;
|
||||
@ -1198,7 +1287,8 @@ void Framebuffer::set_size(DeferredDisposer &disposer, const Size2D &size)
|
||||
{
|
||||
this->size = size;
|
||||
|
||||
RARCH_LOG("[Vulkan filter chain]: Updating framebuffer size %u x %u.\n", size.width, size.height);
|
||||
RARCH_LOG("[Vulkan filter chain]: Updating framebuffer size %u x %u.\n",
|
||||
size.width, size.height);
|
||||
|
||||
{
|
||||
// The current framebuffers, etc, might still be in use
|
||||
@ -1247,8 +1337,11 @@ vulkan_filter_chain_t *vulkan_filter_chain_new(
|
||||
return new vulkan_filter_chain(*info);
|
||||
}
|
||||
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_default(const struct vulkan_filter_chain_create_info *info, vulkan_filter_chain_filter filter)
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_default(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain_filter filter)
|
||||
{
|
||||
struct vulkan_filter_chain_pass_info pass_info;
|
||||
auto tmpinfo = *info;
|
||||
tmpinfo.num_passes = 1;
|
||||
|
||||
@ -1256,7 +1349,6 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_default(const struct vulkan_fi
|
||||
if (!chain)
|
||||
return nullptr;
|
||||
|
||||
struct vulkan_filter_chain_pass_info pass_info;
|
||||
memset(&pass_info, 0, sizeof(pass_info));
|
||||
pass_info.scale_type_x = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
|
||||
pass_info.scale_type_y = VULKAN_FILTER_CHAIN_SCALE_VIEWPORT;
|
||||
@ -1266,8 +1358,12 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_default(const struct vulkan_fi
|
||||
pass_info.source_filter = filter;
|
||||
chain->set_pass_info(0, pass_info);
|
||||
|
||||
chain->set_shader(0, VK_SHADER_STAGE_VERTEX_BIT, (const uint32_t*)opaque_vert_spv, opaque_vert_spv_len / sizeof(uint32_t));
|
||||
chain->set_shader(0, VK_SHADER_STAGE_FRAGMENT_BIT, (const uint32_t*)opaque_frag_spv, opaque_frag_spv_len / sizeof(uint32_t));
|
||||
chain->set_shader(0, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
(const uint32_t*)opaque_vert_spv,
|
||||
opaque_vert_spv_len / sizeof(uint32_t));
|
||||
chain->set_shader(0, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
(const uint32_t*)opaque_frag_spv,
|
||||
opaque_frag_spv_len / sizeof(uint32_t));
|
||||
|
||||
if (!chain->init())
|
||||
return nullptr;
|
||||
@ -1284,7 +1380,8 @@ struct ConfigDeleter
|
||||
}
|
||||
};
|
||||
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
const char *path, vulkan_filter_chain_filter filter)
|
||||
{
|
||||
unique_ptr<video_shader> shader{ new video_shader() };
|
||||
@ -1318,7 +1415,8 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(const struct vulka
|
||||
glslang_output output;
|
||||
if (!glslang_compile_shader(pass->source.path, &output))
|
||||
{
|
||||
RARCH_ERR("Failed to compile shader: \"%s\".\n", pass->source.path);
|
||||
RARCH_ERR("Failed to compile shader: \"%s\".\n",
|
||||
pass->source.path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1343,11 +1441,17 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(const struct vulka
|
||||
|
||||
if (!pass->fbo.valid)
|
||||
{
|
||||
pass_info.scale_type_x = i + 1 == shader->passes ? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT : VULKAN_FILTER_CHAIN_SCALE_SOURCE;
|
||||
pass_info.scale_type_y = i + 1 == shader->passes ? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT : VULKAN_FILTER_CHAIN_SCALE_SOURCE;
|
||||
pass_info.scale_type_x = i + 1 == shader->passes
|
||||
? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT
|
||||
: VULKAN_FILTER_CHAIN_SCALE_SOURCE;
|
||||
pass_info.scale_type_y = i + 1 == shader->passes
|
||||
? VULKAN_FILTER_CHAIN_SCALE_VIEWPORT
|
||||
: VULKAN_FILTER_CHAIN_SCALE_SOURCE;
|
||||
pass_info.scale_x = 1.0f;
|
||||
pass_info.scale_y = 1.0f;
|
||||
pass_info.rt_format = i + 1 == shader->passes ? tmpinfo.swapchain.format : VK_FORMAT_R8G8B8A8_UNORM;
|
||||
pass_info.rt_format = i + 1 == shader->passes
|
||||
? tmpinfo.swapchain.format
|
||||
: VK_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1429,17 +1533,20 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(const struct vulka
|
||||
return chain.release();
|
||||
}
|
||||
|
||||
struct video_shader *vulkan_filter_chain_get_preset(vulkan_filter_chain_t *chain)
|
||||
struct video_shader *vulkan_filter_chain_get_preset(
|
||||
vulkan_filter_chain_t *chain)
|
||||
{
|
||||
return chain->get_shader_preset();
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_free(vulkan_filter_chain_t *chain)
|
||||
void vulkan_filter_chain_free(
|
||||
vulkan_filter_chain_t *chain)
|
||||
{
|
||||
delete chain;
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_set_shader(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_set_shader(
|
||||
vulkan_filter_chain_t *chain,
|
||||
unsigned pass,
|
||||
VkShaderStageFlags stage,
|
||||
const uint32_t *spirv,
|
||||
@ -1448,20 +1555,23 @@ void vulkan_filter_chain_set_shader(vulkan_filter_chain_t *chain,
|
||||
chain->set_shader(pass, stage, spirv, spirv_words);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_set_pass_info(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_set_pass_info(
|
||||
vulkan_filter_chain_t *chain,
|
||||
unsigned pass,
|
||||
const struct vulkan_filter_chain_pass_info *info)
|
||||
{
|
||||
chain->set_pass_info(pass, *info);
|
||||
}
|
||||
|
||||
bool vulkan_filter_chain_update_swapchain_info(vulkan_filter_chain_t *chain,
|
||||
bool vulkan_filter_chain_update_swapchain_info(
|
||||
vulkan_filter_chain_t *chain,
|
||||
const vulkan_filter_chain_swapchain_info *info)
|
||||
{
|
||||
return chain->update_swapchain_info(*info);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_notify_sync_index(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_notify_sync_index(
|
||||
vulkan_filter_chain_t *chain,
|
||||
unsigned index)
|
||||
{
|
||||
chain->notify_sync_index(index);
|
||||
@ -1472,19 +1582,22 @@ bool vulkan_filter_chain_init(vulkan_filter_chain_t *chain)
|
||||
return chain->init();
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_set_input_texture(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_set_input_texture(
|
||||
vulkan_filter_chain_t *chain,
|
||||
const struct vulkan_filter_chain_texture *texture)
|
||||
{
|
||||
chain->set_input_texture(*texture);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_build_offscreen_passes(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_build_offscreen_passes(
|
||||
vulkan_filter_chain_t *chain,
|
||||
VkCommandBuffer cmd, const VkViewport *vp)
|
||||
{
|
||||
chain->build_offscreen_passes(cmd, *vp);
|
||||
}
|
||||
|
||||
void vulkan_filter_chain_build_viewport_pass(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_build_viewport_pass(
|
||||
vulkan_filter_chain_t *chain,
|
||||
VkCommandBuffer cmd, const VkViewport *vp, const float *mvp)
|
||||
{
|
||||
chain->build_viewport_pass(cmd, *vp, mvp);
|
||||
|
@ -52,7 +52,8 @@ enum vulkan_filter_chain_scale
|
||||
|
||||
struct vulkan_filter_chain_pass_info
|
||||
{
|
||||
/* For the last pass, make sure VIEWPORT scale with scale factors of 1 are used. */
|
||||
/* For the last pass, make sure VIEWPORT scale
|
||||
* with scale factors of 1 are used. */
|
||||
enum vulkan_filter_chain_scale scale_type_x;
|
||||
enum vulkan_filter_chain_scale scale_type_y;
|
||||
float scale_x;
|
||||
@ -117,13 +118,16 @@ void vulkan_filter_chain_build_offscreen_passes(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_build_viewport_pass(vulkan_filter_chain_t *chain,
|
||||
VkCommandBuffer cmd, const VkViewport *vp, const float *mvp);
|
||||
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_default(const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_default(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
enum vulkan_filter_chain_filter filter);
|
||||
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
const char *path, enum vulkan_filter_chain_filter filter);
|
||||
|
||||
struct video_shader *vulkan_filter_chain_get_preset(vulkan_filter_chain_t *chain);
|
||||
struct video_shader *vulkan_filter_chain_get_preset(
|
||||
vulkan_filter_chain_t *chain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -276,9 +276,11 @@ static bool find_video_driver(void)
|
||||
|
||||
if (video_driver_ctl(RARCH_DISPLAY_CTL_IS_HW_CONTEXT, NULL))
|
||||
{
|
||||
current_video = NULL;
|
||||
struct retro_hw_render_callback *hwr =
|
||||
video_driver_callback();
|
||||
current_video = NULL;
|
||||
|
||||
(void)hwr;
|
||||
|
||||
#if defined(HAVE_VULKAN)
|
||||
if (hwr && hw_render_context_is_vulkan(hwr->context_type))
|
||||
|
@ -336,11 +336,11 @@ int generic_menu_iterate(void *data, void *userdata, enum menu_action action)
|
||||
BIT64_SET(menu->state, MENU_STATE_POP_STACK);
|
||||
break;
|
||||
case ITERATE_TYPE_DEFAULT:
|
||||
/* FIXME: Crappy hack, needed for mouse controls to not be completely broken
|
||||
* in case we press back.
|
||||
/* FIXME: Crappy hack, needed for mouse controls
|
||||
* to not be completely broken in case we press back.
|
||||
*
|
||||
* We need to fix this entire mess, mouse controls should not rely on a
|
||||
* hack like this in order to work. */
|
||||
* We need to fix this entire mess, mouse controls
|
||||
* should not rely on a hack like this in order to work. */
|
||||
selection = max(min(selection, (menu_entries_get_size() - 1)), 0);
|
||||
|
||||
menu_entry_get(&entry, 0, selection, NULL, false);
|
||||
|
@ -293,7 +293,8 @@ static void* xui_init(void **userdata)
|
||||
|
||||
d3d_make_d3dpp(d3d, &video_info, &d3dpp);
|
||||
|
||||
hr = app.InitShared(d3d->dev, &d3dpp, (PFN_XUITEXTURELOADER)XuiTextureLoader);
|
||||
hr = app.InitShared(d3d->dev, &d3dpp,
|
||||
(PFN_XUITEXTURELOADER)XuiTextureLoader);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@ -404,7 +405,7 @@ static void xui_frame(void *data)
|
||||
XUIMessageRender msgRender;
|
||||
D3DXMATRIX matOrigView;
|
||||
LPDIRECT3DDEVICE d3dr;
|
||||
const char *message;
|
||||
const char *message = NULL;
|
||||
D3DVIEWPORT vp_full = {0};
|
||||
d3d_video_t *d3d = (d3d_video_t*)video_driver_get_ptr(false);
|
||||
|
||||
@ -424,7 +425,8 @@ static void xui_frame(void *data)
|
||||
|
||||
XuiRenderGetViewTransform( app.GetDC(), &matOrigView );
|
||||
|
||||
XuiMessageRender( &msg, &msgRender, app.GetDC(), 0xffffffff, XUI_BLEND_NORMAL );
|
||||
XuiMessageRender( &msg, &msgRender,
|
||||
app.GetDC(), 0xffffffff, XUI_BLEND_NORMAL );
|
||||
XuiSendMessage( app.GetRootObj(), &msg );
|
||||
|
||||
XuiRenderSetViewTransform( app.GetDC(), &matOrigView );
|
||||
@ -452,9 +454,7 @@ static void blit_line(int x, int y, const char *message, bool green)
|
||||
|
||||
static void xui_render_background(void)
|
||||
{
|
||||
bool libretro_running = menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL);
|
||||
|
||||
if (libretro_running)
|
||||
if (menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL))
|
||||
XuiElementSetShow(m_background, FALSE);
|
||||
else
|
||||
XuiElementSetShow(m_background, TRUE);
|
||||
@ -666,13 +666,15 @@ static void xui_list_free(file_list_t *list, size_t idx,
|
||||
|
||||
static void xui_list_clear(file_list_t *list)
|
||||
{
|
||||
XuiListDeleteItems(m_menulist, 0, XuiListGetItemCount(m_menulist));
|
||||
XuiListDeleteItems(m_menulist,
|
||||
0, XuiListGetItemCount(m_menulist));
|
||||
}
|
||||
|
||||
static void xui_list_set_selection(void *data, file_list_t *list)
|
||||
{
|
||||
if (list)
|
||||
XuiListSetCurSel(m_menulist, file_list_get_directory_ptr(list));
|
||||
XuiListSetCurSel(m_menulist,
|
||||
file_list_get_directory_ptr(list));
|
||||
}
|
||||
|
||||
static int xui_environ(menu_environ_cb_t type, void *data)
|
||||
|
@ -213,8 +213,10 @@ static void zarch_zui_font(void)
|
||||
|
||||
menu_display_ctl(MENU_DISPLAY_CTL_FONT_SIZE, &font_size);
|
||||
|
||||
fill_pathname_join(mediapath, settings->assets_directory, "zarch", sizeof(mediapath));
|
||||
fill_pathname_join(fontpath, mediapath, "Roboto-Condensed.ttf", sizeof(fontpath));
|
||||
fill_pathname_join(mediapath,
|
||||
settings->assets_directory, "zarch", sizeof(mediapath));
|
||||
fill_pathname_join(fontpath,
|
||||
mediapath, "Roboto-Condensed.ttf", sizeof(fontpath));
|
||||
|
||||
font_info.path = fontpath;
|
||||
font_info.size = font_size;
|
||||
@ -250,7 +252,8 @@ static int16_t zarch_zui_input_state(zui_t *zui, enum zarch_zui_input_state stat
|
||||
case MENU_POINTER_ZARCH_Y:
|
||||
return menu_input_pointer_state(MENU_POINTER_Y_AXIS);
|
||||
case MENU_ZARCH_PRESSED:
|
||||
if (menu_input_mouse_state(MENU_MOUSE_LEFT_BUTTON) || menu_input_pointer_state(MENU_POINTER_PRESSED))
|
||||
if ( menu_input_mouse_state(MENU_MOUSE_LEFT_BUTTON)
|
||||
|| menu_input_pointer_state(MENU_POINTER_PRESSED))
|
||||
return 1;
|
||||
if (zui->action == MENU_ACTION_OK)
|
||||
return 1;
|
||||
@ -260,7 +263,8 @@ static int16_t zarch_zui_input_state(zui_t *zui, enum zarch_zui_input_state stat
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2)
|
||||
static bool zarch_zui_check_button_down(zui_t *zui,
|
||||
unsigned id, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
bool result = false;
|
||||
bool inside = menu_input_mouse_check_hitbox(x1, y1, x2, y2);
|
||||
@ -268,7 +272,8 @@ static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1,
|
||||
if (inside)
|
||||
zui->item.hot = id;
|
||||
|
||||
if (zui->item.hot == id && zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
if ( zui->item.hot == id
|
||||
&& zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
{
|
||||
result = true;
|
||||
zui->item.active = id;
|
||||
@ -277,7 +282,8 @@ static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1,
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool zarch_zui_check_button_up(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2)
|
||||
static bool zarch_zui_check_button_up(zui_t *zui,
|
||||
unsigned id, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
bool result = false;
|
||||
bool inside = menu_input_mouse_check_hitbox(x1, y1, x2, y2);
|
||||
@ -285,7 +291,8 @@ static bool zarch_zui_check_button_up(zui_t *zui, unsigned id, int x1, int y1, i
|
||||
if (inside)
|
||||
zui->item.hot = id;
|
||||
|
||||
if (zui->item.active == id && !zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
if ( zui->item.active == id
|
||||
&& !zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
{
|
||||
if (zui->item.hot == id)
|
||||
result = true;
|
||||
@ -314,7 +321,8 @@ static unsigned zarch_zui_hash(zui_t *zui, const char *s)
|
||||
return zui->hash = hval;
|
||||
}
|
||||
|
||||
static void zarch_zui_draw_text(zui_t *zui, uint32_t color, int x, int y, const char *text)
|
||||
static void zarch_zui_draw_text(zui_t *zui,
|
||||
uint32_t color, int x, int y, const char *text)
|
||||
{
|
||||
struct font_params params;
|
||||
|
||||
@ -375,14 +383,16 @@ static float zarch_zui_randf(float min, float max)
|
||||
return (rand() * ((max - min) / RAND_MAX)) + min;
|
||||
}
|
||||
|
||||
static float zarch_zui_scalef(float val, float oldmin, float oldmax, float newmin, float newmax)
|
||||
static float zarch_zui_scalef(float val,
|
||||
float oldmin, float oldmax, float newmin, float newmax)
|
||||
{
|
||||
return (((val - oldmin) * (newmax - newmin)) / (oldmax - oldmin)) + newmin;
|
||||
}
|
||||
|
||||
#define NPARTICLES 100
|
||||
|
||||
static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int height)
|
||||
static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca,
|
||||
int width, int height)
|
||||
{
|
||||
static part_t particles[NPARTICLES];
|
||||
static bool initialized = false;
|
||||
@ -404,11 +414,11 @@ static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int hei
|
||||
int16_t mouse_x = zarch_zui_input_state(zui, MENU_ZARCH_MOUSE_X);
|
||||
|
||||
p->y += p->yspeed;
|
||||
p->x += zarch_zui_scalef(mouse_x, 0, width, -0.3, 0.3) + p->xspeed;
|
||||
|
||||
p->alive = p->y >= 0 && p->y < height && p->x >= 0 && p->x < width;
|
||||
|
||||
p->x += zarch_zui_scalef(mouse_x, 0, width, -0.3, 0.3);
|
||||
p->x += p->xspeed;
|
||||
|
||||
p->alive = p->y >= 0 && p->y < height
|
||||
&& p->x >= 0 && p->x < width;
|
||||
}
|
||||
else if (max_gen > 0 && timeout <= 0)
|
||||
{
|
||||
@ -447,13 +457,15 @@ static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int hei
|
||||
colors[j] = alpha;
|
||||
}
|
||||
|
||||
zarch_zui_push_quad(width, height, colors, ca, p->x-2, p->y-2, p->x+2, p->y+2);
|
||||
zarch_zui_push_quad(width, height,
|
||||
colors, ca, p->x-2, p->y-2, p->x+2, p->y+2);
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool zarch_zui_button_full(zui_t *zui, int x1, int y1, int x2, int y2, const char *label)
|
||||
static bool zarch_zui_button_full(zui_t *zui,
|
||||
int x1, int y1, int x2, int y2, const char *label)
|
||||
{
|
||||
unsigned id = zarch_zui_hash(zui, label);
|
||||
bool active = zarch_zui_check_button_up(zui, id, x1, y1, x2, y2);
|
||||
@ -470,7 +482,8 @@ static bool zarch_zui_button_full(zui_t *zui, int x1, int y1, int x2, int y2, co
|
||||
|
||||
static bool zarch_zui_button(zui_t *zui, int x1, int y1, const char *label)
|
||||
{
|
||||
return zarch_zui_button_full(zui, x1, y1, x1 + zarch_zui_strwidth(zui->fb_buf, label, 1.0) + 24, y1 + 64, label);
|
||||
return zarch_zui_button_full(zui, x1, y1, x1
|
||||
+ zarch_zui_strwidth(zui->fb_buf, label, 1.0) + 24, y1 + 64, label);
|
||||
}
|
||||
|
||||
static bool zarch_zui_list_item(zui_t *zui, zui_tabbed_t *tab, int x1, int y1,
|
||||
@ -506,7 +519,8 @@ static bool zarch_zui_list_item(zui_t *zui, zui_tabbed_t *tab, int x1, int y1,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zui->active_id != item_id && zui->pending_selection == item_id)
|
||||
if ( zui->active_id != item_id
|
||||
&& zui->pending_selection == item_id)
|
||||
set_active_id = true;
|
||||
}
|
||||
|
||||
@ -542,7 +556,8 @@ static void zarch_zui_tabbed_begin(zui_t *zui, zui_tabbed_t *tab, int x, int y)
|
||||
tab->tabline_size = 60 + 4;
|
||||
}
|
||||
|
||||
static bool zarch_zui_tab(zui_t *zui, zui_tabbed_t *tab, const char *label, unsigned tab_id)
|
||||
static bool zarch_zui_tab(zui_t *zui, zui_tabbed_t *tab,
|
||||
const char *label, unsigned tab_id)
|
||||
{
|
||||
bool active;
|
||||
int x1, y1, x2, y2;
|
||||
@ -656,7 +671,8 @@ static void zarch_zui_render_lay_root_load_free(zui_t *zui)
|
||||
zui->load_dlist = NULL;
|
||||
}
|
||||
|
||||
static void zarch_zui_render_lay_root_load_set_new_path(zui_t *zui, const char *newpath)
|
||||
static void zarch_zui_render_lay_root_load_set_new_path(zui_t *zui,
|
||||
const char *newpath)
|
||||
{
|
||||
if (!zui)
|
||||
return;
|
||||
@ -685,23 +701,29 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
core_info_t *core_info = NULL;
|
||||
core_info_ctl(CORE_INFO_CTL_CURRENT_CORE_GET, &core_info);
|
||||
|
||||
zui->load_dlist = dir_list_new(zui->load_cwd, core_info->supported_extensions, true, true);
|
||||
zui->load_dlist = dir_list_new(zui->load_cwd,
|
||||
core_info->supported_extensions, true, true);
|
||||
dir_list_sort(zui->load_dlist, true);
|
||||
zui->load_dlist_first = 0;
|
||||
}
|
||||
|
||||
cwd_offset = min(strlen(zui->load_cwd), 60);
|
||||
|
||||
zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]);
|
||||
zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15,
|
||||
tabbed->tabline_size + 5 + 41,
|
||||
&zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]);
|
||||
|
||||
if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home"))
|
||||
if (zarch_zui_button(zui, zui->width - 290 - 129,
|
||||
tabbed->tabline_size + 5, "Home"))
|
||||
zarch_zui_render_lay_root_load_free(zui);
|
||||
|
||||
if (zui->load_dlist)
|
||||
{
|
||||
fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir));
|
||||
fill_pathname_parent_dir(parent_dir,
|
||||
zui->load_cwd, sizeof(parent_dir));
|
||||
if (!string_is_empty(parent_dir) &&
|
||||
zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */))
|
||||
zarch_zui_list_item(zui, tabbed, 0,
|
||||
tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */))
|
||||
{
|
||||
zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir);
|
||||
}
|
||||
@ -713,7 +735,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
const char *basename = path_basename(zui->load_dlist->elems[i].data);
|
||||
const char *basename =
|
||||
path_basename(zui->load_dlist->elems[i].data);
|
||||
if (basename[0] != '.')
|
||||
break;
|
||||
skip++;
|
||||
@ -726,7 +749,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
else if (zui->load_dlist_first > (int)size - 5)
|
||||
zui->load_dlist_first = size - 5;
|
||||
|
||||
zui->load_dlist_first = min(max(zui->load_dlist_first, 0), size - 5 - skip);
|
||||
zui->load_dlist_first = min(max(zui->load_dlist_first, 0),
|
||||
size - 5 - skip);
|
||||
|
||||
for (i = skip + zui->load_dlist_first; i < size; ++i)
|
||||
{
|
||||
@ -747,7 +771,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
if (path_is_directory(path))
|
||||
strncat(label, "/", sizeof(label)-1);
|
||||
|
||||
if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * 54,
|
||||
if (zarch_zui_list_item(zui, tabbed, 0,
|
||||
tabbed->tabline_size + 73 + j * 54,
|
||||
label, i, NULL))
|
||||
{
|
||||
if (path_is_directory(path))
|
||||
@ -758,7 +783,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
|
||||
zui->pick_cores = NULL;
|
||||
zui->pick_supported = 0;
|
||||
strncpy(zui->pick_content, path, sizeof(zui->pick_content)-1);
|
||||
strncpy(zui->pick_content,
|
||||
path, sizeof(zui->pick_content)-1);
|
||||
|
||||
core_info_ctl(CORE_INFO_CTL_LIST_GET, &list);
|
||||
|
||||
@ -781,7 +807,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zarch_zui_render_lay_root_collections(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
static int zarch_zui_render_lay_root_collections(
|
||||
zui_t *zui, zui_tabbed_t *tabbed)
|
||||
{
|
||||
if (zarch_zui_tab(zui, tabbed, "Collections", 2))
|
||||
{
|
||||
@ -791,7 +818,8 @@ static int zarch_zui_render_lay_root_collections(zui_t *zui, zui_tabbed_t *tabbe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zarch_zui_render_lay_root_downloads(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
static int zarch_zui_render_lay_root_downloads(
|
||||
zui_t *zui, zui_tabbed_t *tabbed)
|
||||
{
|
||||
if (zarch_zui_tab(zui, tabbed, "Download", 3))
|
||||
{
|
||||
@ -855,7 +883,8 @@ static int zarch_zui_render_lay_root(zui_t *zui)
|
||||
else
|
||||
zui->pending_selection = -1;
|
||||
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_HILITE, &zui->ca, 0, 60, zui->width - 290 - 40, 60+4);
|
||||
zarch_zui_push_quad(zui->width, zui->height,
|
||||
ZUI_BG_HILITE, &zui->ca, 0, 60, zui->width - 290 - 40, 60+4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -923,7 +952,8 @@ static int zarch_zui_render_pick_core(zui_t *zui)
|
||||
|
||||
if (!zui->pick_supported)
|
||||
{
|
||||
zarch_zui_list_item(zui, &tabbed, 0, 54, "Content unsupported", 0, NULL /* TODO/FIXME */);
|
||||
zarch_zui_list_item(zui, &tabbed, 0, 54,
|
||||
"Content unsupported", 0, NULL /* TODO/FIXME */);
|
||||
zui->active_id = 0;
|
||||
return 1;
|
||||
}
|
||||
@ -999,7 +1029,8 @@ static void zarch_frame(void *data)
|
||||
|
||||
menu_display_ctl(MENU_DISPLAY_CTL_FONT_BIND_BLOCK, &zui->tmp_block);
|
||||
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_SCREEN, &zui->ca, 0, 0, zui->width, zui->height);
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_SCREEN,
|
||||
&zui->ca, 0, 0, zui->width, zui->height);
|
||||
zarch_zui_snow(zui, &zui->ca, zui->width, zui->height);
|
||||
|
||||
switch (layout)
|
||||
@ -1078,7 +1109,8 @@ static void *zarch_init(void **userdata)
|
||||
int unused;
|
||||
zui_t *zui = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu));
|
||||
menu_handle_t *menu = (menu_handle_t*)
|
||||
calloc(1, sizeof(*menu));
|
||||
|
||||
if (!menu)
|
||||
goto error;
|
||||
@ -1112,7 +1144,8 @@ static void *zarch_init(void **userdata)
|
||||
|
||||
if (!string_is_empty(settings->menu.wallpaper))
|
||||
rarch_task_push_image_load(settings->menu.wallpaper,
|
||||
"cb_menu_wallpaper", menu_display_handle_wallpaper_upload, NULL);
|
||||
"cb_menu_wallpaper",
|
||||
menu_display_handle_wallpaper_upload, NULL);
|
||||
|
||||
zui->ca.allocated = 0;
|
||||
|
||||
@ -1276,18 +1309,22 @@ static bool zarch_menu_init_list(void *data)
|
||||
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
|
||||
|
||||
|
||||
strlcpy(info.label, menu_hash_to_str(MENU_VALUE_HISTORY_TAB), sizeof(info.label));
|
||||
strlcpy(info.label,
|
||||
menu_hash_to_str(MENU_VALUE_HISTORY_TAB), sizeof(info.label));
|
||||
|
||||
menu_entries_push(menu_stack, info.path, info.label, info.type, info.flags, 0);
|
||||
menu_entries_push(menu_stack,
|
||||
info.path, info.label, info.type, info.flags, 0);
|
||||
|
||||
#if 0
|
||||
menu_entries_increment_menu_stack();
|
||||
|
||||
strlcpy(info.label, menu_hash_to_str(MENU_VALUE_MAIN_MENU), sizeof(info.label));
|
||||
strlcpy(info.label,
|
||||
menu_hash_to_str(MENU_VALUE_MAIN_MENU), sizeof(info.label));
|
||||
|
||||
menu_stack = menu_entries_get_menu_stack_ptr(1);
|
||||
|
||||
menu_entries_push(menu_stack, info.path, info.label, info.type, info.flags, 0);
|
||||
menu_entries_push(menu_stack,
|
||||
info.path, info.label, info.type, info.flags, 0);
|
||||
#endif
|
||||
|
||||
event_cmd_ctl(EVENT_CMD_HISTORY_INIT, NULL);
|
||||
|
@ -126,7 +126,8 @@ static void menu_display_d3d_draw(void *data)
|
||||
draw->height = 1;
|
||||
|
||||
if (!mat)
|
||||
mat = (math_matrix_4x4*)menu_display_d3d_get_default_mvp();
|
||||
mat = (math_matrix_4x4*)
|
||||
menu_display_d3d_get_default_mvp();
|
||||
if (!draw->coords->vertex)
|
||||
draw->coords->vertex = &d3d_vertexes[0];
|
||||
if (!draw->coords->tex_coord)
|
||||
|
@ -53,21 +53,23 @@ static void *menu_display_vk_get_default_mvp(void)
|
||||
return &vk->mvp_no_rot;
|
||||
}
|
||||
|
||||
static unsigned to_display_pipeline(enum menu_display_prim_type prim_type, bool blend)
|
||||
static unsigned to_display_pipeline(
|
||||
enum menu_display_prim_type prim_type, bool blend)
|
||||
{
|
||||
return ((prim_type == MENU_DISPLAY_PRIM_TRIANGLESTRIP) << 1) | (blend << 0);
|
||||
}
|
||||
|
||||
static void menu_display_vk_draw(void *data)
|
||||
{
|
||||
menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data;
|
||||
struct vk_texture *texture;
|
||||
const float *vertex, *tex_coord, *color;
|
||||
math_matrix_4x4 *mat;
|
||||
struct vk_buffer_range range;
|
||||
struct vk_vertex *pv;
|
||||
unsigned i;
|
||||
|
||||
struct vk_buffer_range range;
|
||||
struct vk_texture *texture = NULL;
|
||||
const float *vertex = NULL;
|
||||
const float *tex_coord = NULL;
|
||||
const float *color = NULL;
|
||||
math_matrix_4x4 *mat = NULL;
|
||||
struct vk_vertex *pv = NULL;
|
||||
menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data;
|
||||
vk_t *vk = vk_get_ptr();
|
||||
if (!vk)
|
||||
return;
|
||||
@ -120,7 +122,8 @@ static void menu_display_vk_draw(void *data)
|
||||
|
||||
{
|
||||
const struct vk_draw_triangles call = {
|
||||
vk->display.pipelines[to_display_pipeline(draw->prim_type, vk->display.blend)],
|
||||
vk->display.pipelines[
|
||||
to_display_pipeline(draw->prim_type, vk->display.blend)],
|
||||
texture,
|
||||
texture->default_smooth ? vk->samplers.linear : vk->samplers.nearest,
|
||||
mat,
|
||||
|
Loading…
x
Reference in New Issue
Block a user