Example #1
0
int main()
{
	// first, create a vulkan instance
	// the needed/used instance extensions
	constexpr const char* iniExtensions[] = {
		VK_KHR_SURFACE_EXTENSION_NAME,
		VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
		VK_EXT_DEBUG_REPORT_EXTENSION_NAME
	};

	// enables all default layers
	constexpr auto layer = "VK_LAYER_LUNARG_standard_validation";

	// basic application info
	// we use vulkan api version 1.0
	vk::ApplicationInfo appInfo ("vpp-intro", 1, "vpp", 1, VK_API_VERSION_1_0);

	vk::InstanceCreateInfo instanceInfo;
	instanceInfo.pApplicationInfo = &appInfo;
	instanceInfo.enabledExtensionCount = sizeof(iniExtensions) / sizeof(iniExtensions[0]);
	instanceInfo.ppEnabledExtensionNames = iniExtensions;
	instanceInfo.enabledLayerCount = 1;
	instanceInfo.ppEnabledLayerNames = &layer;

	vpp::Instance instance(instanceInfo);

	// create a debug callback for our instance and the default layers
	// the default implementation will just output to std::cerr when a debug callback
	// is received
	vpp::DebugCallback debugCallback(instance);

	// this function will create a winapi window wrapper and also create a surface for it
	// this should usually be done by a cross platform window abstraction
	Window window(instance);

	// now create a device for the instance and surface
	// note how vpp will automatically select a suited physical device and query
	// queue families to create basic-needs queues with this constructor.
	// We also retrieve the present queue to present on our surface from this
	// constructor
	const vpp::Queue* presentQueue;
	vpp::Device device(instance, window.surface, presentQueue);

	// now we can create a vulkan swapchain
	// again, we just use the fast way that choses quite sane defaults for us but note
	// that the class offers many convininient configuration possibilities
	vpp::Swapchain swapchain(device, window.surface);

	// to render the triangle we also need to create a render pass
	vpp::RenderPass renderPass = createRenderPass(swapchain);

	// we also create the graphics pipeline that will render our triangle as well
	// as the buffer to hold our vertices
	vpp::PipelineLayout pipelineLayout(device, {});
	auto pipeline = createGraphicsPipeline(device, renderPass, pipelineLayout);

	// note how vpp takes care of buffer allocation (in an efficient way, even when used
	// for multiple resources)
	constexpr auto size = 3u * (2u + 4u) * 4u; // 3 vertices, vec2, vec4 with 4 bytes components
	constexpr auto usage = vk::BufferUsageBits::vertexBuffer | vk::BufferUsageBits::transferDst;
	vpp::Buffer vertexBuffer(device, {{}, size, usage});

	// vertex data (only positions and color)
	constexpr std::array<float, 6 * 3> vertexData = {{
		0.f, -0.75f,     1.f, 0.f, 0.f, 1.f, // top
		-0.75f, 0.75f,    0.f, 1.f, 0.f, 1.f, // left
		0.75f, 0.75f,    0.f, 0.f, 1.f, 1.f // right
	}};

	// vpp can now be used to fill the vertex buffer with data in the most efficient way
	// in this case the buffer layout does not matter since its a vertex buffer
	// note how vpp automatically unpacks the std::array
	vpp::fill140(vertexBuffer, vpp::raw(vertexData));

	// to render onto the created swapchain we can use vpp::SwapchainRenderer
	// the class implements the default framebuffer and commandbuffer handling
	// we simply implement the vpp::RendererBuilder interface that will be used
	// to build the render command buffers
	vpp::SwapchainRenderer::CreateInfo rendererInfo;
	rendererInfo.queueFamily = device.queue(vk::QueueBits::graphics)->family();
	rendererInfo.renderPass = renderPass;

	auto impl = std::make_unique<IntroRendererImpl>();
	impl->pipeline = pipeline;
	impl->vertexBuffer = vertexBuffer;

	vpp::SwapchainRenderer renderer(swapchain, rendererInfo, std::move(impl));
	renderer.record();

	// run the main loop
	// we just recevie windows events and render after all are processed
	// sry for windows again...
	using Clock = std::chrono::high_resolution_clock;
	auto frames = 0u;
	auto point = Clock::now();

	auto run = true;
	while(run) {
		MSG msg;
		while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != 0) {
			if(msg.message == WM_QUIT) {
				run = false;
				break;
			} else {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}

		if(!run) break;
		renderer.renderBlock(*presentQueue);
		++frames;

		// output the average fps count ever second
		auto duration = Clock::now() - point;
		if(duration >= std::chrono::seconds(1)) {
			auto count = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
			std::cout << static_cast<int>(frames * (1000.0 / count)) << " fps\n";
			point = Clock::now();
			frames = 0u;
		}
	}

	return EXIT_SUCCESS;
}
Example #2
0
void handleSpuSerial(char c, int isError)
{
	//char strDebugMsg[1024];
  //if it's an error flag and discard till the start of the next message

  if(isError){
    s_isSpuRxError=isError;
	debugCallback();
    return;
  }
  switch(s_nSpuRxState){
  case eSpuStraightSerialRxInit:
    if('{'==c){
      initSpuMsgStart(c);
    }
    break;
  case eSpuStraightSerialRxStartMsg:
    if('{' ==c){
      //empty message
      initSpuMsgStart(c);
    }
    else if('}' ==c){
    	s_spuRxPacket.swarm_msg_payload[++s_nSpuRxStateByteNum]=c;
    	if(!s_isSpuRxError){
	   		s_spuRxPacket.swarm_msg_payload[s_nSpuRxStateByteNum+1]='\0';
	   		(*s_pushSwarmMsgBus)(s_spuRxPacket, 1);
	 	}
	 	s_nSpuRxState=eSpuStraightSerialRxInit;
    }
    else{
      s_nSpuRxState=eSpuStraightSerialRxPayload;
      s_nSpuRxStateByteNum++;
      s_spuRxPacket.swarm_msg_payload[s_nSpuRxStateByteNum]=c;
    }
    break;
  case eSpuStraightSerialRxPayload:
  	if('{' ==c)
  		initSpuMsgStart(c);
     else if('}'==c)
     {
     	s_spuRxPacket.swarm_msg_payload[++s_nSpuRxStateByteNum]=c;
		 //if not error first dispatch old message
	 	if(!s_isSpuRxError){
	   		s_spuRxPacket.swarm_msg_payload[s_nSpuRxStateByteNum+1]='\0';
	   		(*s_pushSwarmMsgBus)(s_spuRxPacket, 1);
	 	}
	 	s_nSpuRxState=eSpuStraightSerialRxInit;
     }
     else
     {
	 	//check for max size
	 	s_nSpuRxStateByteNum++;
	 	if(s_nSpuRxStateByteNum <= MAX_SWARM_MSG_LENGTH )
	   		s_spuRxPacket.swarm_msg_payload[s_nSpuRxStateByteNum]=c;
//	   	else
//	   		debug("maximum size exceeded for message");
	 	//else ignore till the end
     }
     break;
   default:
     break;
  }
}
Example #3
0
int main()
{
	constexpr auto width = 1200u;
	constexpr auto height = 800u;

	// init ny app
	auto& backend = ny::Backend::choose();
	if(!backend.vulkan()) {
		dlg_error("ny backend has no vulkan support!");
		return 0;
	}

	auto ac = backend.createAppContext();

	// basic vpp init
	auto iniExtensions = ac->vulkanExtensions();
	iniExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
	vk::ApplicationInfo appInfo ("vpp-intro", 1, "vpp", 1, VK_API_VERSION_1_0);
	vk::InstanceCreateInfo instanceInfo;
	instanceInfo.pApplicationInfo = &appInfo;
	instanceInfo.enabledExtensionCount = iniExtensions.size();
	instanceInfo.ppEnabledExtensionNames = iniExtensions.data();

#ifdef WithLayers
	constexpr auto layer = "VK_LAYER_LUNARG_standard_validation";
	instanceInfo.enabledLayerCount = 1;
	instanceInfo.ppEnabledLayerNames = &layer;
#endif

	vpp::Instance instance(instanceInfo);

#ifdef WithLayers
	vpp::DebugCallback debugCallback(instance);
#endif

	// ny init
	auto run = true;

	auto listener = MyWindowListener {};
	listener.run = &run;

	auto vkSurface = vk::SurfaceKHR {};
	auto ws = ny::WindowSettings {};
	ws.surface = ny::SurfaceType::vulkan;
	ws.listener = &listener;
	ws.size = {width, height};
	ws.vulkan.instance = (VkInstance) instance.vkHandle();
	ws.vulkan.storeSurface = &(std::uintptr_t&) (vkSurface);
	auto wc = ac->createWindowContext(ws);

	// further vpp init
	const vpp::Queue* presentQueue;
	vpp::Device device(instance, vkSurface, presentQueue);
	vpp::Swapchain swapchain(device, vkSurface, {width, height}, {});

	// vvg setup
	auto nvgContext = vvg::createContext(swapchain);
	auto font = nvgCreateFont(nvgContext, "sans", "Roboto-Regular.ttf");

	using Clock = std::chrono::high_resolution_clock;
	auto lastFrameTimer = Clock::now();
	unsigned int framesCount = 0;
	std::string fpsString = "420 fps";

	// main loop
	while(run) {
		if(!ac->dispatchEvents())
			break;

		nvgBeginFrame(nvgContext, width, height, width / (float) height);

		nvgBeginPath(nvgContext);
		nvgMoveTo(nvgContext, 10, 10);
		nvgLineTo(nvgContext, 10, 400);
		nvgLineTo(nvgContext, 100, 400);
		nvgQuadTo(nvgContext, 100, 50, 400, 120);
		nvgLineTo(nvgContext, 450, 10);
		nvgClosePath(nvgContext);

		nvgFillColor(nvgContext, nvgRGBAf(0.5, 0.8, 0.7, 1.0));
		nvgFill(nvgContext);

		nvgBeginPath(nvgContext);
		nvgFontFaceId(nvgContext, font);
		nvgFontSize(nvgContext, 100.f);
		nvgFontBlur(nvgContext, .8f);
		nvgFillColor(nvgContext, nvgRGBAf(1.0, 1.0, 1.0, 1.0));
		nvgTextBox(nvgContext, 200, 200, width - 200, "Hello Vulkan Vector Graphics World", nullptr);

		nvgFontSize(nvgContext, 30.f);
		nvgFontBlur(nvgContext, .2f);
		nvgText(nvgContext, 10, height - 20, fpsString.c_str(), nullptr);

		nvgBeginPath(nvgContext);
		nvgRect(nvgContext, 700, 400, 300, 300);
		nvgPathWinding(nvgContext, NVG_HOLE);
		nvgRect(nvgContext, 750, 450, 50, 50);
		// auto paint = nvgRadialGradient(nvgContext, 750, 425,20, 50, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0));
		// auto paint = nvgRadialGradient(nvgContext, 0.0, 0.0, 0.2, 100.0, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0));
		auto paint = nvgLinearGradient(nvgContext, 700, 400, 800, 450, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0));
		nvgFillPaint(nvgContext, paint);
		// nvgFillColor(nvgContext, nvgRGBA(200, 200, 0, 200));
		nvgClosePath(nvgContext);
		nvgFill(nvgContext);

		nvgEndFrame(nvgContext);

		// only refresh frame timer every second
		framesCount++;
		if(Clock::now() - lastFrameTimer >= std::chrono::seconds(1)) {
			fpsString = std::to_string(framesCount) + " fps";
			lastFrameTimer = Clock::now();
			framesCount = 0;
		}
	}

	vvg::destroyContext(*nvgContext);
}