Ejemplo n.º 1
0
void op3d::Engine::initVulkan()
{
    instance.create();
    callback.setup(instance);
    surface.create(instance, window);
    physicalDevice.create(instance, surface);
    device.create(physicalDevice, surface, graphicsQueue, presentQueue);
    swapChain.create(device, surface, physicalDevice, window);
    swapChain.createImageViews(device, swapChainImageViews);
    createRenderPass();
    createDescriptorSetLayout();
    createGraphicsPipeline();
    commandBufferManager.createCommandPool(physicalDevice, surface);
    createDepthResources();
    createFramebuffers();
    createTextureImage();
    createTextureImageView();
    createTextureSampler();
    createVertexBuffer();
    createIndexBuffer();
    createUniformBuffer();
    descriptorPool.createPool();
    descriptorSet.createSet(uniformBuffer, textureImageView, textureSampler, descriptorSetLayout, descriptorPool, device);
    createCommandBuffers();
    createSemaphores();
}
 void initVulkan() {
     createInstance();
     setupDebugCallback();
     createSurface();
     pickPhysicalDevice();
     createLogicalDevice();
     createSwapChain();
     createImageViews();
     createRenderPass();
     createGraphicsPipeline();
 }
Ejemplo n.º 3
0
void op3d::Engine::recreateSwapChain()
{
    vkDeviceWaitIdle(device);

    swapChain.create(device, surface, physicalDevice, window);
    swapChain.createImageViews(device, swapChainImageViews);
    createRenderPass();
    createGraphicsPipeline();
    createDepthResources();
    createFramebuffers();
    createCommandBuffers();
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
int main(int argc, char *args[]) {
	// Initialize function pointers, much like GLEW in OpenGL
	mantleLoadFunctions();

	// Set debug callback
	grDbgRegisterMsgCallback(debugCallback, nullptr);

	// Create device and presentable image
	GR_DEVICE device;
	GR_QUEUE universalQueue;
	createDeviceAndQueue(device, universalQueue);

	GR_IMAGE presentableImage;
	GR_MEMORY_REF presentableImageMemRef;
	GR_IMAGE_SUBRESOURCE_RANGE imageColorRange;
	initPresentableImage(device, universalQueue, presentableImage, presentableImageMemRef, imageColorRange);

	// Create window to present to
	SDL_Init(SDL_INIT_VIDEO);

	SDL_Window* window = SDL_CreateWindow("Mantle Hello Triangle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);

	GR_WSI_WIN_PRESENT_INFO presentInfo = {};
	presentInfo.hWndDest = GetActiveWindow();
	presentInfo.srcImage = presentableImage;
	presentInfo.presentMode = GR_WSI_WIN_PRESENT_MODE_WINDOWED;

	// Create color target view
	GR_COLOR_TARGET_VIEW colorTargetView;
	GR_COLOR_TARGET_VIEW_CREATE_INFO colorTargetViewCreateInfo = {};
	colorTargetViewCreateInfo.image = presentableImage;
	colorTargetViewCreateInfo.arraySize = 1;
	colorTargetViewCreateInfo.baseArraySlice = 0;
	colorTargetViewCreateInfo.mipLevel = 0;
	colorTargetViewCreateInfo.format.channelFormat = GR_CH_FMT_R8G8B8A8;
	colorTargetViewCreateInfo.format.numericFormat = GR_NUM_FMT_UNORM;

	grCreateColorTargetView(device, &colorTargetViewCreateInfo, &colorTargetView);

	// Create dynamic states (viewport, depth/stencil operations, etc.)
	createTargetStates(device, msaaState, viewportState, colorBlendState, depthStencilState, rasterState);

	// Create graphics pipeline with shaders and descriptor bindings
	GR_PIPELINE pipeline;
	GR_MEMORY_REF pipelineMemRef;
	createGraphicsPipeline(device, pipeline, pipelineMemRef);

	// Set up descriptor set with vertex data memory views
	GR_DESCRIPTOR_SET descriptorSet;
	GR_MEMORY_REF descriptorMemRef, vertexDataMemRef;
	initDescriptorSet(device, universalQueue, descriptorSet, descriptorMemRef, vertexDataMemRef);

	// Create command buffers for rendering steps
	GR_CMD_BUFFER bufferPrepareRender = createPrepareBuffer(device, presentableImage, imageColorRange);
	GR_CMD_BUFFER bufferClear = createClearBuffer(device, presentableImage, imageColorRange);
	GR_CMD_BUFFER bufferDrawTriangle = createDrawTriangleBuffer(device, colorTargetView, descriptorSet, pipeline);
	GR_CMD_BUFFER bufferFinish = createFinishBuffer(device, presentableImage, imageColorRange);

	// Create fence for CPU synchronization with rendering
	GR_FENCE fence;
	GR_FENCE_CREATE_INFO fenceCreateInfo = {};
	grCreateFence(device, &fenceCreateInfo, &fence);

	// Main loop
	while (true) {
		SDL_Event windowEvent;
		if (SDL_PollEvent(&windowEvent)) {
			if (windowEvent.type == SDL_QUIT) break;
		}

		// Wait for previous frame to end
		grWaitForFences(device, 1, &fence, true, 1);

		// Submit command buffers along with memory references
		GR_MEMORY_REF memoryRefs[] = {presentableImageMemRef, pipelineMemRef, descriptorMemRef, vertexDataMemRef};
		GR_CMD_BUFFER commandBuffers[] = {bufferPrepareRender, bufferClear, bufferDrawTriangle, bufferFinish};

		grQueueSubmit(universalQueue, 4, commandBuffers, 4, memoryRefs, fence);

		// Present image to the window
		grWsiWinQueuePresent(universalQueue, &presentInfo);
	}

	return 0;
}