Start implementing basic ffmpeg decoder
This commit is contained in:
parent
7c8ee5f384
commit
0d90b67015
3 changed files with 465 additions and 20 deletions
|
@ -72,12 +72,6 @@ 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.
|
||||
|
||||
|
||||
/*
|
||||
The application launches a compute shader that renders the mandelbrot set,
|
||||
by rendering it into a storage buffer.
|
||||
The storage buffer is then read from the GPU, and saved as .png.
|
||||
*/
|
||||
struct ComputeApplication {
|
||||
// The pixels of the rendered mandelbrot set are in this format:
|
||||
struct Pixel {
|
||||
|
@ -173,22 +167,9 @@ struct ComputeApplication {
|
|||
The validation layer will NOT give warnings if you forget these, so be very careful not to forget them.
|
||||
*/
|
||||
vkCmdBindPipeline(chain[chidx].commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipeline);
|
||||
/*
|
||||
Now we shall start recording commands into the newly allocated command buffer.
|
||||
*/
|
||||
vkCmdBindDescriptorSets(chain[chidx].commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipelineLayout, 0, 1, &chain[chidx].descriptorSet, 0, NULL);
|
||||
|
||||
/*
|
||||
Calling vkCmdDispatch basically starts the compute pipeline, and executes the compute shader.
|
||||
The number of workgroups is specified in the arguments.
|
||||
If you are already familiar with compute shaders from OpenGL, this should be nothing new to you.
|
||||
*/
|
||||
vkCmdDispatch(chain[chidx].commandBuffer, (uint32_t)ceil(WIDTH/2 / float(WORKGROUP_SIZE)), (uint32_t)ceil(HEIGHT/2 / float(WORKGROUP_SIZE)), 1);
|
||||
|
||||
VK_CHECK_RESULT(vkEndCommandBuffer(chain[chidx].commandBuffer)); // end recording commands.
|
||||
/*
|
||||
We create a fence.
|
||||
*/
|
||||
$Sc fenceCreateInfo = FenceInfo();
|
||||
VK_CHECK_RESULT(vkCreateFence(dev.device, &fenceCreateInfo, NULL, &chain[chidx].fence));
|
||||
|
||||
|
|
462
vkplayer.cpp
Normal file
462
vkplayer.cpp
Normal file
|
@ -0,0 +1,462 @@
|
|||
#include "vulkan_pipeline_utl.h"
|
||||
#include "vulkan_utl.h"
|
||||
#include "vulkan_framebuffer_utl.h"
|
||||
#include "vulkan_texture_utl.h"
|
||||
#include "vulkan_contructors.h"
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/avassert.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
}
|
||||
#include <pthread.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
// use glfw for temporary swapchain window
|
||||
// todo: GET RID OF THIS, IT SOMEHOW INCLUDES GL!!!
|
||||
#include <GLFW/glfw3.h>
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#include <GLFW/glfw3native.h>
|
||||
// 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
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float position[3];
|
||||
float color[3];
|
||||
};
|
||||
|
||||
|
||||
struct DecoderImage
|
||||
{
|
||||
VkSamplerYcbcrConversion ycbcr_sampler_conversion;
|
||||
VkSampler ycbcr_sampler;
|
||||
VkImage image;
|
||||
VkDeviceMemory image_memory;
|
||||
// todo: deduplicate shared parameters
|
||||
VkDeviceSize memory_offset_plane0, memory_offset_plane1;
|
||||
VkImageView image_view;
|
||||
unsigned char *pMappedData;
|
||||
};
|
||||
|
||||
|
||||
void CreateSoftwareImage(VkInstance inst, VulkanDevice &dev, DecoderImage &image)
|
||||
{
|
||||
|
||||
CallWith(Image2dInfo(VK_IMAGE_USAGE_SAMPLED_BIT, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, 1920, 1080,
|
||||
$(flags) = VK_IMAGE_CREATE_DISJOINT_BIT,
|
||||
$(tiling) = VK_IMAGE_TILING_LINEAR,
|
||||
$(initialLayout) = VK_IMAGE_LAYOUT_PREINITIALIZED ),
|
||||
vkCreateImage(dev.device, &ref,NULL, &image.image));
|
||||
|
||||
VkImagePlaneMemoryRequirementsInfo plane_info = $M(VkImagePlaneMemoryRequirementsInfo{VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO},
|
||||
$(planeAspect) = VK_IMAGE_ASPECT_PLANE_0_BIT);
|
||||
VkImageMemoryRequirementsInfo2 image_info = $M(VkImageMemoryRequirementsInfo2{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2},
|
||||
$(image) = image.image);
|
||||
VkMemoryRequirements2 image_reqs = $M(VkMemoryRequirements2{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2});
|
||||
image_info.pNext = &plane_info;
|
||||
PFN_vkGetImageMemoryRequirements2 pvkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)vkGetInstanceProcAddr(inst, "vkGetImageMemoryRequirements2KHR");
|
||||
pvkGetImageMemoryRequirements2(dev.device, &image_info, &image_reqs);
|
||||
|
||||
VkDeviceSize image_size = image_reqs.memoryRequirements.size;
|
||||
uint32_t image_bits = image_reqs.memoryRequirements.memoryTypeBits;
|
||||
image.memory_offset_plane0 = 0;
|
||||
image.memory_offset_plane1 = image_size; // todo: should not we align plane offset here
|
||||
plane_info.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
|
||||
pvkGetImageMemoryRequirements2(dev.device, &image_info, &image_reqs);
|
||||
|
||||
image_size += image_reqs.memoryRequirements.size;
|
||||
image_bits = image_bits | image_reqs.memoryRequirements.memoryTypeBits;
|
||||
|
||||
VkMemoryAllocateInfo ainfo = AllocateInfo(image_size);
|
||||
dev.GetMemoryType(image_bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &ainfo.memoryTypeIndex);
|
||||
vkAllocateMemory(dev.device, &ainfo, NULL, &image.image_memory);
|
||||
VkBindImagePlaneMemoryInfo plane0i = {VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, NULL, VK_IMAGE_ASPECT_PLANE_0_BIT};
|
||||
VkBindImagePlaneMemoryInfo plane1i = {VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, NULL, VK_IMAGE_ASPECT_PLANE_1_BIT};
|
||||
VkBindImageMemoryInfo bindInfo[2] = {{VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, &plane0i}, {VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, &plane1i}};
|
||||
$F(bindInfo[0], $(image) = image.image, $(memory) = image.image_memory, $(memoryOffset) = image.memory_offset_plane0);
|
||||
$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,
|
||||
$(subresourceRange) = SubresourceRange()),
|
||||
vkCreateImageView(dev.device, &ref, NULL, &image.image_view));
|
||||
vkMapMemory(dev.device, image.image_memory, 0, image_size, 0, (void**)&image.pMappedData);
|
||||
}
|
||||
static struct FFmpegDecoder
|
||||
{
|
||||
DecoderImage images[4];
|
||||
// todo: align thread-shared data to unshare with immutable
|
||||
volatile int decode_index, present_index;
|
||||
pthread_t thread = 0;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
// todo: should keep availiable frames list/mask here (atomic uint64_t?)
|
||||
} gFF;
|
||||
|
||||
static int WaitActiveFrame()
|
||||
{
|
||||
// todo: where frame selection should be done?
|
||||
pthread_mutex_lock(&gFF.mutex);
|
||||
while(gFF.decode_index <= gFF.present_index)
|
||||
pthread_cond_wait(&gFF.cond, &gFF.mutex);
|
||||
int ret = ++gFF.present_index;
|
||||
pthread_mutex_unlock(&gFF.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *DecoderThread(void*)
|
||||
{
|
||||
AVFormatContext *input_ctx = NULL;
|
||||
AVCodec *decoder = NULL;
|
||||
AVCodecContext *decoder_ctx = NULL;
|
||||
AVPacket *packet = NULL;
|
||||
int video;
|
||||
avformat_open_input(&input_ctx, "out.265", NULL, NULL);
|
||||
avformat_find_stream_info(input_ctx, NULL);
|
||||
video = av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
|
||||
decoder_ctx = avcodec_alloc_context3(decoder);
|
||||
avcodec_open2(decoder_ctx, decoder, NULL);
|
||||
packet = av_packet_alloc();
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
int idx = 0;
|
||||
while(true)
|
||||
{
|
||||
av_read_frame(input_ctx, packet);
|
||||
if(packet->stream_index == video)
|
||||
{
|
||||
|
||||
int res = avcodec_send_packet(decoder_ctx, packet);
|
||||
if(res >= 0)
|
||||
{
|
||||
res = avcodec_receive_frame(decoder_ctx, frame);
|
||||
if(res < 0)
|
||||
break;
|
||||
idx++;
|
||||
DecoderImage &img = gFF.images[idx & 3];
|
||||
// todo: wait fence?
|
||||
memcpy(img.pMappedData + img.memory_offset_plane0 , frame->data[0], frame->linesize[0] + frame->height);
|
||||
memcpy(img.pMappedData + img.memory_offset_plane1 , frame->data[1], frame->linesize[1] + frame->height/2);
|
||||
pthread_mutex_lock(&gFF.mutex);
|
||||
gFF.decode_index = idx;
|
||||
pthread_cond_signal(&gFF.cond);
|
||||
pthread_mutex_unlock(&gFF.mutex);
|
||||
printf("frame %d\n", idx);
|
||||
usleep(20000);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void SetupFFMpeg(VkInstance inst, VulkanDevice &dev)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
CreateSoftwareImage(inst, dev, gFF.images[i]);
|
||||
pthread_mutex_init(&gFF.mutex, NULL);
|
||||
pthread_cond_init(&gFF.cond, NULL);
|
||||
pthread_create(&gFF.thread, NULL, &DecoderThread, NULL);
|
||||
}
|
||||
|
||||
struct GraphicsApplicationPipeline: BaseVulkanPipeline
|
||||
{
|
||||
|
||||
void Init(VkDevice dev, VkRenderPass renderPass)
|
||||
{
|
||||
|
||||
device = dev;
|
||||
CreateDescriptorSetLayout(
|
||||
BasicBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,1,VK_SHADER_STAGE_VERTEX_BIT)
|
||||
);
|
||||
CreatePool(1,
|
||||
BasicPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
|
||||
);
|
||||
VkShaderModule vp, fp;
|
||||
CreateGraphicsPipeline(renderPass,
|
||||
Stages(
|
||||
ShaderFromFile(vp, "triangle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
|
||||
ShaderFromFile(fp, "triangle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT)),
|
||||
VertexBindings(
|
||||
VertexBinding(0, sizeof(Vertex))
|
||||
),
|
||||
VertexAttributes(
|
||||
VertAttrib(0, 0, offsetof(Vertex,position)),
|
||||
VertAttrib(1, 0, offsetof(Vertex,color))
|
||||
),
|
||||
DynamicStates(
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
),
|
||||
DepthStencil(true, true)
|
||||
);
|
||||
vkDestroyShaderModule(device, vp, NULL);
|
||||
vkDestroyShaderModule(device, fp, NULL);
|
||||
}
|
||||
void UpdateDescriptors(VkDescriptorSet dstSet, const VkDescriptorBufferInfo &buffer)
|
||||
{
|
||||
WriteDescriptors(
|
||||
BufferWrite(dstSet, 0, buffer)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct GraphicsApplication
|
||||
{
|
||||
VulkanContext context;
|
||||
VulkanDevice dev;
|
||||
GLFWwindow *window = NULL;
|
||||
VkSwapchainKHR swapchain;
|
||||
VkSurfaceKHR surface;
|
||||
VkImage swapchainImages[MAX_SWAPCHAIN_IMAGES];
|
||||
unsigned int numSwapchainImages;
|
||||
VulkanFramebuffer swapchainFbs[MAX_SWAPCHAIN_IMAGES];
|
||||
VkCommandBuffer commandBuffers[MAX_SWAPCHAIN_IMAGES];
|
||||
VkFence chainFences[MAX_SWAPCHAIN_IMAGES];
|
||||
VkSemaphore swapchainRenderSemaphore[MAX_SWAPCHAIN_IMAGES], swapchainPresentSemaphore[MAX_SWAPCHAIN_IMAGES];
|
||||
struct UBO
|
||||
{
|
||||
glm::mat4 transformationMatrix;
|
||||
};
|
||||
|
||||
GraphicsApplicationPipeline graphicsPipeline;
|
||||
VkDescriptorSet descriptorSet;
|
||||
VulkanBuffer uboBuf;
|
||||
VulkanBuffer stagingVert;
|
||||
VulkanBuffer stagingInd;
|
||||
//VkFence swapchainFence;
|
||||
void CreateWindow(const char* windowTitle, int& outWidth, int& outHeight, bool resizable)
|
||||
{
|
||||
if (!glfwInit())
|
||||
return;
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
// render full screen without overlapping taskbar
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
window = glfwCreateWindow(outWidth, outHeight, windowTitle, nullptr, nullptr);
|
||||
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
glfwGetWindowSize(window, &outWidth, &outHeight);
|
||||
|
||||
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int, int action, int) {
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
});
|
||||
|
||||
glfwSetErrorCallback([](int error, const char* description) { printf("GLFW Error (%i): %s\n", error, description); });
|
||||
}
|
||||
void DestroyWindow()
|
||||
{
|
||||
if(window)
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
void CreateSwapchain(uint32_t width, uint32_t height)
|
||||
{
|
||||
VK_CHECK_RESULT(CallWith($M(VkXlibSurfaceCreateInfoKHR{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR},
|
||||
$(dpy) = glfwGetX11Display(), $(window) = glfwGetX11Window(window)),
|
||||
vkCreateXlibSurfaceKHR(context.instance, &ref, nullptr, &surface)));
|
||||
CallWith($M(
|
||||
VkSwapchainCreateInfoKHR{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR},
|
||||
$(surface) = surface, $(minImageCount) = 4,
|
||||
$(imageFormat) = VK_FORMAT_B8G8R8A8_UNORM,
|
||||
$(imageColorSpace) = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||
$(imageExtent) = VkExtent2D{width, height},
|
||||
$(imageArrayLayers),$(queueFamilyIndexCount),$(clipped),
|
||||
$(imageUsage) = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
$(pQueueFamilyIndices) = &dev.defaultFamilyIndex,
|
||||
$(preTransform) = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
||||
$(compositeAlpha) = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
|
||||
$(presentMode) = VK_PRESENT_MODE_FIFO_KHR),
|
||||
vkCreateSwapchainKHR(dev.device, &ref, nullptr, &swapchain));
|
||||
|
||||
numSwapchainImages = MAX_SWAPCHAIN_IMAGES;
|
||||
|
||||
VK_CHECK_RESULT(vkGetSwapchainImagesKHR(dev.device, swapchain, &numSwapchainImages, swapchainImages));
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
||||
for(int i = 0; i < numSwapchainImages; i++)
|
||||
{
|
||||
swapchainFbs[i].Create(dev.device);
|
||||
swapchainFbs[i].CreateDepthAttachment(dev, VK_FORMAT_D32_SFLOAT, width, height);
|
||||
swapchainFbs[i].Init(swapchainImages[i], VK_FORMAT_B8G8R8A8_UNORM, width, height);
|
||||
VK_CHECK_RESULT(vkCreateSemaphore(dev.device, &semaphoreCreateInfo, nullptr, &swapchainPresentSemaphore[i]));
|
||||
VK_CHECK_RESULT(vkCreateSemaphore(dev.device, &semaphoreCreateInfo, nullptr, &swapchainRenderSemaphore[i]));
|
||||
}
|
||||
}
|
||||
unsigned int AcquireImage(int sem_index, VkFence fence = NULL)
|
||||
{
|
||||
unsigned int index;
|
||||
vkAcquireNextImageKHR(dev.device, swapchain, UINT64_MAX, swapchainRenderSemaphore[sem_index], fence, &index);
|
||||
return index;
|
||||
}
|
||||
void PresentImage(unsigned int index)
|
||||
{
|
||||
CallWith(PresentInfo(&swapchain, &index, &swapchainPresentSemaphore[index]),
|
||||
vkQueuePresentKHR(dev.defautQueue, &ref));
|
||||
}
|
||||
void DestroySwapchain()
|
||||
{
|
||||
for(int i = 0; i < numSwapchainImages; i++)
|
||||
{
|
||||
swapchainFbs[i].Destroy();
|
||||
vkDestroySemaphore(dev.device, swapchainPresentSemaphore[i], NULL);
|
||||
vkDestroySemaphore(dev.device, swapchainRenderSemaphore[i], NULL);
|
||||
}
|
||||
vkDestroySwapchainKHR(dev.device, swapchain, NULL);
|
||||
vkDestroySurfaceKHR(context.instance,surface,NULL);
|
||||
}
|
||||
|
||||
// todo: NUKE THIS!!!
|
||||
void updateUniformData() {
|
||||
static unsigned int frameNum;
|
||||
// Rotate based on time
|
||||
long long millis = frameNum++;
|
||||
float angle = (millis % 400) / 400.0f * glm::radians(360.f);
|
||||
|
||||
glm::mat4 modelMatrix = glm::identity<glm::mat4>();
|
||||
modelMatrix = glm::rotate(modelMatrix, angle, glm::vec3(0, 0, 1));
|
||||
//((UBO*)uboBuf.mapped)->transformationMatrix = modelMatrix;
|
||||
modelMatrix = glm::translate(modelMatrix, glm::vec3(0.5f / 3.0f, -0.5f / 3.0f, 0.0f));
|
||||
|
||||
// Set up view
|
||||
auto viewMatrix = glm::lookAt(glm::vec3(1, 1, 1), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1));
|
||||
|
||||
// Set up projection
|
||||
auto projMatrix = glm::perspective(glm::radians(70.f), 800.0f / 600.0f, 0.1f, 10.0f);
|
||||
((UBO*)uboBuf.mapped)->transformationMatrix = projMatrix * viewMatrix * modelMatrix;
|
||||
}
|
||||
|
||||
void waitFence(int chidx)
|
||||
{
|
||||
VK_CHECK_RESULT(vkWaitForFences(dev.device, 1, &chainFences[chidx], VK_TRUE, 100000000000));
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#define ENABLE_VALIDATION_LAYERS 1
|
||||
#else
|
||||
#define ENABLE_VALIDATION_LAYERS 0
|
||||
#endif
|
||||
context.Create("streamingengine", "vulkan-playground-server", ENABLE_VALIDATION_LAYERS);
|
||||
dev.Create(context.FindPhysicalDevice(), VK_QUEUE_GRAPHICS_BIT);
|
||||
dev.CreateDevice(context);
|
||||
int width = 800;
|
||||
int height = 600;
|
||||
CreateWindow("demo", width, height, false);
|
||||
CreateSwapchain(width,height);
|
||||
dev.CreateAndMap(uboBuf, sizeof(UBO));
|
||||
graphicsPipeline.Init(dev.device, swapchainFbs[0].render_pass);
|
||||
descriptorSet = graphicsPipeline.AllocateSingleDescriptorSet();
|
||||
graphicsPipeline.UpdateDescriptors(descriptorSet, uboBuf.descriptor);
|
||||
updateUniformData();
|
||||
|
||||
Vertex vertices[] = {
|
||||
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f } },
|
||||
{ { -0.5f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f } },
|
||||
{ { 0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f } }
|
||||
};
|
||||
|
||||
uint32_t indices[] = { 0, 1, 2 };
|
||||
|
||||
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 );
|
||||
swapchainFbs[i].BeginRenderPass(commandBuffers[i]);
|
||||
swapchainFbs[i].SetViewportAndScissor(commandBuffers[i]);
|
||||
|
||||
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);
|
||||
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 });
|
||||
vkEndCommandBuffer(commandBuffers[i]);
|
||||
VK_CHECK_RESULT(CallWith(FenceInfo(VK_FENCE_CREATE_SIGNALED_BIT),
|
||||
vkCreateFence(dev.device, &ref, NULL, &chainFences[i])));
|
||||
}
|
||||
SetupFFMpeg(context.instance, dev);
|
||||
uint32_t idx = 0;
|
||||
int sem_idx = 0;
|
||||
while(true)
|
||||
{
|
||||
updateUniformData();
|
||||
sem_idx = (sem_idx + 1) % numSwapchainImages;
|
||||
waitFence(sem_idx);
|
||||
idx = AcquireImage(sem_idx);
|
||||
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]));
|
||||
PresentImage(idx);
|
||||
}
|
||||
vkDeviceWaitIdle(dev.device);
|
||||
graphicsPipeline.Destroy();
|
||||
stagingVert.Destroy();
|
||||
stagingInd.Destroy();
|
||||
uboBuf.Destroy();
|
||||
DestroySwapchain();
|
||||
DestroyWindow();
|
||||
dev.Destroy();
|
||||
context.Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
GraphicsApplication app;
|
||||
app.Run();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -388,11 +388,13 @@ struct VulkanDevice
|
|||
deviceExtensions[deviceExtensionsCount++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
|
||||
|
||||
VkPhysicalDeviceFeatures enabled_features = {
|
||||
.samplerAnisotropy = VK_TRUE,
|
||||
.samplerAnisotropy = VK_TRUE
|
||||
};
|
||||
VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrFeat = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, .samplerYcbcrConversion = VK_TRUE};
|
||||
|
||||
VkDeviceCreateInfo device_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &ycbcrFeat,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queue_info,
|
||||
.enabledLayerCount = ctx.enabledLayersCount,
|
||||
|
|
Loading…
Reference in a new issue