parent
							
								
									a0b8b66f2b
								
							
						
					
					
						commit
						04fb6d29e0
					
				| 
						 | 
					@ -120,7 +120,6 @@ 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_TRANSFER_SRC_OPTIMAL;
 | 
							attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_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,15 +143,8 @@ 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_PRESENT_SRC_KHR;
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			attachments[1].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			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;
 | 
				
			||||||
		attachments[2].samples = settings.sampleCount;
 | 
							attachments[2].samples = settings.sampleCount;
 | 
				
			||||||
| 
						 | 
					@ -221,39 +214,30 @@ 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
 | 
				
			||||||
		attachmentDescriptions[0].format = swapChain.colorFormat;
 | 
							attachments[0].format = swapChain.colorFormat;
 | 
				
			||||||
		attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
							attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
		attachmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
							attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
				
			||||||
		attachmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
							attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
				
			||||||
		attachmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
							attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
				
			||||||
		attachmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
							attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
				
			||||||
		attachmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
							attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
		if (settings.headless)
 | 
							attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Depth attachment
 | 
							// Depth attachment
 | 
				
			||||||
		attachmentDescriptions[1].format = depthFormat;
 | 
							attachments[1].format = depthFormat;
 | 
				
			||||||
		attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
							attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
		attachmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
							attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
				
			||||||
		attachmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
							attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
				
			||||||
		attachmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
							attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
				
			||||||
		attachmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
							attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
				
			||||||
		attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
							attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
		attachmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
							attachments[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;
 | 
				
			||||||
| 
						 | 
					@ -291,16 +275,13 @@ 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>(attachmentDescriptions.size());
 | 
							renderPassCI.attachmentCount = static_cast<uint32_t>(attachments.size());
 | 
				
			||||||
		renderPassCI.pAttachments = attachmentDescriptions.data();
 | 
							renderPassCI.pAttachments = attachments.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));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -318,6 +299,189 @@ 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()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -375,9 +539,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, depthAttachment.view, nullptr);
 | 
						vkDestroyImageView(device, depthStencil.view, nullptr);
 | 
				
			||||||
	vkDestroyImage(device, depthAttachment.image, nullptr);
 | 
						vkDestroyImage(device, depthStencil.image, nullptr);
 | 
				
			||||||
	vkFreeMemory(device, depthAttachment.memory, nullptr);
 | 
						vkFreeMemory(device, depthStencil.mem, nullptr);
 | 
				
			||||||
	vkDestroyPipelineCache(device, pipelineCache, nullptr);
 | 
						vkDestroyPipelineCache(device, pipelineCache, nullptr);
 | 
				
			||||||
	vkDestroyCommandPool(device, cmdPool, nullptr);
 | 
						vkDestroyCommandPool(device, cmdPool, nullptr);
 | 
				
			||||||
	if (settings.multiSampling) {
 | 
						if (settings.multiSampling) {
 | 
				
			||||||
| 
						 | 
					@ -1658,9 +1822,8 @@ 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 | 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;
 | 
							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;
 | 
				
			||||||
| 
						 | 
					@ -1728,140 +1891,65 @@ 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));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		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) {
 | 
						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] = depthAttachment.view;
 | 
							attachments[3] = depthStencil.view;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		
 | 
							attachments[1] = depthStencil.view;
 | 
				
			||||||
		attachments[1] = depthAttachment.view;
 | 
					 | 
				
			||||||
		attachments[0] = colorAttachment.view;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VkFramebufferCreateInfo frameBufferCI{};
 | 
						VkFramebufferCreateInfo frameBufferCI{};
 | 
				
			||||||
| 
						 | 
					@ -1874,35 +1962,16 @@ void VulkanExampleBase::setupFrameBuffer()
 | 
				
			||||||
	frameBufferCI.height = height;
 | 
						frameBufferCI.height = height;
 | 
				
			||||||
	frameBufferCI.layers = 1;
 | 
						frameBufferCI.layers = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (settings.headless && ! settings.multiSampling)
 | 
						// Create frame buffers for every swap chain image
 | 
				
			||||||
	{
 | 
						frameBuffers.resize(swapChain.imageCount);
 | 
				
			||||||
		VkImageView attachments[2];
 | 
						for (uint32_t i = 0; i < frameBuffers.size(); i++) {
 | 
				
			||||||
		attachments[0] = colorAttachment.view;
 | 
							if (settings.multiSampling) {
 | 
				
			||||||
		attachments[1] = depthAttachment.view;
 | 
								attachments[1] = swapChain.buffers[i].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]));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							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);
 | 
							vkDestroyImage(device, multisampleTarget.depth.image, nullptr);
 | 
				
			||||||
		vkFreeMemory(device, multisampleTarget.depth.memory, nullptr);
 | 
							vkFreeMemory(device, multisampleTarget.depth.memory, nullptr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	vkDestroyImageView(device, depthAttachment.view, nullptr);
 | 
						vkDestroyImageView(device, depthStencil.view, nullptr);
 | 
				
			||||||
	vkDestroyImage(device, depthAttachment.image, nullptr);
 | 
						vkDestroyImage(device, depthStencil.image, nullptr);
 | 
				
			||||||
	vkFreeMemory(device, depthAttachment.memory, nullptr);
 | 
						vkFreeMemory(device, depthStencil.mem, 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,7 +58,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VulkanExampleBase
 | 
					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 MultisampleTarget {
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			VkImage image;
 | 
								VkImage image;
 | 
				
			||||||
| 
						 | 
					@ -71,17 +80,6 @@ public:
 | 
				
			||||||
			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;
 | 
				
			||||||
| 
						 | 
					@ -92,7 +90,6 @@ 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;
 | 
				
			||||||
| 
						 | 
					@ -109,31 +106,25 @@ 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 FrameBufferAttachment {
 | 
						struct DepthStencil {
 | 
				
			||||||
		VkImage image;
 | 
							VkImage image;
 | 
				
			||||||
		VkDeviceMemory memory;
 | 
							VkDeviceMemory mem;
 | 
				
			||||||
		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,9 +189,6 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
			VK_CHECK_RESULT(vkEndCommandBuffer(currentCB));
 | 
								VK_CHECK_RESULT(vkEndCommandBuffer(currentCB));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -532,7 +529,6 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT;
 | 
							rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT;
 | 
				
			||||||
		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;
 | 
				
			||||||
| 
						 | 
					@ -562,10 +558,6 @@ 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,
 | 
				
			||||||
| 
						 | 
					@ -627,7 +619,9 @@ 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 = {
 | 
				
			||||||
| 
						 | 
					@ -1584,23 +1578,29 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		prepared = true;
 | 
							prepared = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence)
 | 
						void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		VkSubmitInfo submitInfo = vks::initializers::submitInfo();
 | 
							VkSubmitInfo submitInfo = vks::initializers::submitInfo();
 | 
				
			||||||
		submitInfo.commandBufferCount = 1;
 | 
							submitInfo.commandBufferCount = 1;
 | 
				
			||||||
		submitInfo.pCommandBuffers = &cmdBuffer;
 | 
							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(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,14 +1610,7 @@ 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 = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			imageCreateInfo.samples = settings.sampleCount;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1630,28 +1623,20 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		VkDeviceMemory dstImageMemory;
 | 
							VkDeviceMemory dstImageMemory;
 | 
				
			||||||
		vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
 | 
							vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
 | 
				
			||||||
		memAllocInfo.allocationSize = memRequirements.size;
 | 
							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
 | 
							// 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 = vks::initializers::commandBufferAllocateInfo(cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY,1);
 | 
							VkCommandBufferAllocateInfo cmdBufferAllocInfo;
 | 
				
			||||||
		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, 
 | 
							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 });
 | 
				
			||||||
											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;
 | 
				
			||||||
| 
						 | 
					@ -1662,50 +1647,14 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		imageCopyRegion.extent.height = height;
 | 
							imageCopyRegion.extent.height = height;
 | 
				
			||||||
		imageCopyRegion.extent.depth = 1;
 | 
							imageCopyRegion.extent.depth = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		VkImage srcImage;
 | 
							vkCmdCopyImage(copyCmd, offscreen.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopyRegion);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		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,
 | 
							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});
 | 
				
			||||||
											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,waitFences[frameIndex]);
 | 
							submitWork(copyCmd, queue);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		vkDeviceWaitIdle(device);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Get layout of the image
 | 
							// Get layout of the image
 | 
				
			||||||
		VkImageSubresource subResource{};
 | 
							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);
 | 
							std::string deviceFilePath = filePath.outputPath + "/device" + std::to_string(selectedPhysicalDeviceIndex);
 | 
				
			||||||
| 
						 | 
					@ -1764,34 +1713,33 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			_mkdir(deviceFilePath.c_str());
 | 
								_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;
 | 
								//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()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -1802,9 +1750,12 @@ 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)) {
 | 
				
			||||||
| 
						 | 
					@ -1813,6 +1764,7 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			VK_CHECK_RESULT(acquire);
 | 
								VK_CHECK_RESULT(acquire);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
 | 
								
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Update UBOs
 | 
							// Update UBOs
 | 
				
			||||||
| 
						 | 
					@ -1832,10 +1784,8 @@ 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]);
 | 
				
			||||||
		if (!((present == VK_SUCCESS) || (present == VK_SUBOPTIMAL_KHR))) {
 | 
							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)
 | 
						void PlumageRender::fileDropped(std::string filename)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			vkDeviceWaitIdle(device);
 | 
								vkDeviceWaitIdle(device);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,6 +216,19 @@ 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;
 | 
				
			||||||
| 
						 | 
					@ -247,7 +260,6 @@ public:
 | 
				
			||||||
		glm::vec3 rotation = glm::vec3(75.0f, 40.0f, 0.0f);
 | 
							glm::vec3 rotation = glm::vec3(75.0f, 40.0f, 0.0f);
 | 
				
			||||||
	} lightSource;
 | 
						} lightSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//cube map generation
 | 
						//cube map generation
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					@ -274,14 +286,7 @@ public:
 | 
				
			||||||
	} prefilterPushBlock;
 | 
						} prefilterPushBlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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()
 | 
				
			||||||
| 
						 | 
					@ -340,14 +345,12 @@ public:
 | 
				
			||||||
	void updateShaderData();
 | 
						void updateShaderData();
 | 
				
			||||||
	void windowResized();
 | 
						void windowResized();
 | 
				
			||||||
	void         prepare();
 | 
						void         prepare();
 | 
				
			||||||
	void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue, VkFence fence);
 | 
						void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue);
 | 
				
			||||||
	void writeImageToFile(std::string filePath);
 | 
						void writeImageToFile(std::string filePath);
 | 
				
			||||||
	void outputImageSequence(uint32_t currentFrame);
 | 
						void outputImageSequence();
 | 
				
			||||||
	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