Beispiel #1
0
void CTexture9::Clear(const vk::ClearDepthStencilValue& clearValue)
{
	vk::ImageLayout originalLayout = mImageLayout;

	mDevice->BeginRecordingUtilityCommands();
	{
		SetImageLayout(vk::ImageLayout::eTransferDstOptimal);

		const vk::ImageSubresourceRange subResourceRange = vk::ImageSubresourceRange()
			.setBaseMipLevel(0)
			.setLevelCount(1)
			.setBaseArrayLayer(0)
			.setLayerCount(1)
			.setAspectMask(vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil);
		mDevice->mCurrentUtilityCommandBuffer.clearDepthStencilImage(mImage.get(), vk::ImageLayout::eTransferDstOptimal, &clearValue, 1, &subResourceRange);

		SetImageLayout(originalLayout);
	}
	mDevice->StopRecordingUtilityCommands();
}
Beispiel #2
0
CTexture9::CTexture9(CDevice9* device, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, HANDLE *pSharedHandle)
	: mDevice(device),
	mWidth(Width),
	mHeight(Height),
	mLevels(Levels),
	mUsage(Usage),
	mFormat(Format),
	mPool(Pool),
	mSharedHandle(pSharedHandle)
{
	Log(info) << "CTexture9::CTexture9" << std::endl;

	//mDevice->AddRef();

	if (!mLevels)
	{
		mLevels = (UINT)std::log2(std::max(mWidth, mHeight)) + 1;
	}

	if (mUsage == 0)
	{
		mUsage = D3DUSAGE_RENDERTARGET;
	}

	mSurfaces.reserve(mLevels);
	UINT width = mWidth, height = mHeight;
	for (int32_t i = 0; i < (int32_t)mLevels; i++)
	{
		CSurface9* ptr = new CSurface9(mDevice, this, width, height, mUsage, 1 /*Levels*/, mFormat, D3DMULTISAMPLE_NONE, 0 /*MultisampleQuality*/, false /*Discard*/, false /*Lockable*/, mPool, mSharedHandle);
		ptr->mMipIndex = i;

		mSurfaces.push_back(ptr);

		width /= 2;
		height /= 2;

		if (height == 0)
		{
			height = 1;
		}
		if (width == 0 && Width > 0)
		{
			width = 1;
		}
	}

	const vk::ImageTiling tiling = vk::ImageTiling::eOptimal;
	const vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
	const vk::MemoryPropertyFlags required_props = vk::MemoryPropertyFlagBits::eDeviceLocal;

	const vk::ImageCreateInfo imageCreateInfo = vk::ImageCreateInfo()
		.setImageType(vk::ImageType::e2D)
		.setFormat(ConvertFormat(mFormat))
		.setExtent({ mWidth, mHeight, 1 })
		.setMipLevels(mLevels)
		.setArrayLayers(1)
		.setSamples(vk::SampleCountFlagBits::e1)
		.setTiling(tiling)
		.setUsage(usage)
		.setSharingMode(vk::SharingMode::eExclusive)
		.setQueueFamilyIndexCount(0)
		.setPQueueFamilyIndices(nullptr)
		.setInitialLayout(vk::ImageLayout::ePreinitialized);
	mImage = mDevice->mDevice->createImageUnique(imageCreateInfo);

	vk::MemoryRequirements memoryRequirements;
	mDevice->mDevice->getImageMemoryRequirements(mImage.get(), &memoryRequirements);

	mImageMemoryAllocateInfo.setAllocationSize(memoryRequirements.size);
	mImageMemoryAllocateInfo.setMemoryTypeIndex(0);

	auto pass = mDevice->FindMemoryTypeFromProperties(memoryRequirements.memoryTypeBits, required_props, &mImageMemoryAllocateInfo.memoryTypeIndex);

	mImageDeviceMemory = mDevice->mDevice->allocateMemoryUnique(mImageMemoryAllocateInfo);

	mDevice->mDevice->bindImageMemory(mImage.get(), mImageDeviceMemory.get(), 0);

	//Now transition this thing from init to shader ready.
	SetImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal);

	/*
	This block handles the luminance & x formats. They are converted to color formats but need a little mapping to make them work correctly.
	*/
	vk::ComponentMapping componentMapping;
	switch (mFormat)
	{
	case D3DFMT_R5G6B5:
		//Vulkan has a matching format but nvidia doesn't support using it as a color attachment so we just use the other one and re-map the components.
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne);
		break;
	case D3DFMT_A8:
		//TODO: Revisit A8 mapping.
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eR);
		break;
	case D3DFMT_L8:
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne);
		break;
	case D3DFMT_L16:
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne);
		break;
	case D3DFMT_A8L8:
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG);
		break;
	case D3DFMT_X8R8G8B8:
	case D3DFMT_X8B8G8R8:
		componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eOne);
		break;
	default:
		break;
	}

	auto const viewInfo = vk::ImageViewCreateInfo()
		.setImage(mImage.get())
		.setViewType(vk::ImageViewType::e2D)
		.setFormat(ConvertFormat(mFormat))
		.setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, mLevels, 0, 1))
		.setComponents(componentMapping);
	mImageView = mDevice->mDevice->createImageViewUnique(viewInfo);
}
Beispiel #3
0
void NewSwapchainInfo(WindowInfo* windowInfo,
					  const PhysDeviceInfo* physDeviceInfo,
                      const SurfaceInfo* surfaceInfo,
                      const DeviceInfo* deviceInfo,
                      SwapchainInfo* swapchainInfo)
{
	//TODO parts of this function could be moved to other functions to improve the flow of initialization?
	//specifically move the use of the function extensions into a single function?
	VkResult error;

	//after logical device creation we can retrieve function pointers associated with it
	GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, CreateSwapchainKHR);
	GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, DestroySwapchainKHR);
	GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, GetSwapchainImagesKHR);
	GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, AcquireNextImageKHR);
	GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, QueuePresentKHR);

	VkSurfaceCapabilitiesKHR surfaceCaps = GetSurfaceCaps(physDeviceInfo->physicalDevice, surfaceInfo->surface);
	std::vector<VkPresentModeKHR> presentModes = GetPresentModes(physDeviceInfo->physicalDevice, surfaceInfo->surface);

	VkSwapchainCreateInfoKHR scInfo = {};
	scInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
	scInfo.surface = surfaceInfo->surface;
	scInfo.minImageCount = GetDesiredNumSwapChainImages(&surfaceCaps);
	scInfo.imageFormat = surfaceInfo->colorFormat;
	scInfo.imageColorSpace = surfaceInfo->colorSpace;
	scInfo.imageExtent = GetSurfaceExtent(&surfaceCaps, &windowInfo->clientWidth, &windowInfo->clientHeight);
	scInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
	scInfo.preTransform = GetSurfaceTransformBits(&surfaceCaps);
	scInfo.imageArrayLayers = 1;
	scInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
	scInfo.presentMode = GetPresentMode(&presentModes);
	//TODO do I ever have an old swapchain and need to create a new one?
	//swapchainCI.oldSwapchain = oldSwapChain;
	scInfo.clipped = VK_TRUE;
	scInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

	error = CreateSwapchainKHR(deviceInfo->device, &scInfo, nullptr, &swapchainInfo->swapChain);
	Assert(error, "could not create a swapchain");

	error = GetSwapchainImagesKHR(deviceInfo->device, swapchainInfo->swapChain, &swapchainInfo->imageCount, nullptr);
	Assert(error, "could not get surface image count");
	swapchainInfo->images.resize(swapchainInfo->imageCount);
	swapchainInfo->views.resize(swapchainInfo->imageCount);
	error = GetSwapchainImagesKHR(deviceInfo->device, swapchainInfo->swapChain, &swapchainInfo->imageCount, swapchainInfo->images.data());
	Assert(error, "could not fill surface images vector");

	for (uint32_t i = 0; i < swapchainInfo->imageCount; i++)
	{
		VkImageViewCreateInfo ivInfo = {};
		ivInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
		ivInfo.format = surfaceInfo->colorFormat;
		ivInfo.components = {
			VK_COMPONENT_SWIZZLE_R,
			VK_COMPONENT_SWIZZLE_G,
			VK_COMPONENT_SWIZZLE_B,
			VK_COMPONENT_SWIZZLE_A
		};
		ivInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
		ivInfo.subresourceRange.baseMipLevel = 0;
		ivInfo.subresourceRange.levelCount = 1;
		ivInfo.subresourceRange.baseArrayLayer = 0;
		ivInfo.subresourceRange.layerCount = 1;
		ivInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
		ivInfo.flags = 0;

		SetImageLayout(deviceInfo->setupCmdBuffer,
		               swapchainInfo->images[i],
		               VK_IMAGE_ASPECT_COLOR_BIT,
		               VK_IMAGE_LAYOUT_UNDEFINED,
		               VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);

		ivInfo.image = swapchainInfo->images[i];
		error = vkCreateImageView(deviceInfo->device, &ivInfo, nullptr, &swapchainInfo->views[i]);
		Assert(error, "could not create image view");
	}
}
Beispiel #4
0
void DrawScene()
{
	// 次のバックバッファを取得する
	uint32_t currentBuffer = g_VkSwapchain.AcquireNextImage(g_VkPresentComplete);

	// コマンドバッファの積み込み
	{
		auto& cmdBuffer = g_VkCmdBuffers[currentBuffer];

		cmdBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources);
		vk::CommandBufferBeginInfo cmdBufInfo;
		cmdBuffer.begin(cmdBufInfo);

		vk::ClearColorValue clearColor(std::array<float, 4>{ 0.0f, 0.0f, 0.5f, 1.0f });

		// カラーバッファクリア
		{
			MySwapchain::Image& colorImage = g_VkSwapchain.GetImages()[currentBuffer];
			vk::ImageSubresourceRange subresourceRange;
			subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
			subresourceRange.levelCount = 1;
			subresourceRange.layerCount = 1;
			
			// カラーバッファクリアのため、レイアウトを変更する
			SetImageLayout(
				cmdBuffer,
				colorImage.image,
				vk::ImageLayout::eUndefined,
				vk::ImageLayout::eTransferDstOptimal,
				subresourceRange);

			// クリアコマンド
			cmdBuffer.clearColorImage(colorImage.image, vk::ImageLayout::eTransferDstOptimal, clearColor, subresourceRange);

			// Presentのため、レイアウトを変更する
			SetImageLayout(
				cmdBuffer,
				colorImage.image,
				vk::ImageLayout::eTransferDstOptimal,
				vk::ImageLayout::ePresentSrcKHR,
				subresourceRange);
		}

		cmdBuffer.end();
	}

	// Submit
	{
		vk::PipelineStageFlags pipelineStages = vk::PipelineStageFlagBits::eBottomOfPipe;
		vk::SubmitInfo submitInfo;
		submitInfo.pWaitDstStageMask = &pipelineStages;
		// 待つ必要があるセマフォの数とその配列を渡す
		submitInfo.waitSemaphoreCount = 1;
		submitInfo.pWaitSemaphores = &g_VkPresentComplete;
		// Submitするコマンドバッファの配列を渡す
		// 複数のコマンドバッファをSubmitしたい場合は配列にする
		submitInfo.commandBufferCount = 1;
		submitInfo.pCommandBuffers = &g_VkCmdBuffers[currentBuffer];
		// 描画完了を知らせるセマフォを登録する
		submitInfo.signalSemaphoreCount = 1;
		submitInfo.pSignalSemaphores = &g_VkRenderComplete;

		// Queueに対してSubmitする
		vk::Fence fence = g_VkSwapchain.GetSubmitFence(true);
		g_VkQueue.submit(submitInfo, fence);
		vk::Result fenceRes = g_VkDevice.waitForFences(fence, VK_TRUE, kFenceTimeout);
		assert(fenceRes == vk::Result::eSuccess);
		//g_VkQueue.waitIdle();
	}

	// Present
	g_VkSwapchain.Present(g_VkRenderComplete);
}