Start of Vulkan compute rendering code. Getting FBIDs (glxgears still OK).
This commit is contained in:
parent
df5244f547
commit
2be0bdbcbb
8 changed files with 370 additions and 6 deletions
|
@ -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
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
312
src/rendervulkan.cpp
Normal 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
34
src/rendervulkan.hpp
Normal 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
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue