예제 #1
0
VkResult WrappedVulkan::vkCreateImage(
			VkDevice                                    device,
			const VkImageCreateInfo*                    pCreateInfo,
			const VkAllocationCallbacks*                pAllocator,
			VkImage*                                    pImage)
{
	VkImageCreateInfo createInfo_adjusted = *pCreateInfo;

	createInfo_adjusted.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;

	VkResult ret = ObjDisp(device)->CreateImage(Unwrap(device), &createInfo_adjusted, pAllocator, pImage);
	
	// SHARING: pCreateInfo sharingMode, queueFamilyCount, pQueueFamilyIndices

	if(ret == VK_SUCCESS)
	{
		ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pImage);
		
		if(m_State >= WRITING)
		{
			Chunk *chunk = NULL;

			{
				CACHE_THREAD_SERIALISER();
		
				SCOPED_SERIALISE_CONTEXT(CREATE_IMAGE);
				Serialise_vkCreateImage(localSerialiser, device, pCreateInfo, NULL, pImage);

				chunk = scope.Get();
			}

			VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pImage);
			record->AddChunk(chunk);

			if(pCreateInfo->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT|VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
			{
				record->sparseInfo = new SparseMapping();
				
				{
					SCOPED_LOCK(m_CapTransitionLock);
					if(m_State != WRITING_CAPFRAME)
						GetResourceManager()->MarkDirtyResource(id);
					else
						GetResourceManager()->MarkPendingDirty(id);
				}

				if(pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)
				{
					// must record image and page dimension, and create page tables
					uint32_t numreqs = NUM_VK_IMAGE_ASPECTS;
					VkSparseImageMemoryRequirements reqs[NUM_VK_IMAGE_ASPECTS];
					ObjDisp(device)->GetImageSparseMemoryRequirements(Unwrap(device), Unwrap(*pImage), &numreqs, reqs);

					RDCASSERT(numreqs > 0);
					
					record->sparseInfo->pagedim = reqs[0].formatProperties.imageGranularity;
					record->sparseInfo->imgdim = pCreateInfo->extent;
					record->sparseInfo->imgdim.width /= record->sparseInfo->pagedim.width;
					record->sparseInfo->imgdim.height /= record->sparseInfo->pagedim.height;
					record->sparseInfo->imgdim.depth /= record->sparseInfo->pagedim.depth;
					
					uint32_t numpages = record->sparseInfo->imgdim.width*record->sparseInfo->imgdim.height*record->sparseInfo->imgdim.depth;

					for(uint32_t i=0; i < numreqs; i++)
					{
						// assume all page sizes are the same for all aspects
						RDCASSERT(record->sparseInfo->pagedim.width == reqs[i].formatProperties.imageGranularity.width &&
							record->sparseInfo->pagedim.height == reqs[i].formatProperties.imageGranularity.height &&
							record->sparseInfo->pagedim.depth == reqs[i].formatProperties.imageGranularity.depth);

						int a=0;
						for(; a < NUM_VK_IMAGE_ASPECTS; a++)
							if(reqs[i].formatProperties.aspectMask & (1<<a))
								break;

						record->sparseInfo->pages[a] = new pair<VkDeviceMemory, VkDeviceSize>[numpages];
					}
				}
				else
				{
					// don't have to do anything, image is opaque and must be fully bound, just need
					// to track the memory bindings.
				}
			}
		}
		else
		{
			GetResourceManager()->AddLiveResource(id, *pImage);
			
			m_CreationInfo.m_Image[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
		}

		VkImageSubresourceRange range;
		range.baseMipLevel = range.baseArrayLayer = 0;
		range.levelCount = pCreateInfo->mipLevels;
		range.layerCount = pCreateInfo->arrayLayers;
		if(pCreateInfo->imageType == VK_IMAGE_TYPE_3D)
			range.layerCount = pCreateInfo->extent.depth;

		ImageLayouts *layout = NULL;
		{
			SCOPED_LOCK(m_ImageLayoutsLock);
			layout = &m_ImageLayouts[id];
		}

		layout->layerCount = pCreateInfo->arrayLayers;
		layout->levelCount = pCreateInfo->mipLevels;
		layout->extent = pCreateInfo->extent;
		layout->format = pCreateInfo->format;

		layout->subresourceStates.clear();

		range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
		if(IsDepthOnlyFormat(pCreateInfo->format))
			range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
		else if(IsDepthStencilFormat(pCreateInfo->format))
			range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT;

		layout->subresourceStates.push_back(ImageRegionState(range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED));
	}

	return ret;
}
예제 #2
0
bool WrappedVulkan::Serialise_vkCreateImage(
			Serialiser*                                 localSerialiser,
			VkDevice                                    device,
			const VkImageCreateInfo*                    pCreateInfo,
			const VkAllocationCallbacks*                pAllocator,
			VkImage*                                    pImage)
{
	SERIALISE_ELEMENT(ResourceId, devId, GetResID(device));
	SERIALISE_ELEMENT(VkImageCreateInfo, info, *pCreateInfo);
	SERIALISE_ELEMENT(ResourceId, id, GetResID(*pImage));

	if(m_State == READING)
	{
		device = GetResourceManager()->GetLiveHandle<VkDevice>(devId);
		VkImage img = VK_NULL_HANDLE;

		VkImageUsageFlags origusage = info.usage;

		// ensure we can always display and copy from/to textures
		info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT;

		VkResult ret = ObjDisp(device)->CreateImage(Unwrap(device), &info, NULL, &img);

		info.usage = origusage;

		if(ret != VK_SUCCESS)
		{
			RDCERR("Failed on resource serialise-creation, VkResult: 0x%08x", ret);
		}
		else
		{
			ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), img);
			GetResourceManager()->AddLiveResource(id, img);
			
			m_CreationInfo.m_Image[live].Init(GetResourceManager(), m_CreationInfo, &info);
			
			VkImageSubresourceRange range;
			range.baseMipLevel = range.baseArrayLayer = 0;
			range.levelCount = info.mipLevels;
			range.layerCount = info.arrayLayers;
			if(info.imageType == VK_IMAGE_TYPE_3D)
				range.layerCount = info.extent.depth;
			
			ImageLayouts &layouts = m_ImageLayouts[live];
			layouts.subresourceStates.clear();
			
			layouts.layerCount = info.arrayLayers;
			layouts.levelCount = info.mipLevels;
			layouts.extent = info.extent;
			layouts.format = info.format;

			range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			if(IsDepthOnlyFormat(info.format))
				range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
			else if(IsDepthStencilFormat(info.format))
				range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT;

			layouts.subresourceStates.push_back(ImageRegionState(range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED));
		}
	}

	return true;
}
예제 #3
0
bool VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
	Wipe();

	VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();

	tex_width = w;
	tex_height = h;
	numMips_ = numMips;
	format_ = format;

	VkImageAspectFlags aspect = IsDepthStencilFormat(format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;

	VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
	image_create_info.imageType = VK_IMAGE_TYPE_2D;
	image_create_info.format = format_;
	image_create_info.extent.width = tex_width;
	image_create_info.extent.height = tex_height;
	image_create_info.extent.depth = 1;
	image_create_info.mipLevels = numMips;
	image_create_info.arrayLayers = 1;
	image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
	image_create_info.flags = 0;
	image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
	image_create_info.usage = usage;
	if (initialLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
		image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
	} else {
		image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
	}

	VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image);
	if (res != VK_SUCCESS) {
		assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
		return false;
	}

	// Write a command to transition the image to the requested layout, if it's not already that layout.
	if (initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
		TransitionImageLayout(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, initialLayout);
	}

	vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs);

	if (allocator_) {
		offset_ = allocator_->Allocate(mem_reqs, &mem);
		if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) {
			return false;
		}
	} else {
		VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
		mem_alloc.memoryTypeIndex = 0;
		mem_alloc.allocationSize = mem_reqs.size;

		// Find memory type - don't specify any mapping requirements
		bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
		assert(pass);

		res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem);
		if (res != VK_SUCCESS) {
			assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
			return false;
		}

		offset_ = 0;
	}

	res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, offset_);
	if (res != VK_SUCCESS) {
		assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
		return false;
	}

	// Create the view while we're at it.
	VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
	view_info.image = image;
	view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
	view_info.format = format_;
	if (mapping) {
		view_info.components = *mapping;
	} else {
		view_info.components.r = VK_COMPONENT_SWIZZLE_R;
		view_info.components.g = VK_COMPONENT_SWIZZLE_G;
		view_info.components.b = VK_COMPONENT_SWIZZLE_B;
		view_info.components.a = VK_COMPONENT_SWIZZLE_A;
	}
	view_info.subresourceRange.aspectMask = aspect;
	view_info.subresourceRange.baseMipLevel = 0;
	view_info.subresourceRange.levelCount = numMips;
	view_info.subresourceRange.baseArrayLayer = 0;
	view_info.subresourceRange.layerCount = 1;

	res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view);
	if (res != VK_SUCCESS) {
		assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
		return false;
	}
	return true;
}