Start of Vulkan compute rendering code. Getting FBIDs (glxgears still OK).

This commit is contained in:
Pierre-Loup A. Griffais 2019-12-07 01:11:33 -08:00 committed by Pierre-Loup A. Griffais
parent df5244f547
commit 2be0bdbcbb
8 changed files with 370 additions and 6 deletions

View file

@ -15,6 +15,7 @@ dep_xxf86vm = dependency('xxf86vm')
pixman_dep = dependency('pixman-1')
drm_dep = dependency('libdrm')
wlroots_dep = dependency('wlroots')
vulkan_dep = dependency('vulkan')
cc = meson.get_compiler('c')
@ -56,10 +57,11 @@ executable(
'src/main.c',
'src/wlserver.c',
'src/drm.cpp',
'src/rendervulkan.cpp',
dependencies : [
dep_x11, dep_xdamage, dep_xcomposite, dep_xrender, dep_xext, dep_gl,
dep_xxf86vm, pixman_dep, drm_dep, wlroots_dep, wayland_server,
wayland_protos, libinput, xkbcommon, math, thread_dep, waffle_dep,
wlroots_static_dep
wlroots_static_dep, vulkan_dep
],
)

View file

@ -13,7 +13,8 @@
#include <sys/select.h>
#include <signal.h>
#include "drm.h"
#include "drm.hpp"
#include "main.hpp"
#include <thread>
@ -407,6 +408,9 @@ int init_drm(struct drm_t *drm, const char *device, const char *mode_str, unsign
std::thread flip_handler_thread( flip_handler_thread_run );
flip_handler_thread.detach();
g_nOutputWidth = drm->mode->hdisplay;
g_nOutputHeight = drm->mode->vdisplay;
return 0;
}

View file

@ -11,7 +11,7 @@
#include "main.hpp"
#include "main.h"
#include "drm.h"
#include "drm.hpp"
#include <waffle.h>
@ -26,6 +26,9 @@ int g_nNestedWidth = 1280;
int g_nNestedHeight = 720;
int g_nNestedRefresh = 60;
int g_nOutputWidth = 1280;
int g_nOutputHeight = 720;
bool g_bIsNested = false;
int BIsNested()
@ -121,8 +124,8 @@ void initOutput(void)
0,
};
const int32_t window_width = 1280;
const int32_t window_height = 720;
const int32_t window_width = g_nOutputWidth;
const int32_t window_height = g_nOutputHeight;
waffle_init(init_attrs);
dpy = waffle_display_connect(NULL);

View file

@ -24,6 +24,9 @@ extern int g_nNestedWidth;
extern int g_nNestedHeight;
extern int g_nNestedRefresh;
extern int g_nOutputWidth;
extern int g_nOutputHeight;
int BIsNested( void );
#ifndef C_SIDE

312
src/rendervulkan.cpp Normal file
View file

@ -0,0 +1,312 @@
// Initialize Vulkan and composite stuff with a compute queue
#include "rendervulkan.hpp"
#include "main.hpp"
PFN_vkGetMemoryFdKHR dyn_vkGetMemoryFdKHR;
const VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "steamcompmgr",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "just some code",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_0,
};
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
uint32_t queueFamilyIndex;
VkQueue queue;
VkDevice device = VK_NULL_HANDLE;
struct VkPhysicalDeviceMemoryProperties memoryProperties;
CVulkanOutputImage outputImage[2];
#define MAX_DEVICE_COUNT 8
#define MAX_QUEUE_COUNT 8
#define VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA (VkStructureType)1000001002
#define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA (VkStructureType)1000001003
struct wsi_image_create_info {
VkStructureType sType;
const void *pNext;
bool scanout;
uint32_t modifier_count;
const uint64_t *modifiers;
};
struct wsi_memory_allocate_info {
VkStructureType sType;
const void *pNext;
bool implicit_sync;
};
static inline uint32_t DRMFormatToVulkanFormat( VkFormat vkFormat )
{
switch ( vkFormat )
{
case VK_FORMAT_R8G8B8A8_UNORM:
return DRM_FORMAT_RGBA8888;
default:
return DRM_FORMAT_INVALID;
}
}
int32_t findMemoryType( VkMemoryPropertyFlags properties, uint32_t requiredTypeBits )
{
for ( uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++ )
{
if ( ( ( 1 << i ) & requiredTypeBits ) == 0 )
continue;
if ( ( properties & memoryProperties.memoryTypes[ i ].propertyFlags ) != properties )
continue;
return i;
}
return -1;
}
bool CVulkanOutputImage::BInit(uint32_t width, uint32_t height, VkFormat format)
{
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
// We'll only access it with compute probably
VkImageUsageFlags usage = VK_IMAGE_USAGE_STORAGE_BIT;
VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.tiling = tiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = usage;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
// If not nested, these images will be flipped directly to the screen
if ( BIsNested() == false )
{
wsi_image_create_info wsiImageCreateInfo = {};
wsiImageCreateInfo.sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA;
wsiImageCreateInfo.scanout = VK_TRUE;
imageInfo.pNext = &wsiImageCreateInfo;
}
if (vkCreateImage(device, &imageInfo, nullptr, &m_vkImage) != VK_SUCCESS) {
return false;
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device, m_vkImage, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(properties, memRequirements.memoryTypeBits );
if ( BIsNested() == false )
{
wsi_memory_allocate_info wsiAllocInfo = {};
wsiAllocInfo.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA;
wsiAllocInfo.implicit_sync = true;
allocInfo.pNext = &wsiAllocInfo;
const VkExportMemoryAllocateInfo memory_export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = &memory_export_info,
.image = m_vkImage,
.buffer = VK_NULL_HANDLE,
};
wsiAllocInfo.pNext = &memory_dedicated_info;
}
if (vkAllocateMemory(device, &allocInfo, nullptr, &m_vkImageMemory) != VK_SUCCESS) {
return false;
}
VkResult res = vkBindImageMemory(device, m_vkImage, m_vkImageMemory, 0);
if ( res != VK_SUCCESS )
return false;
m_DMA = {};
if ( BIsNested() == false )
{
m_DMA.modifier = DRM_FORMAT_MOD_INVALID;
m_DMA.n_planes = 1;
m_DMA.width = width;
m_DMA.height = height;
m_DMA.format = DRMFormatToVulkanFormat( format );
const VkMemoryGetFdInfoKHR memory_get_fd_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
.pNext = NULL,
.memory = m_vkImageMemory,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
res = dyn_vkGetMemoryFdKHR(device, &memory_get_fd_info, &m_DMA.fd[0]);
if ( res != VK_SUCCESS )
return false;
const VkImageSubresource image_subresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.arrayLayer = 0,
};
VkSubresourceLayout image_layout;
vkGetImageSubresourceLayout(device, m_vkImage, &image_subresource, &image_layout);
m_DMA.stride[0] = image_layout.rowPitch;
m_FBID = drm_fbid_from_dmabuf( &g_DRM, &m_DMA );
if ( m_FBID == 0 )
return false;
}
return true;
}
int init_device()
{
uint32_t physicalDeviceCount;
VkPhysicalDevice deviceHandles[MAX_DEVICE_COUNT];
VkQueueFamilyProperties queueFamilyProperties[MAX_QUEUE_COUNT];
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, 0);
physicalDeviceCount = physicalDeviceCount > MAX_DEVICE_COUNT ? MAX_DEVICE_COUNT : physicalDeviceCount;
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, deviceHandles);
for (uint32_t i = 0; i < physicalDeviceCount; ++i)
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(deviceHandles[i], &queueFamilyCount, NULL);
queueFamilyCount = queueFamilyCount > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(deviceHandles[i], &queueFamilyCount, queueFamilyProperties);
for (uint32_t j = 0; j < queueFamilyCount; ++j) {
if ( queueFamilyProperties[j].queueFlags & VK_QUEUE_COMPUTE_BIT &&
!(queueFamilyProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT ) )
{
queueFamilyIndex = j;
physicalDevice = deviceHandles[i];
}
}
if (physicalDevice)
{
break;
}
}
vkGetPhysicalDeviceMemoryProperties( physicalDevice, &memoryProperties );
float queuePriorities = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = queueFamilyIndex,
.queueCount = 1,
.pQueuePriorities = &queuePriorities
};
std::vector< const char * > vecEnabledDeviceExtensions;
vecEnabledDeviceExtensions.push_back( VK_KHR_SWAPCHAIN_EXTENSION_NAME );
vecEnabledDeviceExtensions.push_back( VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME );
vecEnabledDeviceExtensions.push_back( VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME );
VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queueCreateInfo,
.enabledLayerCount = 0,
.ppEnabledLayerNames = 0,
.enabledExtensionCount = (uint32_t)vecEnabledDeviceExtensions.size(),
.ppEnabledExtensionNames = vecEnabledDeviceExtensions.data(),
.pEnabledFeatures = 0,
};
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, NULL, &device);
if ( result != VK_SUCCESS )
{
return false;
}
vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
if ( queue == VK_NULL_HANDLE )
return false;
return true;
}
void fini_device()
{
vkDestroyDevice(device, 0);
}
int init_vulkan(void)
{
VkResult result = VK_ERROR_INITIALIZATION_FAILED;
std::vector< const char * > vecEnabledInstanceExtensions;
vecEnabledInstanceExtensions.push_back( VK_KHR_SURFACE_EXTENSION_NAME );
vecEnabledInstanceExtensions.push_back( VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME );
const VkInstanceCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = (uint32_t)vecEnabledInstanceExtensions.size(),
.ppEnabledExtensionNames = vecEnabledInstanceExtensions.data(),
};
result = vkCreateInstance(&createInfo, 0, &instance);
if ( result != VK_SUCCESS )
return 0;
if ( init_device() != 1 )
{
return 0;
}
dyn_vkGetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)vkGetDeviceProcAddr( device, "vkGetMemoryFdKHR" );
if ( dyn_vkGetMemoryFdKHR == nullptr )
return 0;
bool bSuccess = outputImage[0].BInit( g_nOutputWidth, g_nOutputHeight, VK_FORMAT_R8G8B8A8_UNORM );
if ( bSuccess != true )
return 0;
bSuccess = outputImage[1].BInit( g_nOutputWidth, g_nOutputHeight, VK_FORMAT_R8G8B8A8_UNORM );
if ( bSuccess != true )
return 0;
return 1;
}

34
src/rendervulkan.hpp Normal file
View file

@ -0,0 +1,34 @@
// Initialize Vulkan and composite stuff with a compute queue
#pragma once
#include "drm.hpp"
#ifndef C_SIDE
extern "C" {
#endif
#include <vulkan/vulkan.h>
#include <wlr/render/dmabuf.h>
#include <drm_fourcc.h>
#ifndef C_SIDE
class CVulkanOutputImage
{
public:
bool BInit(uint32_t width, uint32_t height, VkFormat format);
private:
VkImage m_vkImage;
VkDeviceMemory m_vkImageMemory;
wlr_dmabuf_attributes m_DMA;
uint32_t m_FBID;
};
#endif
int init_vulkan(void);
#ifndef C_SIDE
}
#endif

View file

@ -61,7 +61,8 @@
#include "main.hpp"
#include "wlserver.h"
#include "drm.h"
#include "drm.hpp"
#include "rendervulkan.hpp"
#define WAFFLE_API_VERSION 0x0106
#include <waffle.h>
@ -1802,6 +1803,11 @@ steamcompmgr_main (int argc, char **argv)
eglSwapInterval( eglGetCurrentDisplay(), 1 );
}
if ( init_vulkan() != True )
{
fprintf (stderr, "alarm!!!\n");
}
glEnable (GL_DEBUG_OUTPUT);
glDebugMessageCallback(MessageCallback, 0);