mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 10:10:57 +00:00
(shader_vulkan) Simplify - move functions over that were exclusively
used in shader_vulkan.cpp from vulkan_common.c to there
This commit is contained in:
parent
25c33a8306
commit
3b99b42812
@ -2612,12 +2612,6 @@ void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk,
|
||||
}
|
||||
}
|
||||
|
||||
static void vulkan_recycle_acquire_semaphore(struct vulkan_context *ctx, VkSemaphore sem)
|
||||
{
|
||||
assert(ctx->num_recycled_acquire_semaphores < VULKAN_MAX_SWAPCHAIN_IMAGES);
|
||||
ctx->swapchain_recycled_semaphores[ctx->num_recycled_acquire_semaphores++] = sem;
|
||||
}
|
||||
|
||||
static void vulkan_acquire_clear_fences(gfx_ctx_vulkan_data_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
@ -2632,7 +2626,12 @@ static void vulkan_acquire_clear_fences(gfx_ctx_vulkan_data_t *vk)
|
||||
vk->context.swapchain_fences_signalled[i] = false;
|
||||
|
||||
if (vk->context.swapchain_wait_semaphores[i])
|
||||
vulkan_recycle_acquire_semaphore(&vk->context, vk->context.swapchain_wait_semaphores[i]);
|
||||
{
|
||||
struct vulkan_context *ctx = &vk->context;
|
||||
VkSemaphore sem = vk->context.swapchain_wait_semaphores[i];
|
||||
assert(ctx->num_recycled_acquire_semaphores < VULKAN_MAX_SWAPCHAIN_IMAGES);
|
||||
ctx->swapchain_recycled_semaphores[ctx->num_recycled_acquire_semaphores++] = sem;
|
||||
}
|
||||
vk->context.swapchain_wait_semaphores[i] = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@ -2689,7 +2688,12 @@ static void vulkan_acquire_wait_fences(gfx_ctx_vulkan_data_t *vk)
|
||||
vk->context.swapchain_fences_signalled[index] = false;
|
||||
|
||||
if (vk->context.swapchain_wait_semaphores[index] != VK_NULL_HANDLE)
|
||||
vulkan_recycle_acquire_semaphore(&vk->context, vk->context.swapchain_wait_semaphores[index]);
|
||||
{
|
||||
struct vulkan_context *ctx = &vk->context;
|
||||
VkSemaphore sem = vk->context.swapchain_wait_semaphores[index];
|
||||
assert(ctx->num_recycled_acquire_semaphores < VULKAN_MAX_SWAPCHAIN_IMAGES);
|
||||
ctx->swapchain_recycled_semaphores[ctx->num_recycled_acquire_semaphores++] = sem;
|
||||
}
|
||||
vk->context.swapchain_wait_semaphores[index] = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@ -2812,7 +2816,12 @@ retry:
|
||||
{
|
||||
vk->context.has_acquired_swapchain = false;
|
||||
if (semaphore)
|
||||
vulkan_recycle_acquire_semaphore(&vk->context, semaphore);
|
||||
{
|
||||
struct vulkan_context *ctx = &vk->context;
|
||||
VkSemaphore sem = semaphore;
|
||||
assert(ctx->num_recycled_acquire_semaphores < VULKAN_MAX_SWAPCHAIN_IMAGES);
|
||||
ctx->swapchain_recycled_semaphores[ctx->num_recycled_acquire_semaphores++] = sem;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WSI_HARDENING_TEST
|
||||
@ -3244,46 +3253,6 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
return true;
|
||||
}
|
||||
|
||||
void vulkan_initialize_render_pass(VkDevice device, VkFormat format,
|
||||
VkRenderPass *render_pass)
|
||||
{
|
||||
VkAttachmentReference color_ref;
|
||||
VkRenderPassCreateInfo rp_info;
|
||||
VkAttachmentDescription attachment;
|
||||
VkSubpassDescription subpass = {0};
|
||||
|
||||
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
rp_info.pNext = NULL;
|
||||
rp_info.flags = 0;
|
||||
rp_info.attachmentCount = 1;
|
||||
rp_info.pAttachments = &attachment;
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
rp_info.dependencyCount = 0;
|
||||
rp_info.pDependencies = NULL;
|
||||
|
||||
color_ref.attachment = 0;
|
||||
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
/* We will always write to the entire framebuffer,
|
||||
* so we don't really need to clear. */
|
||||
attachment.flags = 0;
|
||||
attachment.format = format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_ref;
|
||||
|
||||
vkCreateRenderPass(device, &rp_info, NULL, render_pass);
|
||||
}
|
||||
|
||||
void vulkan_set_uniform_buffer(
|
||||
VkDevice device,
|
||||
VkDescriptorSet set,
|
||||
@ -3312,253 +3281,3 @@ void vulkan_set_uniform_buffer(
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &write, 0, NULL);
|
||||
}
|
||||
|
||||
void vulkan_framebuffer_generate_mips(
|
||||
VkFramebuffer framebuffer,
|
||||
VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
unsigned levels
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
/* This is run every frame, so make sure
|
||||
* we aren't opting into the "lazy" way of doing this. :) */
|
||||
VkImageMemoryBarrier barriers[2];
|
||||
|
||||
/* First, transfer the input mip level to TRANSFER_SRC_OPTIMAL.
|
||||
* This should allow the surface to stay compressed.
|
||||
* All subsequent mip-layers are now transferred into DST_OPTIMAL from
|
||||
* UNDEFINED at this point.
|
||||
*/
|
||||
|
||||
/* Input */
|
||||
barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barriers[0].pNext = NULL;
|
||||
barriers[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[0].image = image;
|
||||
barriers[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = 0;
|
||||
barriers[0].subresourceRange.levelCount = 1;
|
||||
barriers[0].subresourceRange.baseArrayLayer = 0;
|
||||
barriers[0].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
/* The rest of the mip chain */
|
||||
barriers[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barriers[1].pNext = NULL;
|
||||
barriers[1].srcAccessMask = 0;
|
||||
barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barriers[1].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[1].image = image;
|
||||
barriers[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barriers[1].subresourceRange.baseMipLevel = 1;
|
||||
barriers[1].subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barriers[0].subresourceRange.baseArrayLayer = 0;
|
||||
barriers[1].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
2,
|
||||
barriers);
|
||||
|
||||
for (i = 1; i < levels; i++)
|
||||
{
|
||||
unsigned src_width, src_height, target_width, target_height;
|
||||
VkImageBlit blit_region = {{0}};
|
||||
|
||||
/* For subsequent passes, we have to transition
|
||||
* from DST_OPTIMAL to SRC_OPTIMAL,
|
||||
* but only do so one mip-level at a time. */
|
||||
if (i > 1)
|
||||
{
|
||||
barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = i - 1;
|
||||
barriers[0].subresourceRange.levelCount = 1;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
barriers);
|
||||
}
|
||||
|
||||
src_width = MAX(size.width >> (i - 1), 1u);
|
||||
src_height = MAX(size.height >> (i - 1), 1u);
|
||||
target_width = MAX(size.width >> i, 1u);
|
||||
target_height = MAX(size.height >> i, 1u);
|
||||
|
||||
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit_region.srcSubresource.mipLevel = i - 1;
|
||||
blit_region.srcSubresource.baseArrayLayer = 0;
|
||||
blit_region.srcSubresource.layerCount = 1;
|
||||
blit_region.dstSubresource = blit_region.srcSubresource;
|
||||
blit_region.dstSubresource.mipLevel = i;
|
||||
blit_region.srcOffsets[1].x = src_width;
|
||||
blit_region.srcOffsets[1].y = src_height;
|
||||
blit_region.srcOffsets[1].z = 1;
|
||||
blit_region.dstOffsets[1].x = target_width;
|
||||
blit_region.dstOffsets[1].y = target_height;
|
||||
blit_region.dstOffsets[1].z = 1;
|
||||
|
||||
vkCmdBlitImage(cmd,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &blit_region, VK_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
/* We are now done, and we have all mip-levels except
|
||||
* the last in TRANSFER_SRC_OPTIMAL,
|
||||
* and the last one still on TRANSFER_DST_OPTIMAL,
|
||||
* so do a final barrier which
|
||||
* moves everything to SHADER_READ_ONLY_OPTIMAL in
|
||||
* one go along with the execution barrier to next pass.
|
||||
* Read-to-read memory barrier, so only need execution
|
||||
* barrier for first transition.
|
||||
*/
|
||||
barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = 0;
|
||||
barriers[0].subresourceRange.levelCount = levels - 1;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
/* This is read-after-write barrier. */
|
||||
barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barriers[1].subresourceRange.baseMipLevel = levels - 1;
|
||||
barriers[1].subresourceRange.levelCount = 1;
|
||||
barriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[1].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
2, barriers);
|
||||
|
||||
/* Next pass will wait for ALL_GRAPHICS_BIT, and since
|
||||
* we have dstStage as FRAGMENT_SHADER,
|
||||
* the dependency chain will ensure we don't start
|
||||
* next pass until the mipchain is complete. */
|
||||
}
|
||||
|
||||
void vulkan_framebuffer_copy(VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
VkImage src_image, VkImageLayout src_layout)
|
||||
{
|
||||
VkImageCopy region;
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd, image,VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.mipLevel = 0;
|
||||
region.srcSubresource.baseArrayLayer = 0;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.srcOffset.x = 0;
|
||||
region.srcOffset.y = 0;
|
||||
region.srcOffset.z = 0;
|
||||
region.dstSubresource = region.srcSubresource;
|
||||
region.dstOffset.x = 0;
|
||||
region.dstOffset.y = 0;
|
||||
region.dstOffset.z = 0;
|
||||
region.extent.width = size.width;
|
||||
region.extent.height = size.height;
|
||||
region.extent.depth = 1;
|
||||
|
||||
vkCmdCopyImage(cmd,
|
||||
src_image, src_layout,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_FRAGMENT_SHADER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
|
||||
void vulkan_framebuffer_clear(VkImage image, VkCommandBuffer cmd)
|
||||
{
|
||||
VkClearColorValue color;
|
||||
VkImageSubresourceRange range;
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
|
||||
color.float32[0] = 0.0f;
|
||||
color.float32[1] = 0.0f;
|
||||
color.float32[2] = 0.0f;
|
||||
color.float32[3] = 0.0f;
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
range.baseMipLevel = 0;
|
||||
range.levelCount = 1;
|
||||
range.baseArrayLayer = 0;
|
||||
range.layerCount = 1;
|
||||
|
||||
vkCmdClearColorImage(cmd,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&color,
|
||||
1,
|
||||
&range);
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_FRAGMENT_SHADER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
|
@ -798,24 +798,6 @@ void vulkan_set_uniform_buffer(
|
||||
VkDeviceSize offset,
|
||||
VkDeviceSize range);
|
||||
|
||||
void vulkan_framebuffer_generate_mips(
|
||||
VkFramebuffer framebuffer,
|
||||
VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
unsigned levels
|
||||
);
|
||||
|
||||
void vulkan_framebuffer_copy(VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
VkImage src_image, VkImageLayout src_layout);
|
||||
|
||||
void vulkan_framebuffer_clear(VkImage image, VkCommandBuffer cmd);
|
||||
|
||||
void vulkan_initialize_render_pass(VkDevice device,
|
||||
VkFormat format, VkRenderPass *render_pass);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -430,6 +430,257 @@ struct vulkan_filter_chain
|
||||
void update_history_info();
|
||||
};
|
||||
|
||||
static void vulkan_framebuffer_generate_mips(
|
||||
VkFramebuffer framebuffer,
|
||||
VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
unsigned levels
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
/* This is run every frame, so make sure
|
||||
* we aren't opting into the "lazy" way of doing this. :) */
|
||||
VkImageMemoryBarrier barriers[2];
|
||||
|
||||
/* First, transfer the input mip level to TRANSFER_SRC_OPTIMAL.
|
||||
* This should allow the surface to stay compressed.
|
||||
* All subsequent mip-layers are now transferred into DST_OPTIMAL from
|
||||
* UNDEFINED at this point.
|
||||
*/
|
||||
|
||||
/* Input */
|
||||
barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barriers[0].pNext = NULL;
|
||||
barriers[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[0].image = image;
|
||||
barriers[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = 0;
|
||||
barriers[0].subresourceRange.levelCount = 1;
|
||||
barriers[0].subresourceRange.baseArrayLayer = 0;
|
||||
barriers[0].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
/* The rest of the mip chain */
|
||||
barriers[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barriers[1].pNext = NULL;
|
||||
barriers[1].srcAccessMask = 0;
|
||||
barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barriers[1].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barriers[1].image = image;
|
||||
barriers[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barriers[1].subresourceRange.baseMipLevel = 1;
|
||||
barriers[1].subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barriers[0].subresourceRange.baseArrayLayer = 0;
|
||||
barriers[1].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
2,
|
||||
barriers);
|
||||
|
||||
for (i = 1; i < levels; i++)
|
||||
{
|
||||
unsigned src_width, src_height, target_width, target_height;
|
||||
VkImageBlit blit_region = {{0}};
|
||||
|
||||
/* For subsequent passes, we have to transition
|
||||
* from DST_OPTIMAL to SRC_OPTIMAL,
|
||||
* but only do so one mip-level at a time. */
|
||||
if (i > 1)
|
||||
{
|
||||
barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = i - 1;
|
||||
barriers[0].subresourceRange.levelCount = 1;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
barriers);
|
||||
}
|
||||
|
||||
src_width = MAX(size.width >> (i - 1), 1u);
|
||||
src_height = MAX(size.height >> (i - 1), 1u);
|
||||
target_width = MAX(size.width >> i, 1u);
|
||||
target_height = MAX(size.height >> i, 1u);
|
||||
|
||||
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit_region.srcSubresource.mipLevel = i - 1;
|
||||
blit_region.srcSubresource.baseArrayLayer = 0;
|
||||
blit_region.srcSubresource.layerCount = 1;
|
||||
blit_region.dstSubresource = blit_region.srcSubresource;
|
||||
blit_region.dstSubresource.mipLevel = i;
|
||||
blit_region.srcOffsets[1].x = src_width;
|
||||
blit_region.srcOffsets[1].y = src_height;
|
||||
blit_region.srcOffsets[1].z = 1;
|
||||
blit_region.dstOffsets[1].x = target_width;
|
||||
blit_region.dstOffsets[1].y = target_height;
|
||||
blit_region.dstOffsets[1].z = 1;
|
||||
|
||||
vkCmdBlitImage(cmd,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &blit_region, VK_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
/* We are now done, and we have all mip-levels except
|
||||
* the last in TRANSFER_SRC_OPTIMAL,
|
||||
* and the last one still on TRANSFER_DST_OPTIMAL,
|
||||
* so do a final barrier which
|
||||
* moves everything to SHADER_READ_ONLY_OPTIMAL in
|
||||
* one go along with the execution barrier to next pass.
|
||||
* Read-to-read memory barrier, so only need execution
|
||||
* barrier for first transition.
|
||||
*/
|
||||
barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barriers[0].subresourceRange.baseMipLevel = 0;
|
||||
barriers[0].subresourceRange.levelCount = levels - 1;
|
||||
barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
/* This is read-after-write barrier. */
|
||||
barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barriers[1].subresourceRange.baseMipLevel = levels - 1;
|
||||
barriers[1].subresourceRange.levelCount = 1;
|
||||
barriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barriers[1].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
2, barriers);
|
||||
|
||||
/* Next pass will wait for ALL_GRAPHICS_BIT, and since
|
||||
* we have dstStage as FRAGMENT_SHADER,
|
||||
* the dependency chain will ensure we don't start
|
||||
* next pass until the mipchain is complete. */
|
||||
}
|
||||
|
||||
static void vulkan_framebuffer_copy(VkImage image,
|
||||
struct Size2D size,
|
||||
VkCommandBuffer cmd,
|
||||
VkImage src_image, VkImageLayout src_layout)
|
||||
{
|
||||
VkImageCopy region;
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd, image,VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.mipLevel = 0;
|
||||
region.srcSubresource.baseArrayLayer = 0;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.srcOffset.x = 0;
|
||||
region.srcOffset.y = 0;
|
||||
region.srcOffset.z = 0;
|
||||
region.dstSubresource = region.srcSubresource;
|
||||
region.dstOffset.x = 0;
|
||||
region.dstOffset.y = 0;
|
||||
region.dstOffset.z = 0;
|
||||
region.extent.width = size.width;
|
||||
region.extent.height = size.height;
|
||||
region.extent.depth = 1;
|
||||
|
||||
vkCmdCopyImage(cmd,
|
||||
src_image, src_layout,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_FRAGMENT_SHADER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
|
||||
static void vulkan_framebuffer_clear(VkImage image, VkCommandBuffer cmd)
|
||||
{
|
||||
VkClearColorValue color;
|
||||
VkImageSubresourceRange range;
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
|
||||
color.float32[0] = 0.0f;
|
||||
color.float32[1] = 0.0f;
|
||||
color.float32[2] = 0.0f;
|
||||
color.float32[3] = 0.0f;
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
range.baseMipLevel = 0;
|
||||
range.levelCount = 1;
|
||||
range.baseArrayLayer = 0;
|
||||
range.layerCount = 1;
|
||||
|
||||
vkCmdClearColorImage(cmd,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&color,
|
||||
1,
|
||||
&range);
|
||||
|
||||
VULKAN_IMAGE_LAYOUT_TRANSITION_LEVELS(cmd,
|
||||
image,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_FRAGMENT_SHADER_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t find_memory_type_fallback(
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
uint32_t device_reqs, uint32_t host_reqs)
|
||||
@ -2322,6 +2573,7 @@ void Pass::build_commands(
|
||||
};
|
||||
vkCmdSetViewport(cmd, 0, 1, ¤t_viewport);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
vkCmdDraw(cmd, 4, 1, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2341,12 +2593,7 @@ void Pass::build_commands(
|
||||
|
||||
vkCmdSetViewport(cmd, 0, 1, &_vp);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
}
|
||||
|
||||
vkCmdDraw(cmd, 4, 1, 0, 0);
|
||||
|
||||
if (!final_pass)
|
||||
{
|
||||
vkCmdDraw(cmd, 4, 1, 0, 0);
|
||||
vkCmdEndRenderPass(cmd);
|
||||
|
||||
if (framebuffer->get_levels() > 1)
|
||||
@ -2375,6 +2622,47 @@ void Pass::build_commands(
|
||||
}
|
||||
}
|
||||
|
||||
static void vulkan_initialize_render_pass(VkDevice device, VkFormat format,
|
||||
VkRenderPass *render_pass)
|
||||
{
|
||||
VkAttachmentReference color_ref;
|
||||
VkRenderPassCreateInfo rp_info;
|
||||
VkAttachmentDescription attachment;
|
||||
VkSubpassDescription subpass = {0};
|
||||
|
||||
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
rp_info.pNext = NULL;
|
||||
rp_info.flags = 0;
|
||||
rp_info.attachmentCount = 1;
|
||||
rp_info.pAttachments = &attachment;
|
||||
rp_info.subpassCount = 1;
|
||||
rp_info.pSubpasses = &subpass;
|
||||
rp_info.dependencyCount = 0;
|
||||
rp_info.pDependencies = NULL;
|
||||
|
||||
color_ref.attachment = 0;
|
||||
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
/* We will always write to the entire framebuffer,
|
||||
* so we don't really need to clear. */
|
||||
attachment.flags = 0;
|
||||
attachment.format = format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_ref;
|
||||
|
||||
vkCreateRenderPass(device, &rp_info, NULL, render_pass);
|
||||
}
|
||||
|
||||
|
||||
Framebuffer::Framebuffer(
|
||||
VkDevice device,
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
|
Loading…
Reference in New Issue
Block a user