revert
							parent
							
								
									20a30d9192
								
							
						
					
					
						commit
						a0b8b66f2b
					
				|  | @ -120,6 +120,7 @@ namespace vks | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 		/**
 | 		/**
 | ||||||
| 		* Get the index of a queue family that supports the requested queue flags | 		* 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].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | ||||||
| 		attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | 		attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | ||||||
| 		attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||||||
| 		attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | 		attachments[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; | ||||||
| 
 | 
 | ||||||
| 		// This is the frame buffer attachment to where the multisampled image
 | 		// This is the frame buffer attachment to where the multisampled image
 | ||||||
| 		// will be resolved to and which will be presented to the swapchain
 | 		// will be resolved to and which will be presented to the swapchain
 | ||||||
|  | @ -143,7 +143,14 @@ void VulkanExampleBase::prepare() | ||||||
| 		attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | 		attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | ||||||
| 		attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | 		attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | ||||||
| 		attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		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
 | 		// Multisampled depth attachment we render to
 | ||||||
| 		attachments[2].format = depthFormat; | 		attachments[2].format = depthFormat; | ||||||
|  | @ -214,31 +221,40 @@ void VulkanExampleBase::prepare() | ||||||
| 		renderPassCI.pDependencies = dependencies.data(); | 		renderPassCI.pDependencies = dependencies.data(); | ||||||
| 		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass)); | 		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass)); | ||||||
| 	} | 	} | ||||||
| 	else { | 	else  | ||||||
| 		std::array<VkAttachmentDescription, 2> attachments = {}; | 	{ | ||||||
|  | 		std::array<VkAttachmentDescription, 2> attachmentDescriptions = {}; | ||||||
| 		// Color attachment
 | 		// Color attachment
 | ||||||
| 		attachments[0].format = swapChain.colorFormat; | 		attachmentDescriptions[0].format = swapChain.colorFormat; | ||||||
| 		attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; | 		attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; | ||||||
| 		attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | 		attachmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | ||||||
| 		attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; | 		attachmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; | ||||||
| 		attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | 		attachmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | ||||||
| 		attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | 		attachmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | ||||||
| 		attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		attachmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||||||
| 		attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; | 		if (settings.headless) | ||||||
|  | 		{ | ||||||
|  | 			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; | ||||||
|  | 		} | ||||||
| 		// Depth attachment
 | 		// Depth attachment
 | ||||||
| 		attachments[1].format = depthFormat; | 		attachmentDescriptions[1].format = depthFormat; | ||||||
| 		attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; | 		attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; | ||||||
| 		attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | 		attachmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | ||||||
| 		attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; | 		attachmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; | ||||||
| 		attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | 		attachmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; | ||||||
| 		attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | 		attachmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; | ||||||
| 		attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||||||
| 		attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | 		attachmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | ||||||
| 
 | 
 | ||||||
| 		VkAttachmentReference colorReference = {}; | 		VkAttachmentReference colorReference = {}; | ||||||
| 		colorReference.attachment = 0; | 		colorReference.attachment = 0; | ||||||
| 		colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | 		colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | ||||||
| 		 | 		 | ||||||
|  | 
 | ||||||
| 		VkAttachmentReference depthReference = {}; | 		VkAttachmentReference depthReference = {}; | ||||||
| 		depthReference.attachment = 1; | 		depthReference.attachment = 1; | ||||||
| 		depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | 		depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | ||||||
|  | @ -275,13 +291,16 @@ void VulkanExampleBase::prepare() | ||||||
| 
 | 
 | ||||||
| 		VkRenderPassCreateInfo renderPassCI{}; | 		VkRenderPassCreateInfo renderPassCI{}; | ||||||
| 		renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; | 		renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; | ||||||
| 		renderPassCI.attachmentCount = static_cast<uint32_t>(attachments.size()); | 		renderPassCI.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size()); | ||||||
| 		renderPassCI.pAttachments = attachments.data(); | 		renderPassCI.pAttachments = attachmentDescriptions.data(); | ||||||
| 		renderPassCI.subpassCount = 1; | 		renderPassCI.subpassCount = 1; | ||||||
| 		renderPassCI.pSubpasses = &subpassDescription; | 		renderPassCI.pSubpasses = &subpassDescription; | ||||||
| 		renderPassCI.dependencyCount = static_cast<uint32_t>(dependencies.size()); | 		renderPassCI.dependencyCount = static_cast<uint32_t>(dependencies.size()); | ||||||
| 		renderPassCI.pDependencies = dependencies.data(); | 		renderPassCI.pDependencies = dependencies.data(); | ||||||
| 		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass)); | 		VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass)); | ||||||
|  | 
 | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -299,189 +318,6 @@ void VulkanExampleBase::prepare() | ||||||
| 
 | 
 | ||||||
| void VulkanExampleBase::fileDropped(std::string filename) { } | 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() | VulkanExampleBase::VulkanExampleBase() | ||||||
| { | { | ||||||
|  | @ -539,9 +375,9 @@ VulkanExampleBase::~VulkanExampleBase() | ||||||
| 	for (uint32_t i = 0; i < frameBuffers.size(); i++) { | 	for (uint32_t i = 0; i < frameBuffers.size(); i++) { | ||||||
| 		vkDestroyFramebuffer(device, frameBuffers[i], nullptr); | 		vkDestroyFramebuffer(device, frameBuffers[i], nullptr); | ||||||
| 	} | 	} | ||||||
| 	vkDestroyImageView(device, depthStencil.view, nullptr); | 	vkDestroyImageView(device, depthAttachment.view, nullptr); | ||||||
| 	vkDestroyImage(device, depthStencil.image, nullptr); | 	vkDestroyImage(device, depthAttachment.image, nullptr); | ||||||
| 	vkFreeMemory(device, depthStencil.mem, nullptr); | 	vkFreeMemory(device, depthAttachment.memory, nullptr); | ||||||
| 	vkDestroyPipelineCache(device, pipelineCache, nullptr); | 	vkDestroyPipelineCache(device, pipelineCache, nullptr); | ||||||
| 	vkDestroyCommandPool(device, cmdPool, nullptr); | 	vkDestroyCommandPool(device, cmdPool, nullptr); | ||||||
| 	if (settings.multiSampling) { | 	if (settings.multiSampling) { | ||||||
|  | @ -1822,8 +1658,9 @@ void VulkanExampleBase::setupFrameBuffer() | ||||||
| 		imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 		imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||||||
| 		imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; | 		imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; | ||||||
| 		imageCI.samples = settings.sampleCount; | 		imageCI.samples = settings.sampleCount; | ||||||
| 		imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 		imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; | ||||||
| 		imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||||||
|  | 		 | ||||||
| 		VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multisampleTarget.color.image)); | 		VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multisampleTarget.color.image)); | ||||||
| 
 | 
 | ||||||
| 		VkMemoryRequirements memReqs; | 		VkMemoryRequirements memReqs; | ||||||
|  | @ -1891,10 +1728,6 @@ void VulkanExampleBase::setupFrameBuffer() | ||||||
| 		imageViewCI.subresourceRange.levelCount = 1; | 		imageViewCI.subresourceRange.levelCount = 1; | ||||||
| 		imageViewCI.subresourceRange.layerCount = 1; | 		imageViewCI.subresourceRange.layerCount = 1; | ||||||
| 		VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &multisampleTarget.depth.view)); | 		VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &multisampleTarget.depth.view)); | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// Depth/Stencil attachment is the same for all frame buffers
 |  | ||||||
| 
 | 
 | ||||||
| 		VkImageCreateInfo image = {}; | 		VkImageCreateInfo image = {}; | ||||||
| 		image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; | 		image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; | ||||||
|  | @ -1928,28 +1761,107 @@ void VulkanExampleBase::setupFrameBuffer() | ||||||
| 		depthStencilView.subresourceRange.baseArrayLayer = 0; | 		depthStencilView.subresourceRange.baseArrayLayer = 0; | ||||||
| 		depthStencilView.subresourceRange.layerCount = 1; | 		depthStencilView.subresourceRange.layerCount = 1; | ||||||
| 
 | 
 | ||||||
| 	VkMemoryRequirements memReqs; | 		 | ||||||
| 	VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthStencil.image)); | 		VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthAttachment.image)); | ||||||
| 	vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); | 		vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs); | ||||||
| 		mem_alloc.allocationSize = memReqs.size; | 		mem_alloc.allocationSize = memReqs.size; | ||||||
| 		mem_alloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); | 		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(vkAllocateMemory(device, &mem_alloc, nullptr, &depthAttachment.memory)); | ||||||
| 	VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0)); | 		VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.memory, 0)); | ||||||
| 
 | 
 | ||||||
| 	depthStencilView.image = depthStencil.image; | 		depthStencilView.image = depthAttachment.image; | ||||||
| 	VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view)); | 		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; | ||||||
| 
 | 
 | ||||||
| 	VkImageView attachments[4]; | 		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]; | ||||||
| 
 | 
 | ||||||
| 	if (settings.multiSampling) { | 	if (settings.multiSampling) { | ||||||
|  | 		 | ||||||
| 		attachments[0] = multisampleTarget.color.view; | 		attachments[0] = multisampleTarget.color.view; | ||||||
| 		attachments[2] = multisampleTarget.depth.view; | 		attachments[2] = multisampleTarget.depth.view; | ||||||
| 		attachments[3] = depthStencil.view; | 		attachments[3] = depthAttachment.view; | ||||||
| 	} | 	} | ||||||
| 	else { | 	else { | ||||||
| 		attachments[1] = depthStencil.view; | 		 | ||||||
|  | 		attachments[1] = depthAttachment.view; | ||||||
|  | 		attachments[0] = colorAttachment.view; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	VkFramebufferCreateInfo frameBufferCI{}; | 	VkFramebufferCreateInfo frameBufferCI{}; | ||||||
|  | @ -1962,6 +1874,23 @@ void VulkanExampleBase::setupFrameBuffer() | ||||||
| 	frameBufferCI.height = height; | 	frameBufferCI.height = height; | ||||||
| 	frameBufferCI.layers = 1; | 	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
 | 		// Create frame buffers for every swap chain image
 | ||||||
| 		frameBuffers.resize(swapChain.imageCount); | 		frameBuffers.resize(swapChain.imageCount); | ||||||
| 		for (uint32_t i = 0; i < frameBuffers.size(); i++) { | 		for (uint32_t i = 0; i < frameBuffers.size(); i++) { | ||||||
|  | @ -1973,6 +1902,8 @@ void VulkanExampleBase::setupFrameBuffer() | ||||||
| 			} | 			} | ||||||
| 			VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i])); | 			VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i])); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void VulkanExampleBase::windowResize() | void VulkanExampleBase::windowResize() | ||||||
|  | @ -1994,9 +1925,9 @@ void VulkanExampleBase::windowResize() | ||||||
| 		vkDestroyImage(device, multisampleTarget.depth.image, nullptr); | 		vkDestroyImage(device, multisampleTarget.depth.image, nullptr); | ||||||
| 		vkFreeMemory(device, multisampleTarget.depth.memory, nullptr); | 		vkFreeMemory(device, multisampleTarget.depth.memory, nullptr); | ||||||
| 	} | 	} | ||||||
| 	vkDestroyImageView(device, depthStencil.view, nullptr); | 	vkDestroyImageView(device, depthAttachment.view, nullptr); | ||||||
| 	vkDestroyImage(device, depthStencil.image, nullptr); | 	vkDestroyImage(device, depthAttachment.image, nullptr); | ||||||
| 	vkFreeMemory(device, depthStencil.mem, nullptr); | 	vkFreeMemory(device, depthAttachment.memory, nullptr); | ||||||
| 	for (uint32_t i = 0; i < frameBuffers.size(); i++) { | 	for (uint32_t i = 0; i < frameBuffers.size(); i++) { | ||||||
| 		vkDestroyFramebuffer(device, frameBuffers[i], nullptr); | 		vkDestroyFramebuffer(device, frameBuffers[i], nullptr); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -58,16 +58,7 @@ | ||||||
| 
 | 
 | ||||||
| class VulkanExampleBase | class VulkanExampleBase | ||||||
| { | { | ||||||
| private:	 | public: | ||||||
| 	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 MultisampleTarget { | ||||||
| 		struct { | 		struct { | ||||||
| 			VkImage image; | 			VkImage image; | ||||||
|  | @ -80,6 +71,17 @@ private: | ||||||
| 			VkDeviceMemory memory; | 			VkDeviceMemory memory; | ||||||
| 		} depth; | 		} depth; | ||||||
| 	} multisampleTarget; | 	} 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: | protected: | ||||||
| 	VkInstance instance; | 	VkInstance instance; | ||||||
| 	VkPhysicalDevice physicalDevice; | 	VkPhysicalDevice physicalDevice; | ||||||
|  | @ -90,6 +92,7 @@ protected: | ||||||
| 	vks::VulkanDevice *vulkanDevice; | 	vks::VulkanDevice *vulkanDevice; | ||||||
| 	VkQueue queue; | 	VkQueue queue; | ||||||
| 	VkFormat depthFormat; | 	VkFormat depthFormat; | ||||||
|  | 	VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; | ||||||
| 	VkCommandPool cmdPool; | 	VkCommandPool cmdPool; | ||||||
| 	VkRenderPass renderPass; | 	VkRenderPass renderPass; | ||||||
| 	std::vector<VkFramebuffer>frameBuffers; | 	std::vector<VkFramebuffer>frameBuffers; | ||||||
|  | @ -106,25 +109,31 @@ public: | ||||||
| 	bool prepared = false; | 	bool prepared = false; | ||||||
| 	uint32_t width = 1280; | 	uint32_t width = 1280; | ||||||
| 	uint32_t height = 720; | 	uint32_t height = 720; | ||||||
| 	float frameTimer = 1.0f; |  | ||||||
| 	Camera camera; | 	Camera camera; | ||||||
| 	glm::vec2 mousePos; | 	glm::vec2 mousePos; | ||||||
| 	bool paused = false; | 	bool paused = false; | ||||||
| 	uint32_t lastFPS = 0; |  | ||||||
| 
 | 
 | ||||||
| 	struct Settings { | 	struct Settings { | ||||||
| 		bool validation = true; | 		bool validation = true; | ||||||
| 		bool fullscreen = false; | 		bool fullscreen = false; | ||||||
| 		bool vsync = false; | 		bool vsync = false; | ||||||
| 		bool multiSampling = true; | 		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; | 		VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT; | ||||||
| 	} settings; | 	} settings; | ||||||
| 
 | 
 | ||||||
| 	struct DepthStencil { | 	struct FrameBufferAttachment { | ||||||
| 		VkImage image; | 		VkImage image; | ||||||
| 		VkDeviceMemory mem; | 		VkDeviceMemory memory; | ||||||
| 		VkImageView view; | 		VkImageView view; | ||||||
| 	} depthStencil; | 	}; | ||||||
|  | 
 | ||||||
|  | 	FrameBufferAttachment colorAttachment, depthAttachment; | ||||||
|  | 	VkFramebuffer framebuffer; | ||||||
| 
 | 
 | ||||||
| 	struct GamePadState { | 	struct GamePadState { | ||||||
| 		glm::vec2 axisLeft = glm::vec2(0.0f); | 		glm::vec2 axisLeft = glm::vec2(0.0f); | ||||||
|  |  | ||||||
|  | @ -189,6 +189,9 @@ PlumageRender::PlumageRender() | ||||||
| 			VK_CHECK_RESULT(vkEndCommandBuffer(currentCB)); | 			VK_CHECK_RESULT(vkEndCommandBuffer(currentCB)); | ||||||
| 
 | 
 | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 
 | 
 | ||||||
|  | @ -530,6 +533,7 @@ PlumageRender::PlumageRender() | ||||||
| 		rasterizationStateCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; | 		rasterizationStateCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; | ||||||
| 		rasterizationStateCI.lineWidth = 1.0f; | 		rasterizationStateCI.lineWidth = 1.0f; | ||||||
| 		 | 		 | ||||||
|  | 
 | ||||||
| 		VkPipelineColorBlendAttachmentState blendAttachmentState{}; | 		VkPipelineColorBlendAttachmentState blendAttachmentState{}; | ||||||
| 		blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; | 		blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; | ||||||
| 		blendAttachmentState.blendEnable = VK_FALSE; | 		blendAttachmentState.blendEnable = VK_FALSE; | ||||||
|  | @ -558,6 +562,10 @@ PlumageRender::PlumageRender() | ||||||
| 		if (settings.multiSampling) { | 		if (settings.multiSampling) { | ||||||
| 			multisampleStateCI.rasterizationSamples = settings.sampleCount; | 			multisampleStateCI.rasterizationSamples = settings.sampleCount; | ||||||
| 		} | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		std::vector<VkDynamicState> dynamicStateEnables = { | 		std::vector<VkDynamicState> dynamicStateEnables = { | ||||||
| 			VK_DYNAMIC_STATE_VIEWPORT, | 			VK_DYNAMIC_STATE_VIEWPORT, | ||||||
|  | @ -619,9 +627,7 @@ PlumageRender::PlumageRender() | ||||||
| 		pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size()); | 		pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size()); | ||||||
| 		pipelineCI.pStages = shaderStages.data(); | 		pipelineCI.pStages = shaderStages.data(); | ||||||
| 
 | 
 | ||||||
| 		if (settings.multiSampling) { | 		 | ||||||
| 			multisampleStateCI.rasterizationSamples = settings.sampleCount; |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		// Skybox pipeline (background cube)
 | 		// Skybox pipeline (background cube)
 | ||||||
| 		shaderStages = { | 		shaderStages = { | ||||||
|  | @ -1578,29 +1584,23 @@ PlumageRender::PlumageRender() | ||||||
| 		prepared = true; | 		prepared = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue) | 	void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence) | ||||||
| 	{ | 	{ | ||||||
| 		VkSubmitInfo submitInfo = vks::initializers::submitInfo(); | 		VkSubmitInfo submitInfo = vks::initializers::submitInfo(); | ||||||
| 		submitInfo.commandBufferCount = 1; | 		submitInfo.commandBufferCount = 1; | ||||||
| 		submitInfo.pCommandBuffers = &cmdBuffer; | 		submitInfo.pCommandBuffers = &cmdBuffer; | ||||||
| 		VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(); | 		VK_CHECK_RESULT(vkResetFences(device, 1, &fence)); | ||||||
| 		VkFence fence; |  | ||||||
| 		VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence)); |  | ||||||
| 		VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); | 		VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); | ||||||
| 		VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); | 		VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); | ||||||
| 		vkDestroyFence(device, fence, nullptr); | 		//vkDestroyFence(device, fence, nullptr);
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// todo :根据physicalDeviceIndex确定子文件夹路径,frameIndex确定fileName
 | 	// todo :根据physicalDeviceIndex确定子文件夹路径,frameIndex确定fileName
 | ||||||
| 	void PlumageRender::writeImageToFile(std::string filePath) | 	void PlumageRender::writeImageToFile(std::string filePath) | ||||||
| 	{ | 	{ | ||||||
| 
 |  | ||||||
| 		bool surpportBlit = true; |  | ||||||
| 
 |  | ||||||
| 		 |  | ||||||
| 
 |  | ||||||
| 		char* imageData; | 		char* imageData; | ||||||
| 		// create dst image to copy
 | 		// create dst image to copy
 | ||||||
|  | 		 | ||||||
| 		VkImageCreateInfo imageCreateInfo(vks::initializers::imageCreateInfo()); | 		VkImageCreateInfo imageCreateInfo(vks::initializers::imageCreateInfo()); | ||||||
| 		imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; | 		imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; | ||||||
| 		imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; | 		imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; | ||||||
|  | @ -1610,7 +1610,14 @@ PlumageRender::PlumageRender() | ||||||
| 		imageCreateInfo.arrayLayers = 1; | 		imageCreateInfo.arrayLayers = 1; | ||||||
| 		imageCreateInfo.mipLevels = 1; | 		imageCreateInfo.mipLevels = 1; | ||||||
| 		imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | 		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.tiling = VK_IMAGE_TILING_LINEAR; | ||||||
| 		imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; | 		imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; | ||||||
| 
 | 
 | ||||||
|  | @ -1623,20 +1630,28 @@ PlumageRender::PlumageRender() | ||||||
| 		VkDeviceMemory dstImageMemory; | 		VkDeviceMemory dstImageMemory; | ||||||
| 		vkGetImageMemoryRequirements(device, dstImage, &memRequirements); | 		vkGetImageMemoryRequirements(device, dstImage, &memRequirements); | ||||||
| 		memAllocInfo.allocationSize = memRequirements.size; | 		memAllocInfo.allocationSize = memRequirements.size; | ||||||
| 		memAllocInfo.memoryTypeIndex = getMemoryTypeIndex(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); | 		memAllocInfo.memoryTypeIndex = vulkanDevice -> getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); | ||||||
| 		 | 		 | ||||||
| 		// allocate and bind memory
 | 		// allocate and bind memory
 | ||||||
| 		VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory)); | 		VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory)); | ||||||
| 		VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0)); | 		VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0)); | ||||||
| 
 | 
 | ||||||
| 		// blit image and copy to host visualable memory
 | 		// blit image and copy to host visualable memory
 | ||||||
| 		VkCommandBufferAllocateInfo cmdBufferAllocInfo; | 		VkCommandBufferAllocateInfo cmdBufferAllocInfo = vks::initializers::commandBufferAllocateInfo(cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY,1); | ||||||
| 		VkCommandBuffer copyCmd; | 		VkCommandBuffer copyCmd; | ||||||
| 		VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufferAllocInfo, ©Cmd)); | 		VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufferAllocInfo, ©Cmd)); | ||||||
| 		VkCommandBufferBeginInfo cmdBufferBeginInfo = vks::initializers::commandBufferBeginInfo(); | 		VkCommandBufferBeginInfo cmdBufferBeginInfo = vks::initializers::commandBufferBeginInfo(); | ||||||
| 		VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufferBeginInfo)); | 		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{}; | 		VkImageCopy imageCopyRegion{}; | ||||||
| 		imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 		imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||||||
|  | @ -1647,14 +1662,50 @@ PlumageRender::PlumageRender() | ||||||
| 		imageCopyRegion.extent.height = height; | 		imageCopyRegion.extent.height = height; | ||||||
| 		imageCopyRegion.extent.depth = 1; | 		imageCopyRegion.extent.depth = 1; | ||||||
| 
 | 
 | ||||||
| 		vkCmdCopyImage(copyCmd, offscreen.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopyRegion); | 		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); | ||||||
| 
 | 
 | ||||||
| 		// transition dst image to general layout for map memory
 | 		// 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)); | 		VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); | ||||||
| 
 | 
 | ||||||
| 		submitWork(copyCmd, queue); | 		submitWork(copyCmd, queue,waitFences[frameIndex]); | ||||||
|  | 
 | ||||||
|  | 		vkDeviceWaitIdle(device); | ||||||
| 
 | 
 | ||||||
| 		// Get layout of the image
 | 		// Get layout of the image
 | ||||||
| 		VkImageSubresource subResource{}; | 		VkImageSubresource subResource{}; | ||||||
|  | @ -1705,7 +1756,7 @@ PlumageRender::PlumageRender() | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void PlumageRender::outputImageSequence() | 	void PlumageRender::outputImageSequence(uint32_t currentFrame) | ||||||
| 	{ | 	{ | ||||||
| 
 | 
 | ||||||
| 		std::string deviceFilePath = filePath.outputPath + "/device" + std::to_string(selectedPhysicalDeviceIndex); | 		std::string deviceFilePath = filePath.outputPath + "/device" + std::to_string(selectedPhysicalDeviceIndex); | ||||||
|  | @ -1713,33 +1764,34 @@ PlumageRender::PlumageRender() | ||||||
| 		{ | 		{ | ||||||
| 			_mkdir(deviceFilePath.c_str()); | 			_mkdir(deviceFilePath.c_str()); | ||||||
| 		} | 		} | ||||||
| 
 | 		std::string fileName = "/" + std::to_string(currentFrame) + "result.pmm"; | ||||||
| 		for (uint32_t i = 0; i < settings.outputFrameCount; i++) |  | ||||||
| 		{ |  | ||||||
| 			std::string fileName = "/" + std::to_string(i) + "result.pmm"; |  | ||||||
| 		std::string outputPath = deviceFilePath + fileName; | 		std::string outputPath = deviceFilePath + fileName; | ||||||
| 			//std::cout << outputPath << std::endl;
 | 			//std::cout << outputPath << std::endl;
 | ||||||
| 		writeImageToFile(outputPath); | 		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; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	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() | 	void PlumageRender::render() | ||||||
| 	{ | 	{ | ||||||
|  | @ -1750,12 +1802,9 @@ PlumageRender::PlumageRender() | ||||||
| 		updateUIOverlay(); | 		updateUIOverlay(); | ||||||
| 		//加入写到文件的函数
 | 		//加入写到文件的函数
 | ||||||
| 		//swapChainImage = swapChain.images[frameIndex];
 | 		//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); | 		VkResult acquire = swapChain.acquireNextImage(presentCompleteSemaphores[frameIndex], ¤tBuffer); | ||||||
| 		if ((acquire == VK_ERROR_OUT_OF_DATE_KHR) || (acquire == VK_SUBOPTIMAL_KHR)) { | 		if ((acquire == VK_ERROR_OUT_OF_DATE_KHR) || (acquire == VK_SUBOPTIMAL_KHR)) { | ||||||
|  | @ -1764,7 +1813,6 @@ PlumageRender::PlumageRender() | ||||||
| 		else { | 		else { | ||||||
| 			VK_CHECK_RESULT(acquire); | 			VK_CHECK_RESULT(acquire); | ||||||
| 			 | 			 | ||||||
| 			 |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Update UBOs
 | 		// Update UBOs
 | ||||||
|  | @ -1784,7 +1832,9 @@ PlumageRender::PlumageRender() | ||||||
| 		submitInfo.signalSemaphoreCount = 1; | 		submitInfo.signalSemaphoreCount = 1; | ||||||
| 		submitInfo.pCommandBuffers = &commandBuffers[currentBuffer]; | 		submitInfo.pCommandBuffers = &commandBuffers[currentBuffer]; | ||||||
| 		submitInfo.commandBufferCount = 1; | 		submitInfo.commandBufferCount = 1; | ||||||
|  | 		VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[frameIndex])); | ||||||
| 		VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, 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]); | 		VkResult present = swapChain.queuePresent(queue, currentBuffer, renderCompleteSemaphores[frameIndex]); | ||||||
|  | @ -1826,6 +1876,174 @@ 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) | 	void PlumageRender::fileDropped(std::string filename) | ||||||
| 		{ | 		{ | ||||||
| 			vkDeviceWaitIdle(device); | 			vkDeviceWaitIdle(device); | ||||||
|  |  | ||||||
|  | @ -216,19 +216,6 @@ public: | ||||||
| 		VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE; | 		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 { | 	struct DescriptorSetLayouts { | ||||||
| 		VkDescriptorSetLayout scene; | 		VkDescriptorSetLayout scene; | ||||||
| 		VkDescriptorSetLayout material; | 		VkDescriptorSetLayout material; | ||||||
|  | @ -261,6 +248,7 @@ public: | ||||||
| 	} lightSource; | 	} lightSource; | ||||||
| 
 | 
 | ||||||
| 	 | 	 | ||||||
|  | 
 | ||||||
| 	//cube map generation
 | 	//cube map generation
 | ||||||
| 	 | 	 | ||||||
| 	struct OffScreen | 	struct OffScreen | ||||||
|  | @ -287,6 +275,13 @@ public: | ||||||
| 
 | 
 | ||||||
| 	UI* gui; | 	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(); | ||||||
| 	~PlumageRender() | 	~PlumageRender() | ||||||
|  | @ -345,12 +340,14 @@ public: | ||||||
| 	void updateShaderData(); | 	void updateShaderData(); | ||||||
| 	void windowResized(); | 	void windowResized(); | ||||||
| 	void         prepare(); | 	void         prepare(); | ||||||
| 	void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue); | 	void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence); | ||||||
| 	void writeImageToFile(std::string filePath); | 	void writeImageToFile(std::string filePath); | ||||||
| 	void outputImageSequence(); | 	void outputImageSequence(uint32_t currentFrame); | ||||||
|  | 	void renderFrame(); | ||||||
| 	void outputScreenShot(); | 	void outputScreenShot(); | ||||||
| 	uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties); | 	uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties); | ||||||
| 	virtual void render(); | 	virtual void render(); | ||||||
|  | 	void renderLoop(); | ||||||
| 	virtual void updateUIOverlay(); | 	virtual void updateUIOverlay(); | ||||||
| 	virtual void fileDropped(std::string filename); | 	virtual void fileDropped(std::string filename); | ||||||
| }; | }; | ||||||
		Loading…
	
		Reference in New Issue