示例#1
0
void
TextureLoader::create( const unsigned int _width, const unsigned int _height, 
					   const TEXTURE_FORMAT _textureFormat,
					   const bool _createMipLevels )
{
	// argument checks
	if ( _width < 1 )
		GEM_ERROR( "Invalid texture width " + _width );
	if ( _height < 1 )
		GEM_ERROR( "Invalid texture height " + _height );
	if ( _textureFormat == TEXTURE_FORMAT_NONE )
		GEM_ERROR( "Invalid texture format " + _textureFormat );


	// always create new
	if ( isLoaded_ )
		clear( );


	// allocate memory for first mip level
	try
	{
		if ( _createMipLevels )
		{
			createMipLevels( _width, _height, _textureFormat, MAX_MIP_LEVELS );
		}
		else
		{
			createMipLevels( _width, _height, _textureFormat, 1 );
		}
	}
	catch( const std::exception &e )
	{
		clear();
		GEM_ERROR( e.what() );
	}


	// we got this far, so we are ok to setup member variables
	isLoaded_ = true;
}
示例#2
0
void
TextureLoader::loadDDS( const std::string& _path )
{
	// local vars
	std::ifstream ifs;
	DDSHEADER ddshdr;


	// open file for reading
	ifs.open( _path.c_str(), std::ifstream::in | std::ifstream::binary );
	if ( ifs.fail() )
	{
		GEM_THROW( "Could not open file " + _path );
	}


	// read dds header
	ifs.read( reinterpret_cast<char*>(&ddshdr), sizeof( DDSHEADER ) );
	if ( ifs.fail( ) )
	{
		ifs.close();
		GEM_THROW( "Failed to read image file header." );
	}


	// make sure its a .dds file
	if ( ddshdr.type == "DDS " )
	{
		ifs.close();
		GEM_THROW( "File is not a DDS file." );
	}


	// DXT1 format
	if ( ddshdr.pixelFormat.fourCC==FOURCC_DXT1 )
	{
		// allocate data
		createMipLevels( ddshdr.width, ddshdr.height,
						 TEXTURE_FORMAT_RGB_DXT1, ddshdr.mipMapCount );


		// read image data for each mipmap
		for ( unsigned int i=0; i<mipLevelCount_; ++i )
		{
			// get character ptr and total bytecount
			char* ptr = mipLevels_[i].getWritePtr<char>();
			int bytecount =  mipLevels_[i].getByteCount();

			ifs.read( ptr, bytecount );
			if ( ifs.fail() )
			{
				ifs.close();
				GEM_THROW( "Failed to read image data." );
			}
		}
	}


	// format not supported
	else
	{
		ifs.close();
		GEM_THROW( "This file is not a DXT1 file." );
	}


	// close file and return
	ifs.close();
}
示例#3
0
void
TextureLoader::loadPFM( const std::string& _path )
{
	// local vars
	PFMHEADER hdr;
	std::ifstream ifs;
	char ignore;


	// open file for reading
	ifs.open( _path.c_str(), std::ifstream::in | std::ifstream::binary );
	if ( ifs.fail() )
	{
		GEM_THROW( "Could not open file " + _path );
	}


	// get header info
	ifs >> hdr.p >> hdr.f				// identifier line
		>> hdr.width >> hdr.height		// dimension line
		>> hdr.scalefactor;				// scale/endianess line
		ifs.getline( &ignore, 1 );		// chew last linefeed
	if ( hdr.p!='P' || ( hdr.f!='F' && hdr .f!='f' ) )
	{
		ifs.close();
		GEM_THROW( "Failed to read image header." );
	}


	// 32-bit/channel floating point RGB
	if ( hdr.f=='F' )
	{
		// allocate data
		createMipLevels( hdr.width, hdr.height, TEXTURE_FORMAT_RGB_32F, 1 );


		// get character ptr and total bytecount
		char* ptr = mipLevels_[0].getWritePtr<char>();
		int bytecount =  mipLevels_[0].getByteCount();


		// read floating point data from file
		ifs.read( ptr, bytecount );
		if ( ifs.fail() )
		{
			ifs.close();
			GEM_THROW( "Failed to read image data." );
		}
	}

 
	// 32-bit/channel floating point monochrome
	else
	{
		// set variables and allocate data
		createMipLevels( hdr.width, hdr.height, TEXTURE_FORMAT_R_32F, 1 );
		char* ptr = mipLevels_[0].getWritePtr<char>();
		int bytecount =  mipLevels_[0].getByteCount();


		// read floating point data from file
		ifs.read( ptr, bytecount );
		if ( ifs.fail() )
		{
			ifs.close();
			GEM_THROW( "Failed to read image data." );
		}
	}


	// clean up and return
	ifs.close();
}
示例#4
0
void
TextureLoader::loadBMP( const std::string& _path )
{
	// local vars
	std::ifstream ifs;
	BITMAPFILEHEADER filehdr;
	BITMAPINFOHEADER infohdr;


	// open file for reading
	ifs.open( _path.c_str(), std::ifstream::in | std::ifstream::binary );
	if ( ifs.fail() )
	{
		GEM_THROW( "Could not open file " + _path );
	}


	// read file header.
	// values are read one by one rather then the whole struct at once because
	// compilers will not always do two-padding of structs. This way is
	// preferred here over getting into compiler specific directives.
	ifs.read( reinterpret_cast<char*>(&filehdr.type), 2 );
	ifs.read( reinterpret_cast<char*>(&filehdr.size), 4 );
	ifs.read( reinterpret_cast<char*>(&filehdr.reserved1), 2 );
	ifs.read( reinterpret_cast<char*>(&filehdr.reserved2), 2 );
	ifs.read( reinterpret_cast<char*>(&filehdr.offBits), 4 );
	if ( ifs.fail( ) )
	{
		ifs.close();
		GEM_THROW( "Failed to read image file header." );
	}

	
	// make sure its a bitmap
	if ( filehdr.type == "BM" )
	{
		ifs.close();
		GEM_THROW( "File is not a bitmap." );
	}


	// read info header
	ifs.read( reinterpret_cast<char*>(&infohdr), sizeof( BITMAPINFOHEADER ) );
	if ( ifs.fail( ) )
	{
		ifs.close();
		GEM_THROW( "Failed to read image info header." );
	}


	// read 24-bit (rgb)
	if ( infohdr.bitCount==24 )
	{
		// allocate data
		createMipLevels( infohdr.width, infohdr.height,
						 TEXTURE_FORMAT_RGB_8UI, 1 );

		
		// get character ptr and total bytecount
		char* ptr = mipLevels_[0].getWritePtr<char>();
		int bytecount =  mipLevels_[0].getByteCount();


		// jump to data section
		ifs.seekg( filehdr.offBits, std::ios::beg );

		
		// read image data
		ifs.read( ptr, bytecount );
		if ( ifs.fail() )
		{
			ifs.close();
			GEM_THROW( "Failed to read image data." );
		}


		// data is in BGR format, so swap R and B
		for ( int i=0; i<bytecount; i+=3 )
		{
			ptr[i] ^= ptr[i+2];
			ptr[i+2] ^= ptr[i];
			ptr[i] ^= ptr[i+2];
		}
	}


	// read 8-bit (monochrome)
	else if ( infohdr.bitCount==8 )
	{
		// set variables and allocate data
		createMipLevels( infohdr.width, infohdr.height,
						 TEXTURE_FORMAT_R_8UI, 1 );
		char* ptr = mipLevels_[0].getWritePtr<char>();
		int bytecount =  mipLevels_[0].getByteCount();

		
		// jump to data section
		ifs.seekg( filehdr.offBits, std::ios::beg );

		
		// read image data
		ifs.read( ptr, bytecount );
		if ( ifs.fail() )
		{
			ifs.close();
			GEM_THROW( "Failed to read image data." );
		}
	}


	// bitcount is not supported, close and report failiure
	else
	{
		ifs.close();
		GEM_THROW( "Bitmap format not supported." );
	}


	// close file and return
	ifs.close();
}
示例#5
0
void vkImageBase::updateMipVkImage(uint64_t texSize, std::vector<void *> &pixels,
                                   std::vector<ImageInfo> &bitmapInfos,
                                   std::vector<VkBufferImageCopy> &bufferCopyRegions,
                                   VkImageViewType target, VkFormat internalFormat,
                                   int mipLevels,
                                   VkImageCreateFlags flags) {

    VkResult err;
    bool pass;
    VulkanRenderer *vk_renderer = static_cast<VulkanRenderer *>(Renderer::getInstance());
    VkDevice device = vk_renderer->getDevice();
    VkFormatProperties formatProperties;
    vkGetPhysicalDeviceFormatProperties(vk_renderer->getPhysicalDevice(), internalFormat,
                                        &formatProperties);

    VkBuffer texBuffer;
    VkDeviceMemory texMemory;

    VkMemoryAllocateInfo memoryAllocateInfo = {};
    memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    memoryAllocateInfo.pNext = NULL;
    memoryAllocateInfo.allocationSize = 0;
    memoryAllocateInfo.memoryTypeIndex = 0;

    err = vkCreateBuffer(device,
                         gvr::BufferCreateInfo(texSize,
                                               VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
                         nullptr, &texBuffer);


    GVR_VK_CHECK(!err);

    // Obtain the requirements on memory for this buffer
    VkMemoryRequirements mem_reqs;
    vkGetBufferMemoryRequirements(device, texBuffer, &mem_reqs);
    assert(!err);

    memoryAllocateInfo.allocationSize = mem_reqs.size;

    pass = vk_renderer->GetMemoryTypeFromProperties(mem_reqs.memoryTypeBits,
                                                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
                                                    &memoryAllocateInfo.memoryTypeIndex);
    assert(pass);
    size = mem_reqs.size;
    err = vkAllocateMemory(device, gvr::MemoryAllocateInfo(mem_reqs.size,
                                                           memoryAllocateInfo.memoryTypeIndex),
                           NULL, &texMemory);
    unsigned char *texData;
    err = vkMapMemory(device, texMemory, 0,
                      memoryAllocateInfo.allocationSize, 0, (void **) &texData);
    assert(!err);
    int i = 0;
    for (auto &buffer_copy_region: bufferCopyRegions) {
        memcpy(texData + buffer_copy_region.bufferOffset, pixels[i],
               bitmapInfos[i].size);
        i++;
    }
    vkUnmapMemory(device, texMemory);

    // Bind our buffer to the memory
    err = vkBindBufferMemory(device, texBuffer, texMemory, 0);
    assert(!err);

    err = vkCreateImage(device, gvr::ImageCreateInfo(VK_IMAGE_TYPE_2D,
                                                     internalFormat,
                                                     bitmapInfos[0].width,
                                                     bitmapInfos[0].height, 1, mipLevels, pixels.size(),
                                                     VK_IMAGE_TILING_OPTIMAL,
                                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                                     VK_IMAGE_USAGE_SAMPLED_BIT,
                                                     flags,
                                                     getVKSampleBit(mSampleCount),
                                                     VK_IMAGE_LAYOUT_UNDEFINED), NULL,
                        &imageHandle);
    assert(!err);

    vkGetImageMemoryRequirements(device, imageHandle, &mem_reqs);

    memoryAllocateInfo.allocationSize = mem_reqs.size;

    pass = vk_renderer->GetMemoryTypeFromProperties(mem_reqs.memoryTypeBits,
                                                    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
                                                    &memoryAllocateInfo.memoryTypeIndex);
    assert(pass);

    /* allocate memory */
    err = vkAllocateMemory(device, &memoryAllocateInfo, NULL, &device_memory);
    assert(!err);

    /* bind memory */
    err = vkBindImageMemory(device, imageHandle, device_memory, 0);
    assert(!err);

    // Reset the setup command buffer
    VkCommandBuffer textureCmdBuffer;
    vk_renderer->initCmdBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, textureCmdBuffer);

    vkResetCommandBuffer(textureCmdBuffer, 0);
    VkCommandBufferInheritanceInfo commandBufferInheritanceInfo = {};
    commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
    commandBufferInheritanceInfo.pNext = NULL;
    commandBufferInheritanceInfo.renderPass = VK_NULL_HANDLE;
    commandBufferInheritanceInfo.subpass = 0;
    commandBufferInheritanceInfo.framebuffer = VK_NULL_HANDLE;
    commandBufferInheritanceInfo.occlusionQueryEnable = VK_FALSE;
    commandBufferInheritanceInfo.queryFlags = 0;
    commandBufferInheritanceInfo.pipelineStatistics = 0;

    VkCommandBufferBeginInfo setupCmdsBeginInfo;
    setupCmdsBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    setupCmdsBeginInfo.pNext = NULL;
    setupCmdsBeginInfo.flags = 0;
    setupCmdsBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo;

    // Begin recording to the command buffer.
    vkBeginCommandBuffer(textureCmdBuffer, &setupCmdsBeginInfo);

    VkImageMemoryBarrier imageMemoryBarrier = {};
    imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    imageMemoryBarrier.pNext = NULL;
    imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
    imageMemoryBarrier.subresourceRange.levelCount = 1;
    imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
    imageMemoryBarrier.subresourceRange.layerCount = pixels.size();
    imageMemoryBarrier.srcAccessMask = 0;
    imageMemoryBarrier.dstAccessMask =
            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;

    // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout
    setImageLayout(imageMemoryBarrier, textureCmdBuffer, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT,
                   VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                   imageMemoryBarrier.subresourceRange);

    vkCmdCopyBufferToImage(
            textureCmdBuffer,
            texBuffer,
            imageHandle,
            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
            static_cast<uint32_t>(bufferCopyRegions.size()),
            bufferCopyRegions.data());

    imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

    setImageLayout(imageMemoryBarrier, textureCmdBuffer, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT,
                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                   imageMemoryBarrier.subresourceRange);

    // We are finished recording operations.
    vkEndCommandBuffer(textureCmdBuffer);

    VkCommandBuffer buffers[1];
    buffers[0] = textureCmdBuffer;

    VkSubmitInfo submit_info;
    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info.pNext = NULL;
    submit_info.waitSemaphoreCount = 0;
    submit_info.pWaitSemaphores = NULL;
    submit_info.pWaitDstStageMask = NULL;
    submit_info.commandBufferCount = 1;
    submit_info.pCommandBuffers = &buffers[0];
    submit_info.signalSemaphoreCount = 0;
    submit_info.pSignalSemaphores = NULL;
    VkQueue queue = vk_renderer->getQueue();

    // Submit to our shared graphics queue.
    err = vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
    assert(!err);

    // Wait for the queue to become idle.
    err = vkQueueWaitIdle(queue);
    assert(!err);

    vkFreeMemory(device, texMemory, nullptr);
    vkDestroyBuffer(device, texBuffer, nullptr);

    if(mipLevels > 1)
        createMipLevels(formatProperties, vk_renderer, setupCmdsBeginInfo,
                        bufferCopyRegions, mipLevels, bitmapInfos, imageMemoryBarrier,
                        submit_info, buffers, queue);

    err = vkCreateImageView(device, gvr::ImageViewCreateInfo(imageHandle,
                                                             target,
                                                             internalFormat, mipLevels,0,
                                                             pixels.size(),
                                                             VK_IMAGE_ASPECT_COLOR_BIT), NULL,
                            &imageView);
    assert(!err);
}