summaryrefslogtreecommitdiff
path: root/vktest/vktest.c
diff options
context:
space:
mode:
Diffstat (limited to 'vktest/vktest.c')
-rw-r--r--vktest/vktest.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/vktest/vktest.c b/vktest/vktest.c
new file mode 100644
index 0000000..31bc828
--- /dev/null
+++ b/vktest/vktest.c
@@ -0,0 +1,208 @@
+#include <vulkan/vulkan.h>
+#include <X11/Xlib.h>
+#include <vulkan/vulkan_xlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define W 1260
+#define H 720
+
+#define CK(x) do { VkResult _r = (x); if (_r != VK_SUCCESS) { \
+ fprintf(stderr, "FAIL %s -> %d\n", #x, _r); exit(1); } } while (0)
+
+int main()
+{
+ Display *dpy = XOpenDisplay( NULL );
+ if (!dpy) { fprintf( stderr, "no display\n" ); return 1; }
+ Window win = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 10, 10, W, H, 0, 0, 0 );
+ XStoreName( dpy, win, "vktest" );
+ XMapWindow( dpy, win );
+ XFlush( dpy );
+
+ const char *iexts[] = { "VK_KHR_surface", "VK_KHR_xlib_surface" };
+ VkApplicationInfo ai = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+ ai.apiVersion = VK_API_VERSION_1_1;
+ VkInstanceCreateInfo ici = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+ ici.pApplicationInfo = &ai;
+ ici.enabledExtensionCount = 2;
+ ici.ppEnabledExtensionNames = iexts;
+ VkInstance inst;
+ CK( vkCreateInstance(&ici, NULL, &inst ));
+
+ uint32_t n = 1;
+ VkPhysicalDevice phys;
+ vkEnumeratePhysicalDevices( inst, &n, &phys );
+
+ VkSurfaceKHR surf;
+ VkXlibSurfaceCreateInfoKHR sci = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR };
+ sci.dpy = dpy;
+ sci.window = win;
+ CK( vkCreateXlibSurfaceKHR( inst, &sci, NULL, &surf ) );
+
+ uint32_t nfam = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties( phys, &nfam, NULL );
+ VkQueueFamilyProperties fam[8];
+ if( nfam > 8 ) nfam = 8;
+ vkGetPhysicalDeviceQueueFamilyProperties( phys, &nfam, fam );
+ uint32_t qf = UINT32_MAX;
+ for( uint32_t i = 0; i < nfam; i++ ) {
+ VkBool32 pres = VK_FALSE;
+ vkGetPhysicalDeviceSurfaceSupportKHR( phys, i, surf, &pres );
+ if( (fam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && pres ) { qf = i; break; }
+ }
+ if( qf == UINT32_MAX ) { fprintf( stderr, "no queue\n" ); return 1; }
+
+ float prio = 1.0f;
+ VkDeviceQueueCreateInfo qci = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
+ qci.queueFamilyIndex = qf;
+ qci.queueCount = 1;
+ qci.pQueuePriorities = &prio;
+ const char *dexts[] = { "VK_KHR_swapchain" };
+ VkDeviceCreateInfo dci = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ dci.queueCreateInfoCount = 1;
+ dci.pQueueCreateInfos = &qci;
+ dci.enabledExtensionCount = 1;
+ dci.ppEnabledExtensionNames = dexts;
+ VkDevice dev;
+ CK( vkCreateDevice( phys, &dci, NULL, &dev ) );
+ VkQueue q;
+ vkGetDeviceQueue( dev, qf, 0, &q );
+
+ VkSurfaceFormatKHR fmts[16];
+ uint32_t nfmt = 16;
+ vkGetPhysicalDeviceSurfaceFormatsKHR( phys, surf, &nfmt, fmts );
+ VkSurfaceCapabilitiesKHR caps;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR( phys, surf, &caps );
+
+ VkSwapchainCreateInfoKHR scci = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
+ scci.surface = surf;
+ scci.minImageCount = caps.minImageCount;
+ scci.imageFormat = fmts[0].format;
+ scci.imageColorSpace = fmts[0].colorSpace;
+ scci.imageExtent.width = W;
+ scci.imageExtent.height = H;
+ scci.imageArrayLayers = 1;
+ scci.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ scci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ scci.preTransform = caps.currentTransform;
+ scci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ scci.presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ scci.clipped = VK_TRUE;
+ VkSwapchainKHR sc;
+ CK( vkCreateSwapchainKHR( dev, &scci, NULL, &sc ) );
+ printf( "swapchain format: %d\n", fmts[0].format );
+
+ uint32_t nimg = 8;
+ VkImage imgs[8];
+ vkGetSwapchainImagesKHR( dev, sc, &nimg, imgs );
+
+ VkCommandPoolCreateInfo cpci = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+ cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ cpci.queueFamilyIndex = qf;
+ VkCommandPool pool;
+ CK( vkCreateCommandPool( dev, &cpci, NULL, &pool ));
+ VkCommandBufferAllocateInfo cbai = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+ cbai.commandPool = pool;
+ cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ cbai.commandBufferCount = 1;
+ VkCommandBuffer cb;
+ CK( vkAllocateCommandBuffers( dev, &cbai, &cb ) );
+
+ VkSemaphoreCreateInfo semci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
+ VkSemaphore acq, ren;
+ CK( vkCreateSemaphore( dev, &semci, NULL, &acq ) );
+ CK( vkCreateSemaphore( dev, &semci, NULL, &ren ) );
+ VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
+ VkFence fence;
+ CK( vkCreateFence(dev, &fci, NULL, &fence ));
+
+ VkBufferCreateInfo bci = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bci.size = (VkDeviceSize)W * H * 4;
+ bci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ VkBuffer rb;
+ CK( vkCreateBuffer( dev, &bci, NULL, &rb ) );
+ VkMemoryRequirements mr;
+ vkGetBufferMemoryRequirements( dev, rb, &mr );
+ VkPhysicalDeviceMemoryProperties mp;
+ vkGetPhysicalDeviceMemoryProperties( phys, &mp );
+ uint32_t type = 0;
+ for( uint32_t i = 0; i < mp.memoryTypeCount; i++ ) {
+ if( (mr.memoryTypeBits & (1u << i)) && (mp.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ) {
+ type = i; break;
+ }
+ }
+ VkMemoryAllocateInfo mai = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ mai.allocationSize = mr.size;
+ mai.memoryTypeIndex = type;
+ VkDeviceMemory rmem;
+ CK( vkAllocateMemory(dev, &mai, NULL, &rmem ) );
+ CK( vkBindBufferMemory(dev, rb, rmem, 0 ) );
+
+ VkImageSubresourceRange range;
+ memset( &range, 0, sizeof( range ));
+ range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ range.levelCount = 1;
+ range.layerCount = 1;
+
+ for( ;; ) {
+ uint32_t idx;
+ CK( vkAcquireNextImageKHR(dev, sc, UINT64_MAX, acq, VK_NULL_HANDLE, &idx ) );
+
+ VkCommandBufferBeginInfo bi = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+ bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ CK( vkBeginCommandBuffer( cb, &bi ) );
+
+ VkImageMemoryBarrier b = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+ b.srcAccessMask = 0;
+ b.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ b.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ b.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ b.srcQueueFamilyIndex = b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ b.image = imgs[idx];
+ b.subresourceRange = range;
+ vkCmdPipelineBarrier(
+ cb, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL,
+ 0, NULL, 1, &b
+ );
+
+ VkClearColorValue col = { { 0.05f, 0.10f, 0.20f, 1.0f } };
+ vkCmdClearColorImage( cb, imgs[idx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &col, 1, &range );
+
+ b.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ b.dstAccessMask = 0;
+ b.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ b.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ vkCmdPipelineBarrier(
+ cb, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL,
+ 0, NULL, 1, &b
+ );
+ CK( vkEndCommandBuffer( cb ) );
+
+ VkPipelineStageFlags wait = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+ si.waitSemaphoreCount = 1;
+ si.pWaitSemaphores = &acq;
+ si.pWaitDstStageMask = &wait;
+ si.commandBufferCount = 1;
+ si.pCommandBuffers = &cb;
+ si.signalSemaphoreCount = 1;
+ si.pSignalSemaphores = &ren;
+ CK( vkQueueSubmit(q, 1, &si, VK_NULL_HANDLE ) );
+
+ VkPresentInfoKHR pi = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
+ pi.waitSemaphoreCount = 1;
+ pi.pWaitSemaphores = &ren;
+ pi.swapchainCount = 1;
+ pi.pSwapchains = &sc;
+ pi.pImageIndices = &idx;
+ CK( vkQueuePresentKHR( q, &pi ) );
+ vkQueueWaitIdle( q );
+ usleep( 1 );
+ }
+
+ return 0;
+}