I am trying to create an instance and validate that the code can create that instance.
However, For some reason code compiles and fails to create the instance. I do not know what I am doing wrong. Everything before creating instance works. but When I try to validate instance creation it fails. I am using SDL2 to create the window.
This is my cmakelist file:
cmake_minimum_required(VERSION 3.16)
#COMPIER
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
#FLAGS
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -ggdb3")
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
#PROJECT
project(Vulkan_test LANGUAGES C)
enable_language(C)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
#Find packages installed in your system.
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(Vulkan REQUIRED vulkan)
#Include global directories
include_directories(
${SDL2_INCLUDE_DIRS}
${Vulkan_INCLUDE_DIRS}
)
#Executable Specific
add_executable(VULKAN_TEST
${CMAKE_CURRENT_SOURCE_DIR}/main.c
)
#Compile options
target_compile_options(VULKAN_TEST PUBLIC -O0 -ggdb3 -std=c2x -Wall -Wextra -Wmissing-prototypes -Wwrite-strings -Wpedantic)
#Libraries to link
target_link_libraries(
VULKAN_TEST
${SDL2_LIBRARIES}
${Vulkan_LIBRARIES}
)
This is the is the main.h file that I have:
#pragma once
/* Required Standard Headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
/* SDL2 */
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
/* Vulkan */
#include <vulkan/vulkan.h>
#define rt_assert(expr, ...) ((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \
if (!(expr)) { \
fprintf(stderr,"At function [%s] in file [%s:%d], assert failed: [(%s)].\n", __func__, __FILE__, __LINE__, (#expr)); \
__VA_ARGS__; \
exit(EXIT_FAILURE); \
} \
}))
typedef struct _App {
SDL_Window *window;
int window_height;
int window_width;
const char* window_name;
SDL_Event sdl_event;
bool quit;
VkInstance inst;
uint32_t sdlExtCount;
const char** extNames;
} App;
/* Function Prototype */
void init_window(App *);
void init_vulkan(App *);
void main_loop(App *);
void cleanup(App *);
/* sub vulkan functions */
void init_vk_instance(App *);
This file my main.c
#include "main.h"
#define SDL_MAIN_HANDLED
#define App_init(X) App (X) = { \
.window = NULL, .window_height = 600, .window_width = 800, \
.window_name = "Vulkan Test", .quit = false, \
.inst = VK_NULL_HANDLE \
}
VkApplicationInfo appInfo = {0};
VkInstanceCreateInfo instInfo = {0};
void init_vk_instance(App *App) {
/* Vulkan VkApplicationInfo */
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = App->window_name;
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
appInfo.pEngineName = App->window_name;
appInfo.engineVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
/* This is version I have installed from my linux package manager */
appInfo.apiVersion = VK_MAKE_API_VERSION(0,1,3,231);
appInfo.pNext = NULL;
/* Vulkan Instance info - VkInstanceCreateInfo */
instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instInfo.pApplicationInfo = &appInfo;
instInfo.enabledLayerCount = 0;
SDL_Vulkan_GetInstanceExtensions(App->window,&App->sdlExtCount,NULL);
App->extNames = malloc(App->sdlExtCount * sizeof(const char*));
SDL_Vulkan_GetInstanceExtensions(App->window,&App->sdlExtCount,App->extNames);
instInfo.enabledExtensionCount = App->sdlExtCount;
instInfo.ppEnabledExtensionNames = App->extNames;
for(uint32_t i = 0; i < App->sdlExtCount; i++) {
printf("%u : %s\n",i,App->extNames[i]);
}
rt_assert( (vkCreateInstance(&instInfo, NULL, &App->inst) == VK_SUCCESS), printf("Instance creation failed\n"), cleanup(App));
}
void init_vulkan(App *App) {
init_vk_instance(App);
}
void init_window(App *App) {
App->window = SDL_CreateWindow( App->window_name,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
App->window_width, App->window_height, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN |
SDL_WINDOW_RESIZABLE);
}
void cleanup(App *App) {
free(App->extNames);
SDL_DestroyWindow(App->window);
SDL_Quit();
}
void main_loop(App *App) {
while(!App->quit) {
while (SDL_PollEvent(&App->sdl_event)) {
if( App->sdl_event.type == SDL_QUIT ) App->quit = true;
}
}
}
int main ( void ) {
printf("Vulkan-Engine\n");
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
App_init(test);
init_window(&test);
init_vulkan(&test);
main_loop(&test);
vkDestroyInstance(test.inst, NULL);
cleanup(&test);
return EXIT_SUCCESS;
}
This the output I get after running my program:
Vulkan-Engine
0 : VK_KHR_surface
1 : VK_KHR_xlib_surface
At function [init_vk_instance] in file [/home/Codes/C/Vulkan/main.c:35], assert failed: [((vkCreateInstance(&instInfo, NULL, &App->inst) == VK_SUCCESS))].
Instance creation failed
CMake output during compilation:
-- The C compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
-- Checking for one of the modules 'sdl2'
-- Checking for one of the modules 'vulkan'
-- Configuring done
-- Generating done
-- Build files have been written to: /home/Codes/C/Vulkan/build
[ 50%] Building C object CMakeFiles/VULKAN_TEST.dir/main.c.o
[100%] Linking C executable /home/Codes/C/Vulkan/VULKAN_TEST
[100%] Built target VULKAN_TEST
These are the vulkan related package I have installed on my system through package manager:
As you see from the image the vulkan api version is 1.3.231.1_1. Am I using the VK_MAKE_API_VERSION(0,1,3,231) properly?
I think you are missing KHR macro
For example I am using windows 10 and MSYS2
This is what I did
#define VK_USE_PLATFORM_WIN32_KHR
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
int main(int argc, char** argv)
{
if (0 != SDL_Init(SDL_INIT_EVERYTHING))
{
printf("failed to initialize SDL2 with everything\n");
}
SDL_Window* window = SDL_CreateWindow("test", 10, 10, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN);
if (NULL == window)
{
printf("failed to create window\n");
}
VkApplicationInfo app_info = { 0 };
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.apiVersion = VK_API_VERSION_1_3;
app_info.pApplicationName = "test-app";
app_info.applicationVersion = VK_MAKE_API_VERSION(1, 0, 0, 0);
app_info.pEngineName = "test-engine";
app_info.engineVersion = VK_MAKE_API_VERSION(1, 0, 0, 0);
VkInstanceCreateInfo instance_info = { 0 };
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_info.pApplicationInfo = &app_info;
instance_info.enabledLayerCount = 0;
instance_info.ppEnabledLayerNames = NULL;
unsigned int count = 0;
SDL_Vulkan_GetInstanceExtensions(window, &count, NULL);
const char** extensions = malloc(sizeof(char*) * count);
SDL_Vulkan_GetInstanceExtensions(window, &count, extensions);
for (unsigned int i = 0; i < count; i ++)
{
printf("%u: %s\n", i, extensions[i]);
}
instance_info.enabledExtensionCount = count;
instance_info.ppEnabledExtensionNames = extensions;
VkInstance instance = VK_NULL_HANDLE;
if (0 > vkCreateInstance(&instance_info, NULL, &instance))
{
printf("failed to create instance\n");
}
VkSurfaceKHR surface = VK_NULL_HANDLE;
if (SDL_FALSE == SDL_Vulkan_CreateSurface(window, instance, &surface))
{
printf("failed to create surface, SDL Error: %s", SDL_GetError());
}
return 0;
}
For me it is working fine, so my observation is you need to find a way for defining similar macro like #define VK_USE_PLATFORM_WIN32_KHR
Below are the list extensions assumed in vulkan.h
VK_USE_PLATFORM_ANDROID_KHR
VK_USE_PLATFORM_FUCHSIA
VK_USE_PLATFORM_IOS_MVK
VK_USE_PLATFORM_MACOS_MVK
VK_USE_PLATFORM_METAL_EXT
VK_USE_PLATFORM_VI_NN
VK_USE_PLATFORM_WAYLAND_KHR
VK_USE_PLATFORM_WIN32_KHR
VK_USE_PLATFORM_XCB_KHR
VK_USE_PLATFORM_XLIB_KHR
VK_USE_PLATFORM_DIRECTFB_EXT
VK_USE_PLATFORM_XLIB_XRANDR_EXT
VK_USE_PLATFORM_GGP
VK_USE_PLATFORM_SCREEN_QNX
VK_ENABLE_BETA_EXTENSIONS
This is how I compile in MSYS2
gcc -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\ansi-c.o" "..\\src\\ansi-c.c"
gcc -o ansi-c.exe "src\\ansi-c.o" -lmingw32 -lSDL2main -lSDL2 -lvulkan-1.dll
bcm2835 init works fine, as does all the GPIO & bcm2835_delay and the like.
RPi4 & Pi400, Raspbian "Bullseye", bcm2835 1.71, Libcap installed, added the program name etc
And I've compiled with Geany
gcc -Wall -o "%e" "%f" -pthread $(pkg-config gtk+-3.0 --cflags --libs) -export-dynamic -l bcm2835 -l png -DBCM2835_HAVE_LIBCAP
Here's code:
// bcm_timer.c
//
// Example program for bcm2835 library system time
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <bcm2835.h>
uint64_t now = 0;
uint64_t then = 0;
uint rescode = 0;
int main(int argc, char **argv)
{
// Init GPIO
if ( ! bcm2835_init() )
{
printf("Fail 0x%X ", errno);
return -1;
}
then = bcm2835_st_read();
bcm2835_delay(500);
now = bcm2835_st_read();
printf("Then = 0x%lluX, Now = 0x%lluX \n", then, now) ;
bcm2835_close();
return 0;
}
Here's output:
xxx#raspberrypi:~/Develop/c/test $ ./bcm_timer
Then = 0x0X, Now = 0x0X
I have 4 files in the following example ; a header, a default implementation file, and 2 platform-specific implementation files.I define two functions; get_value_1 and get_value_2. The 'default' behavior is to return -1, but some of these functions have special implementations. I would like each function to return -1 only if another file didn't implement it.
/* interface.h *
***************/
int get_value_1();
int get_value_2();
/* default.c *
*************/
#include "interface.h"
#ifndef GET_VALUE_1
int get_value_1() { return -1; }
#endif
#ifndef GET_VALUE_2
int get_value_2() { return -1; }
#endif
/* platform1.c *
***************/
#include "interface.h"
#ifndef GET_VALUE_1
#define GET_VALUE_1
int get_value_1() { return 1; }
#endif
/* platform2.c *
***************/
#include "interface.h"
#ifndef GET_VALUE_2
#define GET_VALUE_2
int get_value_2() { return 2; }
#endif
But when I run the command gcc default.c platform1.c -shared -fpic -o platform1.so, it tells me that I've multiply defined the get_value_1 function, and that it was originally defined in platform1.c.
So how can I have a set of functions where a subset of those functions can have their behavior chosen at compile time?
make them weak in the default.c and "normal" in your platform files. So if the platform.c file implements this function as not weak, the weak one dfrom default.c will be replaced link time.
It is not the part of the standard but most compilers support it (it can be pragma, attribute or something else - you need to check in the compiler documentation)
gcc version:
#define __weak __attribute__((weak))
/* interface.h *
***************/
int get_value_1();
int get_value_2();
/* default.c *
*************/
#include "interface.h"
#ifndef GET_VALUE_1
__weak int get_value_1() { return -1; }
#endif
#ifndef GET_VALUE_2
__weak int get_value_2() { return -1; }
#endif
/* platform1.c *
***************/
#include "interface.h"
#ifndef GET_VALUE_1
#define GET_VALUE_1
int get_value_1() { return 1; }
#endif
/* platform2.c *
***************/
#include "interface.h"
#ifndef GET_VALUE_2
#define GET_VALUE_2
int get_value_2() { return 2; }
#endif
I have a simple C program that represents a loading screen within the console, but I can't get the cursor to hide. I tried cranking up the speed of the sleep function so that the cursor timer would be reset and the cursor would be gone but that doesn't work.
Any tips on how to hide the cursor?
Code:
#include <stdio.h>
#include <stdlib.h>
const int TIME = 1;
int main(int argc,char *argv[]){
int i;
while (1){
printf("loading");
for (i=0;i<3;i++){
sleep(TIME);
printf(".");
}
sleep(TIME);
printf("\r");
system("Cls");
sleep(TIME);
}
}
To extend on Bishal's answer:
To hide the cursor:
printf("\e[?25l");
To re-enable the cursor:
printf("\e[?25h");
Source
Add to your program the following function
#include <windows.h>
void hidecursor()
{
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = FALSE;
SetConsoleCursorInfo(consoleHandle, &info);
}
and call it in your main.
And read more in the MSDN
printf("\e[?25l");
This should work ! It is taken from ANSI codesheet where the characters are not just what they are seen. They act like some form of commands.
Here a solution that works both in Windows and Linux:
#include <iostream>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <Windows.h>
#endif // _WIN32
using namespace std;
void show_console_cursor(const bool show) {
#if defined(_WIN32)
static const HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(handle, &cci);
cci.bVisible = show; // show/hide cursor
SetConsoleCursorInfo(handle, &cci);
#elif defined(__linux__)
cout << (show ? "\033[?25h" : "\033[?25l"); // show/hide cursor
#endif // Windows/Linux
}
I want to compile following c file:
#include <stdio.h>
#include <stdlib.h>
#include <../deps/linux/gpio.h>
int main(void) {
int r = gpio_is_valid(31);
if (r == -1) {
perror("GPIO address is invalid.\n");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
My Makefile looks as
build: gpio
LDFLAGS = -Llinux
gpio:
$(CC) -o gpio.o src/gpio.c $(LDFLAGS)
Unfortunately I get "gpio.h not found" as error.
gpio.h is a Linux kernel header. It can not be used for user space programs.