parent
							
								
									a0b8b66f2b
								
							
						
					
					
						commit
						04fb6d29e0
					
				| 
						 | 
				
			
			@ -120,7 +120,6 @@ namespace vks
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		* Get the index of a queue family that supports the requested queue flags
 | 
			
		||||
		*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,7 +132,7 @@ void VulkanExampleBase::prepare()
 | 
			
		|||
		attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
		attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		attachments[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
			
		||||
		attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
		// This is the frame buffer attachment to where the multisampled image
 | 
			
		||||
		// will be resolved to and which will be presented to the swapchain
 | 
			
		||||
| 
						 | 
				
			
			@ -143,15 +143,8 @@ void VulkanExampleBase::prepare()
 | 
			
		|||
		attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
		attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		if (settings.headless)
 | 
			
		||||
		{
 | 
			
		||||
			attachments[1].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			attachments[1].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		attachments[1].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
 | 
			
		||||
		// Multisampled depth attachment we render to
 | 
			
		||||
		attachments[2].format = depthFormat;
 | 
			
		||||
		attachments[2].samples = settings.sampleCount;
 | 
			
		||||
| 
						 | 
				
			
			@ -221,39 +214,30 @@ void VulkanExampleBase::prepare()
 | 
			
		|||
		renderPassCI.pDependencies = dependencies.data();
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass));
 | 
			
		||||
	}
 | 
			
		||||
	else 
 | 
			
		||||
	{
 | 
			
		||||
		std::array<VkAttachmentDescription, 2> attachmentDescriptions = {};
 | 
			
		||||
	else {
 | 
			
		||||
		std::array<VkAttachmentDescription, 2> attachments = {};
 | 
			
		||||
		// Color attachment
 | 
			
		||||
		attachmentDescriptions[0].format = swapChain.colorFormat;
 | 
			
		||||
		attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		attachmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
		attachmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
		attachmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		if (settings.headless)
 | 
			
		||||
		{
 | 
			
		||||
			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
		}
 | 
			
		||||
		attachments[0].format = swapChain.colorFormat;
 | 
			
		||||
		attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
		attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
		attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
		// Depth attachment
 | 
			
		||||
		attachmentDescriptions[1].format = depthFormat;
 | 
			
		||||
		attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		attachmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
		attachmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		attachmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
		attachments[1].format = depthFormat;
 | 
			
		||||
		attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
		attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
		attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
		attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
		VkAttachmentReference colorReference = {};
 | 
			
		||||
		colorReference.attachment = 0;
 | 
			
		||||
		colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		VkAttachmentReference depthReference = {};
 | 
			
		||||
		depthReference.attachment = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -291,16 +275,13 @@ void VulkanExampleBase::prepare()
 | 
			
		|||
 | 
			
		||||
		VkRenderPassCreateInfo renderPassCI{};
 | 
			
		||||
		renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
 | 
			
		||||
		renderPassCI.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
 | 
			
		||||
		renderPassCI.pAttachments = attachmentDescriptions.data();
 | 
			
		||||
		renderPassCI.attachmentCount = static_cast<uint32_t>(attachments.size());
 | 
			
		||||
		renderPassCI.pAttachments = attachments.data();
 | 
			
		||||
		renderPassCI.subpassCount = 1;
 | 
			
		||||
		renderPassCI.pSubpasses = &subpassDescription;
 | 
			
		||||
		renderPassCI.dependencyCount = static_cast<uint32_t>(dependencies.size());
 | 
			
		||||
		renderPassCI.pDependencies = dependencies.data();
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass));
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -318,6 +299,189 @@ void VulkanExampleBase::prepare()
 | 
			
		|||
 | 
			
		||||
void VulkanExampleBase::fileDropped(std::string filename) { }
 | 
			
		||||
 | 
			
		||||
void VulkanExampleBase::renderFrame()
 | 
			
		||||
{
 | 
			
		||||
	auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
	render();
 | 
			
		||||
	frameCounter++;
 | 
			
		||||
	auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
	auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
	frameTimer = (float)tDiff / 1000.0f;
 | 
			
		||||
	camera.update(frameTimer);
 | 
			
		||||
	fpsTimer += (float)tDiff;
 | 
			
		||||
	if (fpsTimer > 1000.0f) {
 | 
			
		||||
		lastFPS = static_cast<uint32_t>((float)frameCounter * (1000.0f / fpsTimer));
 | 
			
		||||
		fpsTimer = 0.0f;
 | 
			
		||||
		frameCounter = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VulkanExampleBase::renderLoop()
 | 
			
		||||
{
 | 
			
		||||
	destWidth = width;
 | 
			
		||||
	destHeight = height;
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
	MSG msg;
 | 
			
		||||
	bool quitMessageReceived = false;
 | 
			
		||||
	while (!quitMessageReceived) {
 | 
			
		||||
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
 | 
			
		||||
			TranslateMessage(&msg);
 | 
			
		||||
			DispatchMessage(&msg);
 | 
			
		||||
			if (msg.message == WM_QUIT) {
 | 
			
		||||
				quitMessageReceived = true;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (!IsIconic(window)) {
 | 
			
		||||
			renderFrame();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
 | 
			
		||||
	while (1)
 | 
			
		||||
	{
 | 
			
		||||
		int ident;
 | 
			
		||||
		int events;
 | 
			
		||||
		struct android_poll_source* source;
 | 
			
		||||
		bool destroy = false;
 | 
			
		||||
 | 
			
		||||
		focused = true;
 | 
			
		||||
 | 
			
		||||
		while ((ident = ALooper_pollAll(focused ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (source != NULL)
 | 
			
		||||
			{
 | 
			
		||||
				source->process(androidApp, source);
 | 
			
		||||
			}
 | 
			
		||||
			if (androidApp->destroyRequested != 0)
 | 
			
		||||
			{
 | 
			
		||||
				LOGD("Android app destroy requested");
 | 
			
		||||
				destroy = true;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// App destruction requested
 | 
			
		||||
		// Exit loop, example will be destroyed in application main
 | 
			
		||||
		if (destroy)
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Render frame
 | 
			
		||||
		if (prepared)
 | 
			
		||||
		{
 | 
			
		||||
			auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			render();
 | 
			
		||||
			frameCounter++;
 | 
			
		||||
			auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
			frameTimer = tDiff / 1000.0f;
 | 
			
		||||
			camera.update(frameTimer);
 | 
			
		||||
			fpsTimer += (float)tDiff;
 | 
			
		||||
			if (fpsTimer > 1000.0f)
 | 
			
		||||
			{
 | 
			
		||||
				lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
				fpsTimer = 0.0f;
 | 
			
		||||
				frameCounter = 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Check gamepad state
 | 
			
		||||
			const float deadZone = 0.0015f;
 | 
			
		||||
			// todo : check if gamepad is present
 | 
			
		||||
			// todo : time based and relative axis positions
 | 
			
		||||
			if (camera.type != Camera::CameraType::firstperson)
 | 
			
		||||
			{
 | 
			
		||||
				// Rotate
 | 
			
		||||
				if (std::abs(gamePadState.axisLeft.x) > deadZone) {
 | 
			
		||||
					camera.rotate(glm::vec3(0.0f, gamePadState.axisLeft.x * 0.5f, 0.0f));
 | 
			
		||||
				}
 | 
			
		||||
				if (std::abs(gamePadState.axisLeft.y) > deadZone) {
 | 
			
		||||
					camera.rotate(glm::vec3(gamePadState.axisLeft.y * 0.5f, 0.0f, 0.0f));
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				camera.updatePad(gamePadState.axisLeft, gamePadState.axisRight, frameTimer);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(_DIRECT2DISPLAY)
 | 
			
		||||
	while (!quit)
 | 
			
		||||
	{
 | 
			
		||||
		auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		render();
 | 
			
		||||
		frameCounter++;
 | 
			
		||||
		auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
		frameTimer = tDiff / 1000.0f;
 | 
			
		||||
		camera.update(frameTimer);
 | 
			
		||||
		fpsTimer += (float)tDiff;
 | 
			
		||||
		if (fpsTimer > 1000.0f)
 | 
			
		||||
		{
 | 
			
		||||
			lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
			fpsTimer = 0.0f;
 | 
			
		||||
			frameCounter = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
 | 
			
		||||
	while (!quit)
 | 
			
		||||
	{
 | 
			
		||||
		auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		while (wl_display_prepare_read(display) != 0)
 | 
			
		||||
			wl_display_dispatch_pending(display);
 | 
			
		||||
		wl_display_flush(display);
 | 
			
		||||
		wl_display_read_events(display);
 | 
			
		||||
		wl_display_dispatch_pending(display);
 | 
			
		||||
 | 
			
		||||
		render();
 | 
			
		||||
		frameCounter++;
 | 
			
		||||
		auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
		frameTimer = tDiff / 1000.0f;
 | 
			
		||||
		camera.update(frameTimer);
 | 
			
		||||
		fpsTimer += (float)tDiff;
 | 
			
		||||
		if (fpsTimer > 1000.0f)
 | 
			
		||||
		{
 | 
			
		||||
			wl_shell_surface_set_title(shell_surface, title.c_str());
 | 
			
		||||
			lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
			fpsTimer = 0.0f;
 | 
			
		||||
			frameCounter = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
 | 
			
		||||
	xcb_flush(connection);
 | 
			
		||||
	while (!quit)
 | 
			
		||||
	{
 | 
			
		||||
		auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		xcb_generic_event_t *event;
 | 
			
		||||
		while ((event = xcb_poll_for_event(connection)))
 | 
			
		||||
		{
 | 
			
		||||
			handleEvent(event);
 | 
			
		||||
			free(event);
 | 
			
		||||
		}
 | 
			
		||||
		render();
 | 
			
		||||
		frameCounter++;
 | 
			
		||||
		auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
		frameTimer = tDiff / 1000.0f;
 | 
			
		||||
		camera.update(frameTimer);
 | 
			
		||||
		fpsTimer += (float)tDiff;
 | 
			
		||||
		if (fpsTimer > 1000.0f)
 | 
			
		||||
		{
 | 
			
		||||
			xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
 | 
			
		||||
				window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
 | 
			
		||||
				title.size(), title.c_str());
 | 
			
		||||
			lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
			fpsTimer = 0.0f;
 | 
			
		||||
			frameCounter = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
 | 
			
		||||
	[NSApp run];
 | 
			
		||||
#endif
 | 
			
		||||
	// Flush device to make sure all resources can be freed 
 | 
			
		||||
	vkDeviceWaitIdle(device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VulkanExampleBase::VulkanExampleBase()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -375,9 +539,9 @@ VulkanExampleBase::~VulkanExampleBase()
 | 
			
		|||
	for (uint32_t i = 0; i < frameBuffers.size(); i++) {
 | 
			
		||||
		vkDestroyFramebuffer(device, frameBuffers[i], nullptr);
 | 
			
		||||
	}
 | 
			
		||||
	vkDestroyImageView(device, depthAttachment.view, nullptr);
 | 
			
		||||
	vkDestroyImage(device, depthAttachment.image, nullptr);
 | 
			
		||||
	vkFreeMemory(device, depthAttachment.memory, nullptr);
 | 
			
		||||
	vkDestroyImageView(device, depthStencil.view, nullptr);
 | 
			
		||||
	vkDestroyImage(device, depthStencil.image, nullptr);
 | 
			
		||||
	vkFreeMemory(device, depthStencil.mem, nullptr);
 | 
			
		||||
	vkDestroyPipelineCache(device, pipelineCache, nullptr);
 | 
			
		||||
	vkDestroyCommandPool(device, cmdPool, nullptr);
 | 
			
		||||
	if (settings.multiSampling) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1658,9 +1822,8 @@ void VulkanExampleBase::setupFrameBuffer()
 | 
			
		|||
		imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
			
		||||
		imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
		imageCI.samples = settings.sampleCount;
 | 
			
		||||
		imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
 | 
			
		||||
		imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
 | 
			
		||||
		imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multisampleTarget.color.image));
 | 
			
		||||
 | 
			
		||||
		VkMemoryRequirements memReqs;
 | 
			
		||||
| 
						 | 
				
			
			@ -1728,140 +1891,65 @@ void VulkanExampleBase::setupFrameBuffer()
 | 
			
		|||
		imageViewCI.subresourceRange.levelCount = 1;
 | 
			
		||||
		imageViewCI.subresourceRange.layerCount = 1;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &multisampleTarget.depth.view));
 | 
			
		||||
 | 
			
		||||
		VkImageCreateInfo image = {};
 | 
			
		||||
		image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 | 
			
		||||
		image.pNext = NULL;
 | 
			
		||||
		image.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
		image.format = depthFormat;
 | 
			
		||||
		image.extent = { width, height, 1 };
 | 
			
		||||
		image.mipLevels = 1;
 | 
			
		||||
		image.arrayLayers = 1;
 | 
			
		||||
		image.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		image.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
		image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
 | 
			
		||||
		image.flags = 0;
 | 
			
		||||
 | 
			
		||||
		VkMemoryAllocateInfo mem_alloc = {};
 | 
			
		||||
		mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
		mem_alloc.pNext = NULL;
 | 
			
		||||
		mem_alloc.allocationSize = 0;
 | 
			
		||||
		mem_alloc.memoryTypeIndex = 0;
 | 
			
		||||
 | 
			
		||||
		VkImageViewCreateInfo depthStencilView = {};
 | 
			
		||||
		depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 | 
			
		||||
		depthStencilView.pNext = NULL;
 | 
			
		||||
		depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
		depthStencilView.format = depthFormat;
 | 
			
		||||
		depthStencilView.flags = 0;
 | 
			
		||||
		depthStencilView.subresourceRange = {};
 | 
			
		||||
		depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
 | 
			
		||||
		depthStencilView.subresourceRange.baseMipLevel = 0;
 | 
			
		||||
		depthStencilView.subresourceRange.levelCount = 1;
 | 
			
		||||
		depthStencilView.subresourceRange.baseArrayLayer = 0;
 | 
			
		||||
		depthStencilView.subresourceRange.layerCount = 1;
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthAttachment.image));
 | 
			
		||||
		vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs);
 | 
			
		||||
		mem_alloc.allocationSize = memReqs.size;
 | 
			
		||||
		mem_alloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
			
		||||
		VK_CHECK_RESULT(vkAllocateMemory(device, &mem_alloc, nullptr, &depthAttachment.memory));
 | 
			
		||||
		VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.memory, 0));
 | 
			
		||||
 | 
			
		||||
		depthStencilView.image = depthAttachment.image;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view));
 | 
			
		||||
	}
 | 
			
		||||
	else // color attachment when MSAA is no enabled
 | 
			
		||||
	{
 | 
			
		||||
		VkFormat colorFormat = VK_FORMAT_B8G8R8A8_SRGB;
 | 
			
		||||
		VkFormat depthFormat;
 | 
			
		||||
		vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat);
 | 
			
		||||
		
 | 
			
		||||
		// Color attachment
 | 
			
		||||
		VkImageCreateInfo image = vks::initializers::imageCreateInfo();
 | 
			
		||||
		image.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
		image.format = colorFormat;
 | 
			
		||||
		image.extent.width = width;
 | 
			
		||||
		image.extent.height = height;
 | 
			
		||||
		image.extent.depth = 1;
 | 
			
		||||
		image.mipLevels = 1;
 | 
			
		||||
		image.arrayLayers = 1;
 | 
			
		||||
		image.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		image.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
		image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
 | 
			
		||||
 | 
			
		||||
		VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
 | 
			
		||||
		VkMemoryRequirements memReqs;
 | 
			
		||||
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &colorAttachment.image));
 | 
			
		||||
		vkGetImageMemoryRequirements(device, colorAttachment.image, &memReqs);
 | 
			
		||||
		memAlloc.allocationSize = memReqs.size;
 | 
			
		||||
		memAlloc.memoryTypeIndex = vulkanDevice -> getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
			
		||||
		VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &colorAttachment.memory));
 | 
			
		||||
		VK_CHECK_RESULT(vkBindImageMemory(device, colorAttachment.image, colorAttachment.memory, 0));
 | 
			
		||||
 | 
			
		||||
		VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
 | 
			
		||||
		colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
		colorImageView.format = colorFormat;
 | 
			
		||||
		colorImageView.subresourceRange = {};
 | 
			
		||||
		colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
		colorImageView.subresourceRange.baseMipLevel = 0;
 | 
			
		||||
		colorImageView.subresourceRange.levelCount = 1;
 | 
			
		||||
		colorImageView.subresourceRange.baseArrayLayer = 0;
 | 
			
		||||
		colorImageView.subresourceRange.layerCount = 1;
 | 
			
		||||
		colorImageView.image = colorAttachment.image;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &colorAttachment.view));
 | 
			
		||||
 | 
			
		||||
		// Depth stencil attachment
 | 
			
		||||
		image.format = depthFormat;
 | 
			
		||||
		image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 | 
			
		||||
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthAttachment.image));
 | 
			
		||||
		vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs);
 | 
			
		||||
		memAlloc.allocationSize = memReqs.size;
 | 
			
		||||
		memAlloc.memoryTypeIndex = vulkanDevice -> getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
			
		||||
		VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.memory));
 | 
			
		||||
		VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.memory, 0));
 | 
			
		||||
 | 
			
		||||
		VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo();
 | 
			
		||||
		depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
		depthStencilView.format = depthFormat;
 | 
			
		||||
		depthStencilView.flags = 0;
 | 
			
		||||
		depthStencilView.subresourceRange = {};
 | 
			
		||||
		depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
 | 
			
		||||
		if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT)
 | 
			
		||||
			depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
 | 
			
		||||
		depthStencilView.subresourceRange.baseMipLevel = 0;
 | 
			
		||||
		depthStencilView.subresourceRange.levelCount = 1;
 | 
			
		||||
		depthStencilView.subresourceRange.baseArrayLayer = 0;
 | 
			
		||||
		depthStencilView.subresourceRange.layerCount = 1;
 | 
			
		||||
		depthStencilView.image = depthAttachment.image;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view));	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	if (settings.multiSampling)
 | 
			
		||||
	{
 | 
			
		||||
		i = 4;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		i = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VkImageView attachments[i];
 | 
			
		||||
	// Depth/Stencil attachment is the same for all frame buffers
 | 
			
		||||
 | 
			
		||||
	VkImageCreateInfo image = {};
 | 
			
		||||
	image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 | 
			
		||||
	image.pNext = NULL;
 | 
			
		||||
	image.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
	image.format = depthFormat;
 | 
			
		||||
	image.extent = { width, height, 1 };
 | 
			
		||||
	image.mipLevels = 1;
 | 
			
		||||
	image.arrayLayers = 1;
 | 
			
		||||
	image.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
	image.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
	image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
 | 
			
		||||
	image.flags = 0;
 | 
			
		||||
 | 
			
		||||
	VkMemoryAllocateInfo mem_alloc = {};
 | 
			
		||||
	mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
	mem_alloc.pNext = NULL;
 | 
			
		||||
	mem_alloc.allocationSize = 0;
 | 
			
		||||
	mem_alloc.memoryTypeIndex = 0;
 | 
			
		||||
 | 
			
		||||
	VkImageViewCreateInfo depthStencilView = {};
 | 
			
		||||
	depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 | 
			
		||||
	depthStencilView.pNext = NULL;
 | 
			
		||||
	depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
	depthStencilView.format = depthFormat;
 | 
			
		||||
	depthStencilView.flags = 0;
 | 
			
		||||
	depthStencilView.subresourceRange = {};
 | 
			
		||||
	depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
 | 
			
		||||
	depthStencilView.subresourceRange.baseMipLevel = 0;
 | 
			
		||||
	depthStencilView.subresourceRange.levelCount = 1;
 | 
			
		||||
	depthStencilView.subresourceRange.baseArrayLayer = 0;
 | 
			
		||||
	depthStencilView.subresourceRange.layerCount = 1;
 | 
			
		||||
 | 
			
		||||
	VkMemoryRequirements memReqs;
 | 
			
		||||
	VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthStencil.image));
 | 
			
		||||
	vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs);
 | 
			
		||||
	mem_alloc.allocationSize = memReqs.size;
 | 
			
		||||
	mem_alloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
			
		||||
	VK_CHECK_RESULT(vkAllocateMemory(device, &mem_alloc, nullptr, &depthStencil.mem));
 | 
			
		||||
	VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0));
 | 
			
		||||
 | 
			
		||||
	depthStencilView.image = depthStencil.image;
 | 
			
		||||
	VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view));
 | 
			
		||||
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	VkImageView attachments[4];
 | 
			
		||||
 | 
			
		||||
	if (settings.multiSampling) {
 | 
			
		||||
		
 | 
			
		||||
		attachments[0] = multisampleTarget.color.view;
 | 
			
		||||
		attachments[2] = multisampleTarget.depth.view;
 | 
			
		||||
		attachments[3] = depthAttachment.view;
 | 
			
		||||
		attachments[3] = depthStencil.view;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		
 | 
			
		||||
		attachments[1] = depthAttachment.view;
 | 
			
		||||
		attachments[0] = colorAttachment.view;
 | 
			
		||||
		attachments[1] = depthStencil.view;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VkFramebufferCreateInfo frameBufferCI{};
 | 
			
		||||
| 
						 | 
				
			
			@ -1874,35 +1962,16 @@ void VulkanExampleBase::setupFrameBuffer()
 | 
			
		|||
	frameBufferCI.height = height;
 | 
			
		||||
	frameBufferCI.layers = 1;
 | 
			
		||||
 | 
			
		||||
	if (settings.headless && ! settings.multiSampling)
 | 
			
		||||
	{
 | 
			
		||||
		VkImageView attachments[2];
 | 
			
		||||
		attachments[0] = colorAttachment.view;
 | 
			
		||||
		attachments[1] = depthAttachment.view;
 | 
			
		||||
 | 
			
		||||
		VkFramebufferCreateInfo framebufferCreateInfo = vks::initializers::framebufferCreateInfo();
 | 
			
		||||
		framebufferCreateInfo.renderPass = renderPass;
 | 
			
		||||
		framebufferCreateInfo.attachmentCount = 2;
 | 
			
		||||
		framebufferCreateInfo.pAttachments = attachments;
 | 
			
		||||
		framebufferCreateInfo.width = width;
 | 
			
		||||
		framebufferCreateInfo.height = height;
 | 
			
		||||
		framebufferCreateInfo.layers = 1;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCreateInfo, nullptr, &framebuffer));
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		// Create frame buffers for every swap chain image
 | 
			
		||||
		frameBuffers.resize(swapChain.imageCount);
 | 
			
		||||
		for (uint32_t i = 0; i < frameBuffers.size(); i++) {
 | 
			
		||||
			if (settings.multiSampling) {
 | 
			
		||||
				attachments[1] = swapChain.buffers[i].view;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				attachments[0] = swapChain.buffers[i].view;
 | 
			
		||||
			}
 | 
			
		||||
			VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i]));
 | 
			
		||||
	// Create frame buffers for every swap chain image
 | 
			
		||||
	frameBuffers.resize(swapChain.imageCount);
 | 
			
		||||
	for (uint32_t i = 0; i < frameBuffers.size(); i++) {
 | 
			
		||||
		if (settings.multiSampling) {
 | 
			
		||||
			attachments[1] = swapChain.buffers[i].view;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		else {
 | 
			
		||||
			attachments[0] = swapChain.buffers[i].view;
 | 
			
		||||
		}
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i]));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1925,9 +1994,9 @@ void VulkanExampleBase::windowResize()
 | 
			
		|||
		vkDestroyImage(device, multisampleTarget.depth.image, nullptr);
 | 
			
		||||
		vkFreeMemory(device, multisampleTarget.depth.memory, nullptr);
 | 
			
		||||
	}
 | 
			
		||||
	vkDestroyImageView(device, depthAttachment.view, nullptr);
 | 
			
		||||
	vkDestroyImage(device, depthAttachment.image, nullptr);
 | 
			
		||||
	vkFreeMemory(device, depthAttachment.memory, nullptr);
 | 
			
		||||
	vkDestroyImageView(device, depthStencil.view, nullptr);
 | 
			
		||||
	vkDestroyImage(device, depthStencil.image, nullptr);
 | 
			
		||||
	vkFreeMemory(device, depthStencil.mem, nullptr);
 | 
			
		||||
	for (uint32_t i = 0; i < frameBuffers.size(); i++) {
 | 
			
		||||
		vkDestroyFramebuffer(device, frameBuffers[i], nullptr);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,16 @@
 | 
			
		|||
 | 
			
		||||
class VulkanExampleBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
private:	
 | 
			
		||||
	float fpsTimer = 0.0f;
 | 
			
		||||
	uint32_t frameCounter = 0;
 | 
			
		||||
	uint32_t destWidth;
 | 
			
		||||
	uint32_t destHeight;
 | 
			
		||||
	bool resizing = false;
 | 
			
		||||
	void handleMouseMove(int32_t x, int32_t y);
 | 
			
		||||
	PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallback;
 | 
			
		||||
	PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallback;
 | 
			
		||||
	VkDebugReportCallbackEXT debugReportCallback;
 | 
			
		||||
	struct MultisampleTarget {
 | 
			
		||||
		struct {
 | 
			
		||||
			VkImage image;
 | 
			
		||||
| 
						 | 
				
			
			@ -71,17 +80,6 @@ public:
 | 
			
		|||
			VkDeviceMemory memory;
 | 
			
		||||
		} depth;
 | 
			
		||||
	} multisampleTarget;
 | 
			
		||||
 | 
			
		||||
private:	
 | 
			
		||||
	
 | 
			
		||||
	uint32_t destWidth;
 | 
			
		||||
	uint32_t destHeight;
 | 
			
		||||
	bool resizing = false;
 | 
			
		||||
	void handleMouseMove(int32_t x, int32_t y);
 | 
			
		||||
	PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallback;
 | 
			
		||||
	PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallback;
 | 
			
		||||
	VkDebugReportCallbackEXT debugReportCallback;
 | 
			
		||||
	
 | 
			
		||||
protected:
 | 
			
		||||
	VkInstance instance;
 | 
			
		||||
	VkPhysicalDevice physicalDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +90,6 @@ protected:
 | 
			
		|||
	vks::VulkanDevice *vulkanDevice;
 | 
			
		||||
	VkQueue queue;
 | 
			
		||||
	VkFormat depthFormat;
 | 
			
		||||
	VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
	VkCommandPool cmdPool;
 | 
			
		||||
	VkRenderPass renderPass;
 | 
			
		||||
	std::vector<VkFramebuffer>frameBuffers;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,31 +106,25 @@ public:
 | 
			
		|||
	bool prepared = false;
 | 
			
		||||
	uint32_t width = 1280;
 | 
			
		||||
	uint32_t height = 720;
 | 
			
		||||
	float frameTimer = 1.0f;
 | 
			
		||||
	Camera camera;
 | 
			
		||||
	glm::vec2 mousePos;
 | 
			
		||||
	bool paused = false;
 | 
			
		||||
	uint32_t lastFPS = 0;
 | 
			
		||||
 | 
			
		||||
	struct Settings {
 | 
			
		||||
		bool validation = true;
 | 
			
		||||
		bool fullscreen = false;
 | 
			
		||||
		bool vsync = false;
 | 
			
		||||
		bool multiSampling = true;
 | 
			
		||||
		bool rotateModel = false;
 | 
			
		||||
		bool enableSaveToImageSequeue = false;
 | 
			
		||||
		uint32_t outputFrameCount = 50;
 | 
			
		||||
		bool takeScreenShot = false;
 | 
			
		||||
		bool headless = true;
 | 
			
		||||
		VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
 | 
			
		||||
	} settings;
 | 
			
		||||
 | 
			
		||||
	struct FrameBufferAttachment {
 | 
			
		||||
	
 | 
			
		||||
	struct DepthStencil {
 | 
			
		||||
		VkImage image;
 | 
			
		||||
		VkDeviceMemory memory;
 | 
			
		||||
		VkDeviceMemory mem;
 | 
			
		||||
		VkImageView view;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	FrameBufferAttachment colorAttachment, depthAttachment;
 | 
			
		||||
	VkFramebuffer framebuffer;
 | 
			
		||||
	} depthStencil;
 | 
			
		||||
 | 
			
		||||
	struct GamePadState {
 | 
			
		||||
		glm::vec2 axisLeft = glm::vec2(0.0f);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,9 +189,6 @@ PlumageRender::PlumageRender()
 | 
			
		|||
			VK_CHECK_RESULT(vkEndCommandBuffer(currentCB));
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -532,7 +529,6 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT;
 | 
			
		||||
		rasterizationStateCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
 | 
			
		||||
		rasterizationStateCI.lineWidth = 1.0f;
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		VkPipelineColorBlendAttachmentState blendAttachmentState{};
 | 
			
		||||
		blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
 | 
			
		||||
| 
						 | 
				
			
			@ -562,10 +558,6 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		if (settings.multiSampling) {
 | 
			
		||||
			multisampleStateCI.rasterizationSamples = settings.sampleCount;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::vector<VkDynamicState> dynamicStateEnables = {
 | 
			
		||||
			VK_DYNAMIC_STATE_VIEWPORT,
 | 
			
		||||
| 
						 | 
				
			
			@ -627,7 +619,9 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
 | 
			
		||||
		pipelineCI.pStages = shaderStages.data();
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		if (settings.multiSampling) {
 | 
			
		||||
			multisampleStateCI.rasterizationSamples = settings.sampleCount;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Skybox pipeline (background cube)
 | 
			
		||||
		shaderStages = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1584,23 +1578,29 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		prepared = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence)
 | 
			
		||||
	void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue)
 | 
			
		||||
	{
 | 
			
		||||
		VkSubmitInfo submitInfo = vks::initializers::submitInfo();
 | 
			
		||||
		submitInfo.commandBufferCount = 1;
 | 
			
		||||
		submitInfo.pCommandBuffers = &cmdBuffer;
 | 
			
		||||
		VK_CHECK_RESULT(vkResetFences(device, 1, &fence));
 | 
			
		||||
		VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo();
 | 
			
		||||
		VkFence fence;
 | 
			
		||||
		VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence));
 | 
			
		||||
		VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence));
 | 
			
		||||
		VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX));
 | 
			
		||||
		//vkDestroyFence(device, fence, nullptr);
 | 
			
		||||
		vkDestroyFence(device, fence, nullptr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// todo :根据physicalDeviceIndex确定子文件夹路径,frameIndex确定fileName
 | 
			
		||||
	void PlumageRender::writeImageToFile(std::string filePath)
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		bool surpportBlit = true;
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		char* imageData;
 | 
			
		||||
		// create dst image to copy
 | 
			
		||||
		
 | 
			
		||||
		VkImageCreateInfo imageCreateInfo(vks::initializers::imageCreateInfo());
 | 
			
		||||
		imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
		imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
| 
						 | 
				
			
			@ -1610,14 +1610,7 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		imageCreateInfo.arrayLayers = 1;
 | 
			
		||||
		imageCreateInfo.mipLevels = 1;
 | 
			
		||||
		imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
		if (settings.multiSampling)
 | 
			
		||||
		{
 | 
			
		||||
			imageCreateInfo.samples = settings.sampleCount;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		}
 | 
			
		||||
		imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
		imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
 | 
			
		||||
		imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1630,28 +1623,20 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		VkDeviceMemory dstImageMemory;
 | 
			
		||||
		vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
 | 
			
		||||
		memAllocInfo.allocationSize = memRequirements.size;
 | 
			
		||||
		memAllocInfo.memoryTypeIndex = vulkanDevice -> getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 | 
			
		||||
		memAllocInfo.memoryTypeIndex = getMemoryTypeIndex(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 | 
			
		||||
		
 | 
			
		||||
		// allocate and bind memory
 | 
			
		||||
		VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory));
 | 
			
		||||
		VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0));
 | 
			
		||||
 | 
			
		||||
		// blit image and copy to host visualable memory
 | 
			
		||||
		VkCommandBufferAllocateInfo cmdBufferAllocInfo = vks::initializers::commandBufferAllocateInfo(cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY,1);
 | 
			
		||||
		VkCommandBufferAllocateInfo cmdBufferAllocInfo;
 | 
			
		||||
		VkCommandBuffer copyCmd;
 | 
			
		||||
		VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufferAllocInfo, ©Cmd));
 | 
			
		||||
		VkCommandBufferBeginInfo cmdBufferBeginInfo = vks::initializers::commandBufferBeginInfo();
 | 
			
		||||
		VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufferBeginInfo));
 | 
			
		||||
		
 | 
			
		||||
		vks::tools::insertImageMemoryBarrier(copyCmd, 
 | 
			
		||||
											dstImage, 
 | 
			
		||||
												   0,
 | 
			
		||||
						VK_ACCESS_TRANSFER_WRITE_BIT,
 | 
			
		||||
						VK_IMAGE_LAYOUT_UNDEFINED,
 | 
			
		||||
						VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
 | 
			
		||||
						VK_PIPELINE_STAGE_TRANSFER_BIT, 
 | 
			
		||||
						VK_PIPELINE_STAGE_TRANSFER_BIT,
 | 
			
		||||
						VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1 });
 | 
			
		||||
 | 
			
		||||
		vks::tools::insertImageMemoryBarrier(copyCmd, dstImage, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1 });
 | 
			
		||||
 | 
			
		||||
		VkImageCopy imageCopyRegion{};
 | 
			
		||||
		imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
| 
						 | 
				
			
			@ -1662,50 +1647,14 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		imageCopyRegion.extent.height = height;
 | 
			
		||||
		imageCopyRegion.extent.depth = 1;
 | 
			
		||||
 | 
			
		||||
		VkImage srcImage;
 | 
			
		||||
 | 
			
		||||
		if (settings.multiSampling)
 | 
			
		||||
		{
 | 
			
		||||
			srcImage = multisampleTarget.color.image;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			srcImage = colorAttachment.image;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vks::tools::insertImageMemoryBarrier(copyCmd,
 | 
			
		||||
			srcImage,
 | 
			
		||||
			0,
 | 
			
		||||
			VK_ACCESS_TRANSFER_WRITE_BIT,
 | 
			
		||||
			VK_IMAGE_LAYOUT_UNDEFINED,
 | 
			
		||||
			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
 | 
			
		||||
			VK_PIPELINE_STAGE_TRANSFER_BIT,
 | 
			
		||||
			VK_PIPELINE_STAGE_TRANSFER_BIT,
 | 
			
		||||
			VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1 });
 | 
			
		||||
 | 
			
		||||
		vkCmdCopyImage(copyCmd,
 | 
			
		||||
						srcImage,
 | 
			
		||||
						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 
 | 
			
		||||
						dstImage, 
 | 
			
		||||
						VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
 | 
			
		||||
						1, &imageCopyRegion);
 | 
			
		||||
		vkCmdCopyImage(copyCmd, offscreen.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopyRegion);
 | 
			
		||||
 | 
			
		||||
		// transition dst image to general layout for map memory
 | 
			
		||||
		vks::tools::insertImageMemoryBarrier(copyCmd,
 | 
			
		||||
											dstImage,
 | 
			
		||||
											VK_ACCESS_TRANSFER_WRITE_BIT,
 | 
			
		||||
											VK_ACCESS_MEMORY_READ_BIT,
 | 
			
		||||
											VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
 | 
			
		||||
											VK_IMAGE_LAYOUT_GENERAL, 
 | 
			
		||||
											VK_PIPELINE_STAGE_TRANSFER_BIT,
 | 
			
		||||
											VK_PIPELINE_STAGE_TRANSFER_BIT,
 | 
			
		||||
											VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1});
 | 
			
		||||
		vks::tools::insertImageMemoryBarrier(copyCmd, dstImage, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1});
 | 
			
		||||
 | 
			
		||||
		VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd));
 | 
			
		||||
 | 
			
		||||
		submitWork(copyCmd, queue,waitFences[frameIndex]);
 | 
			
		||||
 | 
			
		||||
		vkDeviceWaitIdle(device);
 | 
			
		||||
		submitWork(copyCmd, queue);
 | 
			
		||||
 | 
			
		||||
		// Get layout of the image
 | 
			
		||||
		VkImageSubresource subResource{};
 | 
			
		||||
| 
						 | 
				
			
			@ -1756,7 +1705,7 @@ PlumageRender::PlumageRender()
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::outputImageSequence(uint32_t currentFrame)
 | 
			
		||||
	void PlumageRender::outputImageSequence()
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		std::string deviceFilePath = filePath.outputPath + "/device" + std::to_string(selectedPhysicalDeviceIndex);
 | 
			
		||||
| 
						 | 
				
			
			@ -1764,34 +1713,33 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		{
 | 
			
		||||
			_mkdir(deviceFilePath.c_str());
 | 
			
		||||
		}
 | 
			
		||||
		std::string fileName = "/" + std::to_string(currentFrame) + "result.pmm";
 | 
			
		||||
		std::string outputPath = deviceFilePath + fileName;
 | 
			
		||||
 | 
			
		||||
		for (uint32_t i = 0; i < settings.outputFrameCount; i++)
 | 
			
		||||
		{
 | 
			
		||||
			std::string fileName = "/" + std::to_string(i) + "result.pmm";
 | 
			
		||||
			std::string outputPath = deviceFilePath + fileName;
 | 
			
		||||
			//std::cout << outputPath << std::endl;
 | 
			
		||||
		writeImageToFile(outputPath);
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::renderFrame()
 | 
			
		||||
	{
 | 
			
		||||
		auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		render();
 | 
			
		||||
		frameCounter++;
 | 
			
		||||
		//VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[frameIndex], VK_TRUE, UINT64_MAX));
 | 
			
		||||
		outputImageSequence(frameCounter);
 | 
			
		||||
		//VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[frameIndex]));
 | 
			
		||||
		auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
		auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
		frameTimer = (float)tDiff / 1000.0f;
 | 
			
		||||
		camera.update(frameTimer);
 | 
			
		||||
		fpsTimer += (float)tDiff;
 | 
			
		||||
		if (fpsTimer > 1000.0f) {
 | 
			
		||||
			lastFPS = static_cast<uint32_t>((float)frameCounter * (1000.0f / fpsTimer));
 | 
			
		||||
			fpsTimer = 0.0f;
 | 
			
		||||
			frameCounter = 0;
 | 
			
		||||
			writeImageToFile(outputPath);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	uint32_t PlumageRender::getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties)
 | 
			
		||||
	{
 | 
			
		||||
		VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
 | 
			
		||||
		vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
 | 
			
		||||
		for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
 | 
			
		||||
		{
 | 
			
		||||
			if ((typeBits & 1) == 1)
 | 
			
		||||
			{
 | 
			
		||||
				if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
 | 
			
		||||
				{
 | 
			
		||||
					return i;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			typeBits >>= 1;
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::render()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -1802,9 +1750,12 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		updateUIOverlay();
 | 
			
		||||
		//加入写到文件的函数
 | 
			
		||||
		//swapChainImage = swapChain.images[frameIndex];
 | 
			
		||||
		//outputImageSequeue(swapChainImage,filePath.imageSequenceFilePath);
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		//VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[frameIndex], VK_TRUE, UINT64_MAX));
 | 
			
		||||
		//VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[frameIndex]));
 | 
			
		||||
 | 
			
		||||
		VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[frameIndex], VK_TRUE, UINT64_MAX));
 | 
			
		||||
		VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[frameIndex]));
 | 
			
		||||
 | 
			
		||||
		VkResult acquire = swapChain.acquireNextImage(presentCompleteSemaphores[frameIndex], ¤tBuffer);
 | 
			
		||||
		if ((acquire == VK_ERROR_OUT_OF_DATE_KHR) || (acquire == VK_SUBOPTIMAL_KHR)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1813,6 +1764,7 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		else {
 | 
			
		||||
			VK_CHECK_RESULT(acquire);
 | 
			
		||||
			
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Update UBOs
 | 
			
		||||
| 
						 | 
				
			
			@ -1832,10 +1784,8 @@ PlumageRender::PlumageRender()
 | 
			
		|||
		submitInfo.signalSemaphoreCount = 1;
 | 
			
		||||
		submitInfo.pCommandBuffers = &commandBuffers[currentBuffer];
 | 
			
		||||
		submitInfo.commandBufferCount = 1;
 | 
			
		||||
		VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[frameIndex]));
 | 
			
		||||
		VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[frameIndex]));
 | 
			
		||||
		VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[frameIndex], VK_TRUE, MAXINT64));
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		//显示队列
 | 
			
		||||
		VkResult present = swapChain.queuePresent(queue, currentBuffer, renderCompleteSemaphores[frameIndex]);
 | 
			
		||||
		if (!((present == VK_SUCCESS) || (present == VK_SUBOPTIMAL_KHR))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1876,174 +1826,6 @@ PlumageRender::PlumageRender()
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::renderLoop()
 | 
			
		||||
	{
 | 
			
		||||
		destWidth = width;
 | 
			
		||||
		destHeight = height;
 | 
			
		||||
 | 
			
		||||
	#if defined(_WIN32)
 | 
			
		||||
		MSG msg;
 | 
			
		||||
		bool quitMessageReceived = false;
 | 
			
		||||
		while (!quitMessageReceived) {
 | 
			
		||||
			while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
 | 
			
		||||
				TranslateMessage(&msg);
 | 
			
		||||
				DispatchMessage(&msg);
 | 
			
		||||
				if (msg.message == WM_QUIT) {
 | 
			
		||||
					quitMessageReceived = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (!IsIconic(window)) {
 | 
			
		||||
				renderFrame();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
 | 
			
		||||
		while (1)
 | 
			
		||||
		{
 | 
			
		||||
			int ident;
 | 
			
		||||
			int events;
 | 
			
		||||
			struct android_poll_source* source;
 | 
			
		||||
			bool destroy = false;
 | 
			
		||||
 | 
			
		||||
			focused = true;
 | 
			
		||||
 | 
			
		||||
			while ((ident = ALooper_pollAll(focused ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
 | 
			
		||||
			{
 | 
			
		||||
				if (source != NULL)
 | 
			
		||||
				{
 | 
			
		||||
					source->process(androidApp, source);
 | 
			
		||||
				}
 | 
			
		||||
				if (androidApp->destroyRequested != 0)
 | 
			
		||||
				{
 | 
			
		||||
					LOGD("Android app destroy requested");
 | 
			
		||||
					destroy = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// App destruction requested
 | 
			
		||||
			// Exit loop, example will be destroyed in application main
 | 
			
		||||
			if (destroy)
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Render frame
 | 
			
		||||
			if (prepared)
 | 
			
		||||
			{
 | 
			
		||||
				auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
				render();
 | 
			
		||||
				frameCounter++;
 | 
			
		||||
				auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
				auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
				frameTimer = tDiff / 1000.0f;
 | 
			
		||||
				camera.update(frameTimer);
 | 
			
		||||
				fpsTimer += (float)tDiff;
 | 
			
		||||
				if (fpsTimer > 1000.0f)
 | 
			
		||||
				{
 | 
			
		||||
					lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
					fpsTimer = 0.0f;
 | 
			
		||||
					frameCounter = 0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Check gamepad state
 | 
			
		||||
				const float deadZone = 0.0015f;
 | 
			
		||||
				// todo : check if gamepad is present
 | 
			
		||||
				// todo : time based and relative axis positions
 | 
			
		||||
				if (camera.type != Camera::CameraType::firstperson)
 | 
			
		||||
				{
 | 
			
		||||
					// Rotate
 | 
			
		||||
					if (std::abs(gamePadState.axisLeft.x) > deadZone) {
 | 
			
		||||
						camera.rotate(glm::vec3(0.0f, gamePadState.axisLeft.x * 0.5f, 0.0f));
 | 
			
		||||
					}
 | 
			
		||||
					if (std::abs(gamePadState.axisLeft.y) > deadZone) {
 | 
			
		||||
						camera.rotate(glm::vec3(gamePadState.axisLeft.y * 0.5f, 0.0f, 0.0f));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					camera.updatePad(gamePadState.axisLeft, gamePadState.axisRight, frameTimer);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#elif defined(_DIRECT2DISPLAY)
 | 
			
		||||
		while (!quit)
 | 
			
		||||
		{
 | 
			
		||||
			auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			render();
 | 
			
		||||
			frameCounter++;
 | 
			
		||||
			auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
			frameTimer = tDiff / 1000.0f;
 | 
			
		||||
			camera.update(frameTimer);
 | 
			
		||||
			fpsTimer += (float)tDiff;
 | 
			
		||||
			if (fpsTimer > 1000.0f)
 | 
			
		||||
			{
 | 
			
		||||
				lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
				fpsTimer = 0.0f;
 | 
			
		||||
				frameCounter = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
 | 
			
		||||
		while (!quit)
 | 
			
		||||
		{
 | 
			
		||||
			auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
			while (wl_display_prepare_read(display) != 0)
 | 
			
		||||
				wl_display_dispatch_pending(display);
 | 
			
		||||
			wl_display_flush(display);
 | 
			
		||||
			wl_display_read_events(display);
 | 
			
		||||
			wl_display_dispatch_pending(display);
 | 
			
		||||
 | 
			
		||||
			render();
 | 
			
		||||
			frameCounter++;
 | 
			
		||||
			auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
			frameTimer = tDiff / 1000.0f;
 | 
			
		||||
			camera.update(frameTimer);
 | 
			
		||||
			fpsTimer += (float)tDiff;
 | 
			
		||||
			if (fpsTimer > 1000.0f)
 | 
			
		||||
			{
 | 
			
		||||
				wl_shell_surface_set_title(shell_surface, title.c_str());
 | 
			
		||||
				lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
				fpsTimer = 0.0f;
 | 
			
		||||
				frameCounter = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
 | 
			
		||||
		xcb_flush(connection);
 | 
			
		||||
		while (!quit)
 | 
			
		||||
		{
 | 
			
		||||
			auto tStart = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			xcb_generic_event_t* event;
 | 
			
		||||
			while ((event = xcb_poll_for_event(connection)))
 | 
			
		||||
			{
 | 
			
		||||
				handleEvent(event);
 | 
			
		||||
				free(event);
 | 
			
		||||
			}
 | 
			
		||||
			render();
 | 
			
		||||
			frameCounter++;
 | 
			
		||||
			auto tEnd = std::chrono::high_resolution_clock::now();
 | 
			
		||||
			auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
 | 
			
		||||
			frameTimer = tDiff / 1000.0f;
 | 
			
		||||
			camera.update(frameTimer);
 | 
			
		||||
			fpsTimer += (float)tDiff;
 | 
			
		||||
			if (fpsTimer > 1000.0f)
 | 
			
		||||
			{
 | 
			
		||||
				xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
 | 
			
		||||
					window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
 | 
			
		||||
					title.size(), title.c_str());
 | 
			
		||||
				lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
 | 
			
		||||
				fpsTimer = 0.0f;
 | 
			
		||||
				frameCounter = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
 | 
			
		||||
		[NSApp run];
 | 
			
		||||
	#endif
 | 
			
		||||
		// Flush device to make sure all resources can be freed 
 | 
			
		||||
		vkDeviceWaitIdle(device);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlumageRender::fileDropped(std::string filename)
 | 
			
		||||
		{
 | 
			
		||||
			vkDeviceWaitIdle(device);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,6 +216,19 @@ public:
 | 
			
		|||
		VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	struct Settings {
 | 
			
		||||
		bool validation = true;
 | 
			
		||||
		bool fullscreen = false;
 | 
			
		||||
		bool vsync = false;
 | 
			
		||||
		bool multiSampling = true;
 | 
			
		||||
		bool rotateModel = true;
 | 
			
		||||
		bool enableSaveToImageSequeue = false;
 | 
			
		||||
		uint32_t outputFrameCount = 50;
 | 
			
		||||
		bool takeScreenShot = false;
 | 
			
		||||
		
 | 
			
		||||
		VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
 | 
			
		||||
	} settings;
 | 
			
		||||
 | 
			
		||||
	struct DescriptorSetLayouts {
 | 
			
		||||
		VkDescriptorSetLayout scene;
 | 
			
		||||
		VkDescriptorSetLayout material;
 | 
			
		||||
| 
						 | 
				
			
			@ -247,7 +260,6 @@ public:
 | 
			
		|||
		glm::vec3 rotation = glm::vec3(75.0f, 40.0f, 0.0f);
 | 
			
		||||
	} lightSource;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	//cube map generation
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -274,14 +286,7 @@ public:
 | 
			
		|||
	} prefilterPushBlock;
 | 
			
		||||
 | 
			
		||||
	UI* gui;
 | 
			
		||||
 | 
			
		||||
	float frameTimer = 1.0f;
 | 
			
		||||
	uint32_t lastFPS = 0;
 | 
			
		||||
	float fpsTimer = 0.0f;
 | 
			
		||||
	uint32_t frameCounter = 0;
 | 
			
		||||
 | 
			
		||||
	uint32_t destWidth;
 | 
			
		||||
	uint32_t destHeight;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	PlumageRender();
 | 
			
		||||
	~PlumageRender()
 | 
			
		||||
| 
						 | 
				
			
			@ -340,14 +345,12 @@ public:
 | 
			
		|||
	void updateShaderData();
 | 
			
		||||
	void windowResized();
 | 
			
		||||
	void         prepare();
 | 
			
		||||
	void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence);
 | 
			
		||||
	void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue);
 | 
			
		||||
	void writeImageToFile(std::string filePath);
 | 
			
		||||
	void outputImageSequence(uint32_t currentFrame);
 | 
			
		||||
	void renderFrame();
 | 
			
		||||
	void outputImageSequence();
 | 
			
		||||
	void outputScreenShot();
 | 
			
		||||
	uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties);
 | 
			
		||||
	virtual void render();
 | 
			
		||||
	void renderLoop();
 | 
			
		||||
	virtual void updateUIOverlay();
 | 
			
		||||
	virtual void fileDropped(std::string filename);
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue