Separate reconstruction framebuffer

This commit is contained in:
mittorn 2024-10-29 06:12:52 +03:00
parent 8ccd994e5b
commit ba7d9abe25
2 changed files with 235 additions and 82 deletions

View file

@ -24,7 +24,7 @@ extern "C" {
// todo: REMOVE THIS. Why "simpliest triangle" demos even use this????
// It does not "HELP" drawing 2D triangle!!! It is not useful in engines using own matrix transform code!
//#include <glm/gtc/matrix_transform.hpp>
#define MAX_SWAPCHAIN_IMAGES 32
#define MAX_SWAPCHAIN_IMAGES 8
// workaround for ffmpeg stable api nonsence with incompatible pointers between versions
struct PointerWrap
{
@ -47,8 +47,6 @@ struct Vertex
struct DecoderImage
{
VkSamplerYcbcrConversion ycbcr_sampler_conversion;
VkSampler ycbcr_sampler;
VkImage image;
VkDeviceMemory image_memory;
// todo: deduplicate shared parameters
@ -59,7 +57,7 @@ struct DecoderImage
};
void CreateSoftwareImage(VkInstance inst, VulkanDevice &dev, DecoderImage &image)
void CreateSoftwareImage(VkInstance inst, VulkanDevice &dev, DecoderImage &image, const VkSamplerYcbcrConversionInfo &ycbcr_info)
{
CallWith(Image2dInfo(VK_IMAGE_USAGE_SAMPLED_BIT, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, 1920, 1080,
@ -97,31 +95,7 @@ void CreateSoftwareImage(VkInstance inst, VulkanDevice &dev, DecoderImage &image
$F(bindInfo[1], $(image) = image.image, $(memory) = image.image_memory, $(memoryOffset) = image.memory_offset_plane1);
PFN_vkBindImageMemory2 pvkBindImageMemory2 = (PFN_vkBindImageMemory2)vkGetInstanceProcAddr(inst, "vkBindImageMemory2KHR");
pvkBindImageMemory2(dev.device, 2, bindInfo);
PFN_vkCreateSamplerYcbcrConversion pvkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion)vkGetInstanceProcAddr(inst, "vkCreateSamplerYcbcrConversionKHR");
CallWith($M(VkSamplerYcbcrConversionCreateInfo{VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO},
$(format) = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
$(ycbcrModel) = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
$(ycbcrRange) = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
$(xChromaOffset) = VK_CHROMA_LOCATION_COSITED_EVEN, // zero
$(yChromaOffset) = VK_CHROMA_LOCATION_COSITED_EVEN,
$(chromaFilter) = VK_FILTER_NEAREST), // zero
pvkCreateSamplerYcbcrConversion(dev.device, &ref, NULL, &image.ycbcr_sampler_conversion));
$Sc ycbcr_info = $M(VkSamplerYcbcrConversionInfo{VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO},
$(conversion) = image.ycbcr_sampler_conversion);
CallWith($M(VkSamplerCreateInfo{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, &ycbcr_info},
$(magFilter) = VK_FILTER_NEAREST,
$(minFilter) = VK_FILTER_NEAREST,
$(mipmapMode) = VK_SAMPLER_MIPMAP_MODE_NEAREST, // zero
$(addressModeU) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(addressModeV) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(addressModeW) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(maxLod) = 1.0f,
$(borderColor) = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK),
vkCreateSampler(dev.device, &ref, NULL, &image.ycbcr_sampler);
);
CallWith($M(VkImageViewCreateInfo{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &ycbcr_info},
$(image) = image.image, $(viewType) = VK_IMAGE_VIEW_TYPE_2D,
$(format) = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
@ -145,6 +119,8 @@ void CreateSoftwareImage(VkInstance inst, VulkanDevice &dev, DecoderImage &image
static struct FFmpegDecoder
{
DecoderImage images[MAX_DECODER_FRAMES];
VkSamplerYcbcrConversion ycbcr_sampler_conversion;
VkSampler ycbcr_sampler;
// todo: align thread-shared data to unshare with immutable
volatile int decode_index, present_index;
pthread_t thread = 0;
@ -227,8 +203,33 @@ static void *DecoderThread(void*)
static void SetupFFMpeg(VkInstance inst, VulkanDevice &dev)
{
PFN_vkCreateSamplerYcbcrConversion pvkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion)vkGetInstanceProcAddr(inst, "vkCreateSamplerYcbcrConversionKHR");
CallWith($M(VkSamplerYcbcrConversionCreateInfo{VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO},
$(format) = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
$(ycbcrModel) = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
$(ycbcrRange) = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
$(xChromaOffset) = VK_CHROMA_LOCATION_COSITED_EVEN, // zero
$(yChromaOffset) = VK_CHROMA_LOCATION_COSITED_EVEN,
$(chromaFilter) = VK_FILTER_NEAREST), // zero
pvkCreateSamplerYcbcrConversion(dev.device, &ref, NULL, &gFF.ycbcr_sampler_conversion));
$Sc ycbcr_info = $M(VkSamplerYcbcrConversionInfo{VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO},
$(conversion) = gFF.ycbcr_sampler_conversion);
CallWith($M(VkSamplerCreateInfo{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, &ycbcr_info},
$(magFilter) = VK_FILTER_NEAREST,
$(minFilter) = VK_FILTER_NEAREST,
$(mipmapMode) = VK_SAMPLER_MIPMAP_MODE_NEAREST, // zero
$(addressModeU) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(addressModeV) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(addressModeW) = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
$(maxLod) = 1.0f,
$(borderColor) = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK),
vkCreateSampler(dev.device, &ref, NULL, &gFF.ycbcr_sampler);
);
for(int i = 0; i < MAX_DECODER_FRAMES; i++)
CreateSoftwareImage(inst, dev, gFF.images[i]);
CreateSoftwareImage(inst, dev, gFF.images[i], ycbcr_info);
pthread_mutex_init(&gFF.mutex, NULL);
pthread_cond_init(&gFF.cond, NULL);
pthread_create(&gFF.thread, NULL, &DecoderThread, NULL);
@ -240,7 +241,7 @@ static void SetupFFMpeg(VkInstance inst, VulkanDevice &dev)
struct GraphicsApplicationPipeline: BaseVulkanPipeline
{
void Init(VkDevice dev, VkRenderPass renderPass, VkSampler *pImmutableSamplers)
void Init(VkDevice dev, VkRenderPass renderPass, VkSampler *pImmutableSamplers, int count)
{
device = dev;
@ -248,9 +249,9 @@ struct GraphicsApplicationPipeline: BaseVulkanPipeline
//BasicBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,1,VK_SHADER_STAGE_VERTEX_BIT)
BasicBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,VK_SHADER_STAGE_FRAGMENT_BIT, pImmutableSamplers)
);
CreatePool(1,
CreatePool(count,
//BasicPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
BasicPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)
BasicPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, count)
);
VkShaderModule vp, fp;
CreateGraphicsPipeline(renderPass,
@ -282,7 +283,7 @@ struct GraphicsApplicationPipeline: BaseVulkanPipeline
struct ComputeApplicationPipeline: BaseVulkanPipeline
{
void Init(VkDevice dev, VkRenderPass renderPass, VkSampler *pImmutableSamplers, int count)
void Init(VkDevice dev, VkRenderPass renderPass, VkSampler *pImmutableSamplers, int count1, int count2, int count3)
{
device = dev;
@ -290,9 +291,9 @@ struct ComputeApplicationPipeline: BaseVulkanPipeline
BasicBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,VK_SHADER_STAGE_COMPUTE_BIT, pImmutableSamplers),
BasicBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,1,VK_SHADER_STAGE_COMPUTE_BIT)
);
CreatePool(count,
BasicPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, count),
BasicPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, count));
CreatePool((count1 + count3) * count2,
BasicPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, count2 * count3),
BasicPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, count3 * count2 * count1));
VkShaderModule shader;
CreateComputePipeline(ShaderFromFile(shader, "quad.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT));
// todo: should not we destroy shader internally?
@ -311,15 +312,27 @@ struct GraphicsApplication
VulkanContext context;
VulkanDevice dev;
GLFWwindow *window = NULL;
// swapchain stuff
VkSwapchainKHR swapchain;
VkSurfaceKHR surface;
VkImage swapchainImages[MAX_SWAPCHAIN_IMAGES];
unsigned int numSwapchainImages;
VulkanFramebuffer swapchainFbs[MAX_SWAPCHAIN_IMAGES];
VkCommandBuffer commandBuffers[MAX_SWAPCHAIN_IMAGES * RECONSTRUCTION_TARGET_FRAMES];
VkCommandBuffer reconstructionCommandBuffers[MAX_DECODER_FRAMES * RECONSTRUCTION_TARGET_FRAMES];
VkFence chainFences[MAX_SWAPCHAIN_IMAGES];
VkSemaphore swapchainRenderSemaphore[MAX_SWAPCHAIN_IMAGES], swapchainPresentSemaphore[MAX_SWAPCHAIN_IMAGES];
// direct reconstruction to swapchain
VkCommandBuffer commandBuffers[MAX_SWAPCHAIN_IMAGES * MAX_DECODER_FRAMES];
// reconstruction to temporary framebuffer
VulkanFramebuffer reconstructionFbs[RECONSTRUCTION_TARGET_FRAMES];
VkImage reconstructionImages[RECONSTRUCTION_TARGET_FRAMES];
VkDeviceMemory reconstructionImagesMem[RECONSTRUCTION_TARGET_FRAMES];
VkCommandBuffer reconstructionCommandBuffers[MAX_DECODER_FRAMES * RECONSTRUCTION_TARGET_FRAMES];
VkCommandBuffer presentCommandBuffers[MAX_SWAPCHAIN_IMAGES * RECONSTRUCTION_TARGET_FRAMES];
VkSemaphore reconstructionSemaphore[RECONSTRUCTION_TARGET_FRAMES];
struct UBO
{
//glm::mat4 transformationMatrix;
@ -328,7 +341,9 @@ struct GraphicsApplication
GraphicsApplicationPipeline graphicsPipeline;
ComputeApplicationPipeline computePipeline;
VkDescriptorSet descriptorSet;
VkDescriptorSet descriptorSets[MAX_SWAPCHAIN_IMAGES];
VkDescriptorSet swapchainDescriptorSets[MAX_SWAPCHAIN_IMAGES*MAX_DECODER_FRAMES];
VkDescriptorSet reconstructionDescriptorSets[RECONSTRUCTION_TARGET_FRAMES*MAX_DECODER_FRAMES];
VkDescriptorSet decodeDescriptorSet[MAX_DECODER_FRAMES];
VulkanBuffer uboBuf;
VulkanBuffer stagingVert;
VulkanBuffer stagingInd;
@ -378,7 +393,7 @@ struct GraphicsApplication
$(imageColorSpace) = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
$(imageExtent) = VkExtent2D{width, height},
$(imageArrayLayers),$(queueFamilyIndexCount),$(clipped),
$(imageUsage) = graphics?VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:VK_IMAGE_USAGE_STORAGE_BIT,
$(imageUsage) = VK_IMAGE_USAGE_TRANSFER_DST_BIT | (graphics?VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:VK_IMAGE_USAGE_STORAGE_BIT),
$(pQueueFamilyIndices) = &dev.defaultFamilyIndex,
$(preTransform) = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
$(compositeAlpha) = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
@ -468,7 +483,8 @@ struct GraphicsApplication
#else
#define ENABLE_VALIDATION_LAYERS 0
#endif
bool compute = true;
bool compute = false;
bool separateReconstruction = false;
context.Create("streamingengine", "vulkan-playground-server", ENABLE_VALIDATION_LAYERS);
dev.Create(context.FindPhysicalDevice(), compute?VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
dev.CreateDevice(context);
@ -476,24 +492,73 @@ struct GraphicsApplication
int height = 1080;
CreateWindow("demo", width, height, false);
CreateSwapchain(width,height, !compute);
printf("%d swapchain images\n", numSwapchainImages);
dev.CreateAndMap(uboBuf, sizeof(UBO));
SetupFFMpeg(context.instance, dev);
for(int i = 0; i < RECONSTRUCTION_TARGET_FRAMES; i++)
{
VkSemaphoreCreateInfo semaphoreCreateInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
VK_CHECK_RESULT(vkCreateSemaphore(dev.device, &semaphoreCreateInfo, nullptr, &reconstructionSemaphore[i]));
CallWith(Image2dInfo(VK_IMAGE_USAGE_STORAGE_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_FORMAT_B8G8R8A8_UNORM, width, height),
vkCreateImage(dev.device, &ref,NULL, &reconstructionImages[i]));
VkMemoryRequirements mem_reqs;
vkGetImageMemoryRequirements(dev.device, reconstructionImages[i], &mem_reqs);
VkMemoryAllocateInfo mem_alloc = AllocateInfo(mem_reqs.size);
if (!dev.GetMemoryType(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&mem_alloc.memoryTypeIndex))
printf("Could not find memory type.\n");
VK_CHECK_RESULT(vkAllocateMemory(dev.device, &mem_alloc, NULL, &reconstructionImagesMem[i]));
VK_CHECK_RESULT(vkBindImageMemory(dev.device, reconstructionImages[i], reconstructionImagesMem[i], 0));
}
if(compute)
{
computePipeline.Init(dev.device, swapchainFbs[0].render_pass, &gFF.images[0].ycbcr_sampler, numSwapchainImages);
computePipeline.Init(dev.device, swapchainFbs[0].render_pass, &gFF.ycbcr_sampler, numSwapchainImages, MAX_DECODER_FRAMES, RECONSTRUCTION_TARGET_FRAMES);
for(int i = 0; i < numSwapchainImages; i++)
{
descriptorSets[i] = computePipeline.AllocateSingleDescriptorSet();
computePipeline.UpdateDescriptors(descriptorSets[i], gFF.images[0].image_view, gFF.images[0].ycbcr_sampler, swapchainFbs[i].color_view);
for(int j = 0; j < MAX_DECODER_FRAMES; j++)
{
int ci = MAX_DECODER_FRAMES * i + j;
swapchainDescriptorSets[ci] = computePipeline.AllocateSingleDescriptorSet();
computePipeline.UpdateDescriptors(swapchainDescriptorSets[ci], gFF.images[j].image_view, gFF.ycbcr_sampler, swapchainFbs[i].color_view);
}
}
for(int i = 0; i < RECONSTRUCTION_TARGET_FRAMES; i++)
{
CallWith($M(VkImageViewCreateInfo{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO},
$(image) = reconstructionImages[i], $(viewType) = VK_IMAGE_VIEW_TYPE_2D,
$(format) = VK_FORMAT_B8G8R8A8_UNORM,
$(subresourceRange) = SubresourceRange()),
vkCreateImageView(dev.device, &ref, NULL, &reconstructionFbs[i].color_view));
for(int j = 0; j < MAX_DECODER_FRAMES; j++)
{
int ci = MAX_DECODER_FRAMES * i + j;
reconstructionDescriptorSets[ci] = computePipeline.AllocateSingleDescriptorSet();
computePipeline.UpdateDescriptors(reconstructionDescriptorSets[ci], gFF.images[j].image_view, gFF.ycbcr_sampler, reconstructionFbs[i].color_view);
}
}
}
else
{
graphicsPipeline.Init(dev.device, swapchainFbs[0].render_pass, &gFF.images[0].ycbcr_sampler);
descriptorSet = graphicsPipeline.AllocateSingleDescriptorSet();
graphicsPipeline.UpdateDescriptors(descriptorSet, gFF.images[0].image_view, gFF.images[0].ycbcr_sampler);
graphicsPipeline.Init(dev.device, swapchainFbs[0].render_pass, &gFF.ycbcr_sampler, MAX_DECODER_FRAMES);
for(int j = 0; j < MAX_DECODER_FRAMES; j++)
{
decodeDescriptorSet[j] = graphicsPipeline.AllocateSingleDescriptorSet();
graphicsPipeline.UpdateDescriptors(decodeDescriptorSet[j], gFF.images[j].image_view, gFF.ycbcr_sampler);
}
for(int i = 0; i < RECONSTRUCTION_TARGET_FRAMES; i++)
{
reconstructionFbs[i].Create(dev.device);
reconstructionFbs[i].CreateDepthAttachment(dev,VK_FORMAT_D32_SFLOAT, width, height);
reconstructionFbs[i].Init(reconstructionImages[i],VK_FORMAT_B8G8R8A8_UNORM, width, height);
}
}
updateUniformData();
/*updateUniformData();
Vertex vertices[] = {
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f } },
@ -505,60 +570,143 @@ struct GraphicsApplication
dev.CreateBuffer(stagingVert, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, sizeof(vertices), vertices);
dev.CreateBuffer(stagingInd, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, sizeof(indices), indices);
*/
for(int i = 0; i < numSwapchainImages; i++)
{
commandBuffers[i] = dev.CreateCommandBuffer();
//VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
//vkCmdClearColorImage(commandBuffers[i], swapchainImages[i],VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &color, 1, &range );
if(!compute)
for(int j = 0; j < MAX_DECODER_FRAMES; j++)
{
swapchainFbs[i].BeginRenderPass(commandBuffers[i]);
swapchainFbs[i].SetViewportAndScissor(commandBuffers[i]);
int ci = MAX_DECODER_FRAMES * i + j;
commandBuffers[ci] = dev.CreateCommandBuffer();
//VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
//vkCmdClearColorImage(commandBuffers[i], swapchainImages[i],VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &color, 1, &range );
if(!compute)
{
swapchainFbs[i].BeginRenderPass(commandBuffers[ci]);
swapchainFbs[i].SetViewportAndScissor(commandBuffers[ci]);
vkCmdBindDescriptorSets(commandBuffers[i],VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipeline);
// VkDeviceSize offset = 0;
//vkCmdBindVertexBuffers(commandBuffers[i],0, 1, &stagingVert.buffer, &offset);
//vkCmdBindIndexBuffer(commandBuffers[i], stagingInd.buffer, 0, VK_INDEX_TYPE_UINT32);
//vkCmdDrawIndexed(commandBuffers[i], 3, 1, 0, 0, 0);
vkCmdDraw(commandBuffers[i], 4, 1, 0, 0);
vkCmdEndRenderPass(commandBuffers[i]);
VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
vkCmdBindDescriptorSets(commandBuffers[ci],VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipelineLayout, 0, 1, &decodeDescriptorSet[j], 0, nullptr);
vkCmdBindPipeline(commandBuffers[ci], VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipeline);
// VkDeviceSize offset = 0;
//vkCmdBindVertexBuffers(commandBuffers[i],0, 1, &stagingVert.buffer, &offset);
//vkCmdBindIndexBuffer(commandBuffers[i], stagingInd.buffer, 0, VK_INDEX_TYPE_UINT32);
//vkCmdDrawIndexed(commandBuffers[i], 3, 1, 0, 0, 0);
vkCmdDraw(commandBuffers[ci], 4, 1, 0, 0);
vkCmdEndRenderPass(commandBuffers[ci]);
VulkanTexture::SetImageLayout(commandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
}
else
{
const int WIDTH = 1920; // Size of rendered mandelbrot set.
const int HEIGHT = 1080; // Size of renderered mandelbrot set.
const int WORKGROUP_SIZE = 32; // Workgroup size in compute shader.
VulkanTexture::SetImageLayout(commandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
vkCmdBindPipeline(commandBuffers[ci], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipeline);
vkCmdBindDescriptorSets(commandBuffers[ci], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipelineLayout, 0, 1, &swapchainDescriptorSets[ci], 0, NULL);
vkCmdDispatch(commandBuffers[ci], (uint32_t)ceil(WIDTH / float(WORKGROUP_SIZE)), (uint32_t)ceil(HEIGHT / float(WORKGROUP_SIZE)), 1);
VulkanTexture::SetImageLayout(commandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
}
vkEndCommandBuffer(commandBuffers[ci]);
}
else
{
const int WIDTH = 1920; // Size of rendered mandelbrot set.
const int HEIGHT = 1080; // Size of renderered mandelbrot set.
const int WORKGROUP_SIZE = 32; // Workgroup size in compute shader.
VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipeline);
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipelineLayout, 0, 1, &descriptorSets[i], 0, NULL);
vkCmdDispatch(commandBuffers[i], (uint32_t)ceil(WIDTH / float(WORKGROUP_SIZE)), (uint32_t)ceil(HEIGHT / float(WORKGROUP_SIZE)), 1);
VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
}
vkEndCommandBuffer(commandBuffers[i]);
VK_CHECK_RESULT(CallWith(FenceInfo(VK_FENCE_CREATE_SIGNALED_BIT),
vkCreateFence(dev.device, &ref, NULL, &chainFences[i])));
}
for(int i = 0; i < numSwapchainImages; i++)
{
for(int j = 0; j < RECONSTRUCTION_TARGET_FRAMES; j++)
{
int ci = RECONSTRUCTION_TARGET_FRAMES*i+j;
presentCommandBuffers[ci] = dev.CreateCommandBuffer();
//VulkanTexture::SetImageLayout(presentCommandBuffers[ci], reconstructionImages[j], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
VulkanTexture::SetImageLayout(presentCommandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
VkImageCopy regions = $M(VkImageCopy{}, $(srcSubresource) = SubresourceLayers(), $(dstSubresource) = SubresourceLayers(), $(extent) = VkExtent3D{1920, 1080, 1});
vkCmdCopyImage(presentCommandBuffers[ci], reconstructionImages[j],VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchainImages[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &regions);
VulkanTexture::SetImageLayout(presentCommandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
vkEndCommandBuffer(presentCommandBuffers[ci]);
}
}
for(int i = 0; i < RECONSTRUCTION_TARGET_FRAMES; i++)
{
for(int j = 0; j < MAX_DECODER_FRAMES; j++)
{
int ci = RECONSTRUCTION_TARGET_FRAMES*i+j;
reconstructionCommandBuffers[ci] = dev.CreateCommandBuffer();
if(!compute)
{
VulkanTexture::SetImageLayout(reconstructionCommandBuffers[ci], reconstructionImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
reconstructionFbs[i].BeginRenderPass(reconstructionCommandBuffers[ci]);
reconstructionFbs[i].SetViewportAndScissor(reconstructionCommandBuffers[ci]);
vkCmdBindDescriptorSets(reconstructionCommandBuffers[ci],VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipelineLayout, 0, 1, &decodeDescriptorSet[j], 0, nullptr);
vkCmdBindPipeline(reconstructionCommandBuffers[ci], VK_PIPELINE_BIND_POINT_GRAPHICS,graphicsPipeline.pipeline);
// VkDeviceSize offset = 0;
//vkCmdBindVertexBuffers(commandBuffers[i],0, 1, &stagingVert.buffer, &offset);
//vkCmdBindIndexBuffer(commandBuffers[i], stagingInd.buffer, 0, VK_INDEX_TYPE_UINT32);
//vkCmdDrawIndexed(commandBuffers[i], 3, 1, 0, 0, 0);
vkCmdDraw(reconstructionCommandBuffers[ci], 4, 1, 0, 0);
vkCmdEndRenderPass(reconstructionCommandBuffers[ci]);
VulkanTexture::SetImageLayout(reconstructionCommandBuffers[ci], reconstructionImages[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
}
else
{
const int WIDTH = 1920; // Size of rendered mandelbrot set.
const int HEIGHT = 1080; // Size of renderered mandelbrot set.
const int WORKGROUP_SIZE = 32; // Workgroup size in compute shader.
//VulkanTexture::SetImageLayout(reconstructionCommandBuffers[ci], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
VulkanTexture::SetImageLayout(reconstructionCommandBuffers[ci], reconstructionImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
vkCmdBindPipeline(reconstructionCommandBuffers[ci], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipeline);
vkCmdBindDescriptorSets(reconstructionCommandBuffers[ci], VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipelineLayout, 0, 1, &reconstructionDescriptorSets[ci], 0, NULL);
vkCmdDispatch(reconstructionCommandBuffers[ci], (uint32_t)ceil(WIDTH / float(WORKGROUP_SIZE)), (uint32_t)ceil(HEIGHT / float(WORKGROUP_SIZE)), 1);
VulkanTexture::SetImageLayout(reconstructionCommandBuffers[ci], reconstructionImages[i], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
}
vkEndCommandBuffer(reconstructionCommandBuffers[ci]);
}
}
uint32_t idx = 0;
int sem_idx = 0;
int ridx = 0;
while(true)
{
updateUniformData();
sem_idx = (sem_idx + 1) % numSwapchainImages;
waitFence(sem_idx);
idx = AcquireImage(sem_idx);
int decoder_idx = WaitActiveFrame() & 3;
VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
vkResetFences(dev.device,1, &chainFences[sem_idx]);
CallWith(
SubmitInfo(
commandBuffers[idx],$(waitSemaphoreCount), $(signalSemaphoreCount),
$(pWaitSemaphores) = &swapchainRenderSemaphore[sem_idx],
$(pSignalSemaphores) = &swapchainPresentSemaphore[idx],
$(pWaitDstStageMask) = &waitDstStageMask),
vkQueueSubmit(dev.defautQueue, 1, &ref, chainFences[sem_idx]));
if(separateReconstruction)
{
CallWith(
SubmitInfo(
reconstructionCommandBuffers[ridx * MAX_DECODER_FRAMES + decoder_idx],$(waitSemaphoreCount), $(signalSemaphoreCount),
$(pWaitSemaphores) = &swapchainRenderSemaphore[sem_idx],
$(pSignalSemaphores) = &reconstructionSemaphore[ridx],
$(pWaitDstStageMask) = &waitDstStageMask),
vkQueueSubmit(dev.defautQueue, 1, &ref, NULL));
CallWith(
SubmitInfo(
presentCommandBuffers[idx * RECONSTRUCTION_TARGET_FRAMES + ridx],$(waitSemaphoreCount), $(signalSemaphoreCount),
$(pWaitSemaphores) = &reconstructionSemaphore[ridx],
$(pSignalSemaphores) = &swapchainPresentSemaphore[idx],
$(pWaitDstStageMask) = &waitDstStageMask),
vkQueueSubmit(dev.defautQueue, 1, &ref, chainFences[sem_idx]));
ridx = (ridx + 1) & 3;
}
else
{
CallWith(
SubmitInfo(
commandBuffers[idx*MAX_DECODER_FRAMES + decoder_idx],$(waitSemaphoreCount), $(signalSemaphoreCount),
$(pWaitSemaphores) = &swapchainRenderSemaphore[sem_idx],
$(pSignalSemaphores) = &swapchainPresentSemaphore[idx],
$(pWaitDstStageMask) = &waitDstStageMask),
vkQueueSubmit(dev.defautQueue, 1, &ref, chainFences[sem_idx]));
}
PresentImage(idx);
}
vkDeviceWaitIdle(dev.device);
graphicsPipeline.Destroy();

View file

@ -74,6 +74,11 @@ VkSubresourceLayout SubresourceLayout(VkDeviceSize pitch, const Args&... argumen
{
return $M(VkSubresourceLayout{0},$(rowPitch) = pitch,arguments...);
}
template <typename... Args>
VkImageSubresourceLayers SubresourceLayers(const Args&... arguments)
{
return $M(VkImageSubresourceLayers{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, arguments...);
}
VkFenceCreateInfo FenceInfo(VkFenceCreateFlags flags = 0)
{