Цель состоит в том, чтобы полностью поменять Каир и использовать Vulkan/Skia для рисования и отображения на мой GTK GUI, но всякий раз, когда я пытаюсь что -то нарисовать, это не сработает. Чтобы использовать Vulkan/Skia, вам нужно сначала настроить устройство Vulkan. Я добавил немного x11, и объясню, почему прямо ниже этого вставленного кода: < /p>
static const void initialize_x11_vulkan() {
// Configure X11
Display* xdisplay = XOpenDisplay(NULL);
if (!xdisplay) {
g_error("Failed to open X display");
return;
}
// Create X11 window
int screen = DefaultScreen(xdisplay);
std::unique_ptr xwindow = std::make_unique(XCreateSimpleWindow(xdisplay,
RootWindow(xdisplay, screen),
0, 0, 500, 500, 0,
BlackPixel(xdisplay, screen),
WhitePixel(xdisplay, screen)));
// Embed X11 window into GTK
GdkDisplay* gdk_display = gdk_x11_lookup_xdisplay(xdisplay);
GdkWindow* gdk_window = gdk_x11_window_foreign_new_for_display(
gdk_display,
*(xwindow.get())
);
gtk_widget_register_window(ui->window, gdk_window);
// Check to see if context is not nullptr
if (!initialize_vulkan(vkBackendContext, xdisplay, *(xwindow.get()))) {
// TODO: We can't do GpGp, so everything will be running on the cpu
printf("Failed!\n");
return;
}
free(gdk_display);
free(gdk_window);
}
< /code>
Приведенный выше код интегрирует в него x11, позволяя мне создать какой -то тип поверхности вулкан и каким -то образом подавать его в бэкэнд, и тогда я смогу визуально увидеть чертеж ..? Это был мой ход мыслей, но я сомневался в себе и выбросил эту идею, поэтому я здесь. Идея появилась отсюда: каков вульковский эквивалент виджета gtkglarea (gtk+)?static const bool initialize_vulkan(skgpu::VulkanBackendContext &vkBackendContext, Display* xdisplay, Window &xwindow) {
std::unique_ptr appInfo = std::make_unique();
appInfo.get()->sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.get()->apiVersion = VK_API_VERSION_1_3;
// Enable the Extension for Vulkan
std::vector instance_extensions = {
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_XLIB_SURFACE_EXTENSION_NAME
};
std::unique_ptr instance_create_info = std::make_unique();
instance_create_info.get()->enabledExtensionCount = static_cast(instance_extensions.size());
instance_create_info.get()->ppEnabledExtensionNames = instance_extensions.data();
instance_create_info.get()->pApplicationInfo = appInfo.release();
vkCreateInstance(instance_create_info.get(), nullptr, &vkBackendContext.fInstance);
instance_create_info.release(); // Clean up the instance_create_info pointer
// Check and see if the device supports vulkan
if (&vkBackendContext.fInstance == nullptr) {
printf("Device does not support vulkan!\n");
return initialize_gpl();
}
// Enable X11 Support
std::unique_ptr create_info = std::make_unique();
create_info.get()->sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
create_info.get()->dpy = xdisplay;
create_info.get()->window = xwindow;
if (vkCreateXlibSurfaceKHR(vkBackendContext.fInstance, create_info.get(), NULL, &vk_surface) != VK_SUCCESS) {
printf("Failed to initialize Vulkan with X11!\n");
return false;
}
create_info.release();
// Check to see if the vulkan device is compatible
if (vkEnumeratePhysicalDevices(vkBackendContext.fInstance, &deviceCount, nullptr) != VK_SUCCESS) {
printf("No Vulkan-compatible GPUs found!\n");
return initialize_gpl();
}
std::vector devices(deviceCount);
// Get the vulkan devices and loop
if (vkEnumeratePhysicalDevices(vkBackendContext.fInstance, &deviceCount, devices.data()) != VK_SUCCESS) {
printf("Could not find Physical Device!\n");
return initialize_gpl();
}
for (int i = 0; i < devices.size(); i++) {
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(devices.at(i), &props);
// Prefer discrete GPUs
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
vkBackendContext.fPhysicalDevice = devices.at(i);
queueFamilyIndex = i;
break;
}
}
// Fallback to first device if no discrete GPU found
if (vkBackendContext.fPhysicalDevice == VK_NULL_HANDLE && !devices.empty()) {
vkBackendContext.fPhysicalDevice = devices.at(0);
queueFamilyIndex = 0;
}
else return initialize_gpl();
// Get the max supported version of your vulkan
std::unique_ptr props = std::make_unique();
vkGetPhysicalDeviceProperties(vkBackendContext.fPhysicalDevice, props.get());
vkBackendContext.fMaxAPIVersion = VK_API_VERSION_1_3;
props.release();
// Enable all the features physical device features two
std::unique_ptr ext_feature = std::make_unique();
ext_feature.get()->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
std::unique_ptr physical_features2 = std::make_unique();
physical_features2.get()->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physical_features2.get()->pNext = ext_feature.release();
vkGetPhysicalDeviceFeatures2(vkBackendContext.fPhysicalDevice, physical_features2.get());
vkBackendContext.fDeviceFeatures2 = physical_features2.release();
// Logic if feature is not supported
//if (features.robustBufferAccess == VK_FALSE) { return 1;}
// Enable Device For Vulkan
std::unique_ptr< VkDeviceCreateInfo> device_create_info = std::make_unique();
std::vector device_extensions = {
VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
VK_KHR_SWAPCHAIN_EXTENSION_NAME, // Enables the ability to render to surface
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, // Optional but recommended
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
};
float queuePriority = 1.0f;
std::unique_ptr queue_create_info = std::make_unique();
queue_create_info.get()->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.get()->queueFamilyIndex = queueFamilyIndex;
queue_create_info.get()->queueCount = 1;
queue_create_info.get()->pQueuePriorities = &queuePriority;
device_create_info.get()->sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.get()->queueCreateInfoCount = 1;
device_create_info.get()->pQueueCreateInfos = queue_create_info.release();
device_create_info.get()->enabledExtensionCount = static_cast(device_extensions.size());
device_create_info.get()->ppEnabledExtensionNames = device_extensions.data();
if (vkCreateDevice(vkBackendContext.fPhysicalDevice, device_create_info.get(), nullptr, &vkBackendContext.fDevice) != VK_SUCCESS) {
printf("Failed to create Vulkan device!\n");
return false;
}
device_create_info.release(); // Clean up the device_create_info
// Create the Queue
vkGetDeviceQueue(vkBackendContext.fDevice, queueFamilyIndex, 0, &vkBackendContext.fQueue);
vkBackendContext.fGraphicsQueueIndex = queueFamilyIndex;
// Get the Proc for the Device
vkBackendContext.fGetProc = [](const char *name, VkInstance inst, VkDevice dev) -> PFN_vkVoidFunction {
if (dev != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(dev, name);
}
return vkGetInstanceProcAddr(inst, name);
};
// Enable skia support
std::unique_ptr fvk(new skgpu::VulkanExtensions());
fvk.get()->init(vkBackendContext.fGetProc, vkBackendContext.fInstance, vkBackendContext.fPhysicalDevice, static_cast(instance_extensions.size()), instance_extensions.data(), static_cast(device_extensions.size()), device_extensions.data());
vkBackendContext.fVkExtensions = fvk.release();
// Initialize the context
context = GrDirectContexts::MakeVulkan(vkBackendContext);
if (!context) {
// TODO: If context returns nullptr, then call in check_compatibility and get the latest api version avialable
// TODO: A feature might be missing. All of that will be resolved in check_compatibility function
if (check_compatibility(vkBackendContext)) {
sk_sp context = GrDirectContexts::MakeVulkan(vkBackendContext);
if (!context) {
return initialize_gpl();
}
}
return initialize_gpl();
}
return true;
}
Приведенный выше код устанавливает устройство Vulkan и инициализирует переменную контекста . Который необходим для следующего шага для получения Canvas .
Это мой код чертежа, где белая коробка должна быть заполнена на моем графическом интерфейсе:
static const gboolean on_source_image_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
// Want this color: #d2d2d4 rgba(219, 219, 219, 0.8)
TileGridUI *ui = (TileGridUI *)user_data;
render_data_t* state = render;
// GrVkImageInfo is used to construct GrBackendTexture and GrBackendRenderTarget objects that in turn are used to create SkSurface and SkImage objects that refer to VkImages created by the Skia client.
// Draw background
if (!draw.update_image_grid_container_drawing) {
// Get widget dimensions
dimensions.width = gtk_widget_get_allocated_width(widget);
dimensions.height = gtk_widget_get_allocated_height(widget);
std::unique_ptr allocation = std::make_unique();
gtk_widget_get_allocation(widget, allocation.get());
dimensions.x = allocation.get()->x; // Get x position
dimensions.y = allocation.get()->y; // Get y position
draw.update_image_grid_container_drawing = TRUE;
allocation.release();
}
strokePaint.setStyle(SkPaint::kStroke_Style); // Set the type of stroke
strokePaint.setStrokeWidth(3.0f); // Set the line width
fillPaint.setColor(SkColorSetARGB(219, 219, 219, 0.8f));
// Create an SkSurface backed by a Vulkan VkImage. Often clients will be getting VkImages from
// swapchains. In those cases they should use SkSurfaces::WrapBackendTexture or
// SkSurfaces::WrapBackendRenderTarget to wrap those premade VkImages in Skia.
SkImageInfo info = SkImageInfo::MakeN32Premul(dimensions.width, dimensions.height);
// Wrapper below self cleans
sk_sp gpuSurface(
SkSurfaces::RenderTarget(context.get(), skgpu::Budgeted::kNo, info));
if (!gpuSurface) {
SkDebugf("SkSurfaces::RenderTarget returned null\n");
return FALSE;
}
SkCanvas* gpuCanvas = gpuSurface->getCanvas();
gpuCanvas->drawRect(draw.rect[0].MakeXYWH(dimensions.x, dimensions.y, dimensions.width, dimensions.height), fillPaint);
context->flush();
context->submit();
return TRUE;
< /code>
draw
- это структура, которая содержит статический массив типа Skrect , который, учитывая правильные размеры x и y и ширина и высота, он должен был втянуть белый квадрат, но это не так. После поиска и поиска, создания постов на Skia-Dicuss и Forums Khronos, я нахожусь в тупике. Кто -нибудь может помочь мне объяснить, почему это не притягивается к моему графическому интерфейсу?
Цель состоит в том, чтобы полностью поменять Каир и использовать Vulkan/Skia для рисования и отображения на мой GTK GUI, но всякий раз, когда я пытаюсь что -то нарисовать, это не сработает. Чтобы использовать Vulkan/Skia, вам нужно сначала настроить устройство Vulkan. Я добавил немного x11, и объясню, почему прямо ниже этого вставленного кода: < /p> [code]static const void initialize_x11_vulkan() { // Configure X11 Display* xdisplay = XOpenDisplay(NULL); if (!xdisplay) { g_error("Failed to open X display"); return; }
// Check to see if context is not nullptr if (!initialize_vulkan(vkBackendContext, xdisplay, *(xwindow.get()))) { // TODO: We can't do GpGp, so everything will be running on the cpu printf("Failed!\n"); return; } free(gdk_display); free(gdk_window);
} < /code> Приведенный выше код интегрирует в него x11, позволяя мне создать какой -то тип поверхности вулкан и каким -то образом подавать его в бэкэнд, и тогда я смогу визуально увидеть чертеж ..? Это был мой ход мыслей, но я сомневался в себе и выбросил эту идею, поэтому я здесь. Идея появилась отсюда: каков вульковский эквивалент виджета gtkglarea (gtk+)?static const bool initialize_vulkan(skgpu::VulkanBackendContext &vkBackendContext, Display* xdisplay, Window &xwindow) { std::unique_ptr appInfo = std::make_unique(); appInfo.get()->sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.get()->apiVersion = VK_API_VERSION_1_3; // Enable the Extension for Vulkan std::vector instance_extensions = { VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME }; std::unique_ptr instance_create_info = std::make_unique(); instance_create_info.get()->enabledExtensionCount = static_cast(instance_extensions.size()); instance_create_info.get()->ppEnabledExtensionNames = instance_extensions.data(); instance_create_info.get()->pApplicationInfo = appInfo.release(); vkCreateInstance(instance_create_info.get(), nullptr, &vkBackendContext.fInstance); instance_create_info.release(); // Clean up the instance_create_info pointer // Check and see if the device supports vulkan if (&vkBackendContext.fInstance == nullptr) { printf("Device does not support vulkan!\n"); return initialize_gpl(); } // Enable X11 Support std::unique_ptr create_info = std::make_unique(); create_info.get()->sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; create_info.get()->dpy = xdisplay; create_info.get()->window = xwindow; if (vkCreateXlibSurfaceKHR(vkBackendContext.fInstance, create_info.get(), NULL, &vk_surface) != VK_SUCCESS) { printf("Failed to initialize Vulkan with X11!\n"); return false; } create_info.release(); // Check to see if the vulkan device is compatible if (vkEnumeratePhysicalDevices(vkBackendContext.fInstance, &deviceCount, nullptr) != VK_SUCCESS) { printf("No Vulkan-compatible GPUs found!\n"); return initialize_gpl(); } std::vector devices(deviceCount); // Get the vulkan devices and loop if (vkEnumeratePhysicalDevices(vkBackendContext.fInstance, &deviceCount, devices.data()) != VK_SUCCESS) { printf("Could not find Physical Device!\n"); return initialize_gpl(); } for (int i = 0; i < devices.size(); i++) { VkPhysicalDeviceProperties props; vkGetPhysicalDeviceProperties(devices.at(i), &props);
// Fallback to first device if no discrete GPU found if (vkBackendContext.fPhysicalDevice == VK_NULL_HANDLE && !devices.empty()) { vkBackendContext.fPhysicalDevice = devices.at(0); queueFamilyIndex = 0; } else return initialize_gpl();
// Get the max supported version of your vulkan std::unique_ptr props = std::make_unique(); vkGetPhysicalDeviceProperties(vkBackendContext.fPhysicalDevice, props.get()); vkBackendContext.fMaxAPIVersion = VK_API_VERSION_1_3; props.release();
// Enable all the features physical device features two std::unique_ptr ext_feature = std::make_unique(); ext_feature.get()->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
// Initialize the context context = GrDirectContexts::MakeVulkan(vkBackendContext); if (!context) { // TODO: If context returns nullptr, then call in check_compatibility and get the latest api version avialable // TODO: A feature might be missing. All of that will be resolved in check_compatibility function if (check_compatibility(vkBackendContext)) { sk_sp context = GrDirectContexts::MakeVulkan(vkBackendContext); if (!context) { return initialize_gpl(); } } return initialize_gpl(); } return true; } [/code] Приведенный выше код устанавливает устройство Vulkan и инициализирует переменную контекста . Который необходим для следующего шага для получения Canvas . Это мой код чертежа, где белая коробка должна быть заполнена на моем графическом интерфейсе: [code]static const gboolean on_source_image_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data) { // Want this color: #d2d2d4 rgba(219, 219, 219, 0.8) TileGridUI *ui = (TileGridUI *)user_data; render_data_t* state = render; // GrVkImageInfo is used to construct GrBackendTexture and GrBackendRenderTarget objects that in turn are used to create SkSurface and SkImage objects that refer to VkImages created by the Skia client. // Draw background if (!draw.update_image_grid_container_drawing) { // Get widget dimensions dimensions.width = gtk_widget_get_allocated_width(widget); dimensions.height = gtk_widget_get_allocated_height(widget); std::unique_ptr allocation = std::make_unique(); gtk_widget_get_allocation(widget, allocation.get()); dimensions.x = allocation.get()->x; // Get x position dimensions.y = allocation.get()->y; // Get y position draw.update_image_grid_container_drawing = TRUE; allocation.release(); } strokePaint.setStyle(SkPaint::kStroke_Style); // Set the type of stroke strokePaint.setStrokeWidth(3.0f); // Set the line width fillPaint.setColor(SkColorSetARGB(219, 219, 219, 0.8f)); // Create an SkSurface backed by a Vulkan VkImage. Often clients will be getting VkImages from // swapchains. In those cases they should use SkSurfaces::WrapBackendTexture or // SkSurfaces::WrapBackendRenderTarget to wrap those premade VkImages in Skia. SkImageInfo info = SkImageInfo::MakeN32Premul(dimensions.width, dimensions.height); // Wrapper below self cleans sk_sp gpuSurface( SkSurfaces::RenderTarget(context.get(), skgpu::Budgeted::kNo, info)); if (!gpuSurface) { SkDebugf("SkSurfaces::RenderTarget returned null\n"); return FALSE; } SkCanvas* gpuCanvas = gpuSurface->getCanvas(); gpuCanvas->drawRect(draw.rect[0].MakeXYWH(dimensions.x, dimensions.y, dimensions.width, dimensions.height), fillPaint); context->flush(); context->submit(); return TRUE; < /code> draw[/code] - это структура, которая содержит статический массив типа Skrect , который, учитывая правильные размеры x и y и ширина и высота, он должен был втянуть белый квадрат, но это не так. После поиска и поиска, создания постов на Skia-Dicuss и Forums Khronos, я нахожусь в тупике. Кто -нибудь может помочь мне объяснить, почему это не притягивается к моему графическому интерфейсу?