예제 #1
0
	void OGLTexture1D::Map1D(uint32_t array_index, uint32_t level, TextureMapAccess tma, uint32_t x_offset, uint32_t /*width*/, void*& data)
	{
		last_tma_ = tma;

		uint32_t const texel_size = NumFormatBytes(format_);

		uint8_t* p;
		OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		switch (tma)
		{
		case TMA_Read_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
				re.BindBuffer(GL_PIXEL_PACK_BUFFER, pbos_[array_index * num_mip_maps_ + level]);

				re.BindTexture(0, target_type_, texture_);
				if (IsCompressedFormat(format_))
				{
					glGetCompressedTexImage(target_type_, level, nullptr);
					p = static_cast<uint8_t*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
				}
				else
				{
					glGetTexImage(target_type_, level, gl_format, gl_type, nullptr);
					p = static_cast<uint8_t*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
				}
			}
			break;

		case TMA_Write_Only:
			re.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
			re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[array_index * num_mip_maps_ + level]);
			p = static_cast<uint8_t*>(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
			break;

		default:
			BOOST_ASSERT(false);
			p = nullptr;
			break;
		}

		if (IsCompressedFormat(format_))
		{
			uint32_t const block_size = NumFormatBytes(format_) * 4;
			data = p + (x_offset / 4 * block_size);
		}
		else
		{
			data = p + x_offset * texel_size;
		}
	}
예제 #2
0
static void GLTexSubImage1DBase(
    GLenum                      target,
    std::uint32_t               mipLevel,
    std::int32_t                x,
    std::uint32_t               width,
    const SrcImageDescriptor&   imageDesc)
{
    if (IsCompressedFormat(imageDesc.format))
    {
        glCompressedTexSubImage1D(
            target,
            static_cast<GLint>(mipLevel),
            x,
            static_cast<GLsizei>(width),
            GLTypes::Map(imageDesc.format),
            static_cast<GLsizei>(imageDesc.dataSize),
            imageDesc.data
        );
    }
    else
    {
        glTexSubImage1D(
            target,
            static_cast<GLint>(mipLevel),
            x,
            static_cast<GLsizei>(width),
            GLTypes::Map(imageDesc.format),
            GLTypes::Map(imageDesc.dataType),
            imageDesc.data
        );
    }
}
예제 #3
0
	void OGLESTexture2D::Unmap2D(uint32_t array_index, uint32_t level)
	{
		switch (last_tma_)
		{
		case TMA_Read_Only:
			break;

		case TMA_Write_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLESMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				uint32_t const w = this->Width(level);
				uint32_t const h = this->Height(level);

				OGLESRenderEngine& re = *checked_cast<OGLESRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
				re.BindTexture(0, target_type_, texture_);

				if (IsCompressedFormat(format_))
				{
					uint32_t const block_size = NumFormatBytes(format_) * 4;
					GLsizei const image_size = ((w + 3) / 4) * ((h + 3) / 4) * block_size;

					if (array_size_ > 1)
					{
						glCompressedTexSubImage3D(target_type_, level, 0, 0, array_index,
							w, h, 1, gl_format, image_size, &tex_data_[array_index * num_mip_maps_ + level][0]);
					}
					else
					{
						glCompressedTexSubImage2D(target_type_, level, 0, 0,
							w, h, gl_format, image_size, &tex_data_[array_index * num_mip_maps_ + level][0]);
					}
				}
				else
				{
					if (array_size_ > 1)
					{
						glTexSubImage3D(target_type_, level, 0, 0, array_index, w, h, 1,
							gl_format, gl_type, &tex_data_[array_index * num_mip_maps_ + level][0]);
					}
					else
					{
						glTexSubImage2D(target_type_, level, 0, 0, w, h,
							gl_format, gl_type, &tex_data_[array_index * num_mip_maps_ + level][0]);
					}
				}
			}
			break;

		default:
			BOOST_ASSERT(false);
			break;
		}
	}
예제 #4
0
bool IsDepthStencilFormat(GLenum internalFormat)
{
	if(IsCompressedFormat(internalFormat))
		return false;

	GLenum fmt = GetBaseFormat(internalFormat);

	return (fmt == eGL_DEPTH_COMPONENT || fmt == eGL_STENCIL || fmt == eGL_DEPTH_STENCIL);
}
예제 #5
0
	OGLTexture1D::OGLTexture1D(uint32_t width, uint32_t numMipMaps, uint32_t array_size, ElementFormat format,
							uint32_t sample_count, uint32_t sample_quality, uint32_t access_hint)
					: OGLTexture(TT_1D, array_size, sample_count, sample_quality, access_hint)
	{
		format_ = format;

		if (0 == numMipMaps)
		{
			num_mip_maps_ = 1;
			uint32_t w = width;
			while (w != 1)
			{
				++ num_mip_maps_;

				w = std::max<uint32_t>(1U, w / 2);
			}
		}
		else
		{
			num_mip_maps_ = numMipMaps;
		}

		width_ = width;

		if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
		{
			glCreateBuffers(1, &pbo_);
		}
		else
		{
			glGenBuffers(1, &pbo_);
		}

		mipmap_start_offset_.resize(num_mip_maps_ + 1);
		mipmap_start_offset_[0] = 0;
		for (uint32_t level = 0; level < num_mip_maps_; ++ level)
		{
			uint32_t const w = this->Width(level);

			GLsizei image_size;
			if (IsCompressedFormat(format_))
			{
				uint32_t const block_size = NumFormatBytes(format_) * 4;
				image_size = ((w + 3) / 4) * block_size;
			}
			else
			{
				uint32_t const texel_size = NumFormatBytes(format_);
				image_size = w * texel_size;
			}

			mipmap_start_offset_[level + 1] = mipmap_start_offset_[level] + image_size;
		}
	}
예제 #6
0
	void OGLESTextureCube::MapCube(uint32_t array_index, CubeFaces face, uint32_t level, TextureMapAccess tma,
					uint32_t x_offset, uint32_t y_offset, uint32_t /*width*/, uint32_t /*height*/,
					void*& data, uint32_t& row_pitch)
	{
		BOOST_ASSERT(0 == array_index);
		UNREF_PARAM(array_index);

		last_tma_ = tma;

		uint32_t const texel_size = NumFormatBytes(format_);
		int block_size;
		if (IsCompressedFormat(format_))
		{
			if ((EF_BC1 == format_) || (EF_SIGNED_BC1 == format_) || (EF_BC1_SRGB == format_)
				|| (EF_BC4 == format_) || (EF_SIGNED_BC4 == format_) || (EF_BC4_SRGB == format_))
			{
				block_size = 8;
			}
			else
			{
				block_size = 16;
			}
		}
		else
		{
			block_size = 0;
		}

		row_pitch = widths_[level] * texel_size;

		uint8_t* p = &tex_data_[face * num_mip_maps_ + level][0];
		if (IsCompressedFormat(format_))
		{
			data = p + (y_offset / 4) * row_pitch + (x_offset / 4 * block_size);
		}
		else
		{
			data = p + (y_offset * widths_[level] + x_offset) * texel_size;
		}
	}
예제 #7
0
	void OGLESTextureCube::UnmapCube(uint32_t array_index, CubeFaces face, uint32_t level)
	{
		BOOST_ASSERT(0 == array_index);
		UNREF_PARAM(array_index);

		switch (last_tma_)
		{
		case TMA_Read_Only:
			break;

		case TMA_Write_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLESMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				glBindTexture(target_type_, texture_);

				if (IsCompressedFormat(format_))
				{
					int block_size;
					if ((EF_BC1 == format_) || (EF_SIGNED_BC1 == format_) || (EF_BC1_SRGB == format_)
						|| (EF_BC4 == format_) || (EF_SIGNED_BC4 == format_) || (EF_BC4_SRGB == format_))
					{
						block_size = 8;
					}
					else
					{
						block_size = 16;
					}

					GLsizei const image_size = ((this->Width(level) + 3) / 4) * ((this->Height(level) + 3) / 4) * block_size;

					glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level,
						0, 0, widths_[level], widths_[level], gl_format, image_size, &tex_data_[face * num_mip_maps_ + level][0]);
				}
				else
				{
					glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level,
						0, 0, widths_[level], widths_[level],
						gl_format, gl_type, &tex_data_[face * num_mip_maps_ + level][0]);
				}
			}
			break;
		default:
			BOOST_ASSERT(false);
			break;
		}
	}
예제 #8
0
	D3D11Texture3D::D3D11Texture3D(uint32_t width, uint32_t height, uint32_t depth, uint32_t numMipMaps, uint32_t array_size, ElementFormat format,
						uint32_t sample_count, uint32_t sample_quality, uint32_t access_hint)
					: D3D11Texture(TT_3D, sample_count, sample_quality, access_hint)
	{
		BOOST_ASSERT(1 == array_size);

		if (0 == numMipMaps)
		{
			numMipMaps = 1;
			uint32_t w = width;
			uint32_t h = height;
			uint32_t d = depth;
			while ((w != 1) || (h != 1) || (d != 1))
			{
				++ numMipMaps;

				w = std::max<uint32_t>(1U, w / 2);
				h = std::max<uint32_t>(1U, h / 2);
				d = std::max<uint32_t>(1U, d / 2);
			}
		}
		num_mip_maps_ = numMipMaps;

		D3D11RenderEngine const & re = *checked_cast<D3D11RenderEngine const *>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		if (re.DeviceFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
		{
			if (!re.DeviceCaps().full_npot_texture_support
				&& (num_mip_maps_ > 1) && (((width & (width - 1)) != 0) || ((height & (height - 1)) != 0) || ((depth & (depth - 1)) != 0)))
			{
				// height or width is not a power of 2 and multiple mip levels are specified. This is not supported at feature levels below 10.0.
				num_mip_maps_ = 1;
			}

			if ((num_mip_maps_ > 1) && IsCompressedFormat(format))
			{
				// height or width is not a multiply of 4 and multiple mip levels are specified. This is not supported at feature levels below 10.0.
				uint32_t clamped_num_mip_maps;
				for (clamped_num_mip_maps = 0; clamped_num_mip_maps < num_mip_maps_; ++ clamped_num_mip_maps)
				{
					uint32_t w = std::max<uint32_t>(1U, width >> clamped_num_mip_maps);
					uint32_t h = std::max<uint32_t>(1U, height >> clamped_num_mip_maps);
					if (((w & 0x3) != 0) || ((h & 0x3) != 0))
					{
						break;
					}
				}
				num_mip_maps_ = clamped_num_mip_maps;
			}
		}
예제 #9
0
	inline uint32_t
	NumComponents(ElementFormat format)
	{
		switch (format)
		{
		case EF_BC4:
		case EF_SIGNED_BC4:
		case EF_BC4_SRGB:
		case EF_ETC2_R11:
		case EF_SIGNED_ETC2_R11:
			return 1;

		case EF_BC5:
		case EF_SIGNED_BC5:
		case EF_BC5_SRGB:
		case EF_ETC2_GR11:
		case EF_SIGNED_ETC2_GR11:
			return 2;

		case EF_BC6:
		case EF_SIGNED_BC6:
		case EF_ETC1:
		case EF_ETC2_BGR8:
		case EF_ETC2_BGR8_SRGB:
			return 3;

		case EF_BC1:
		case EF_SIGNED_BC1:
		case EF_BC1_SRGB:
		case EF_BC2:
		case EF_SIGNED_BC2:
		case EF_BC2_SRGB:
		case EF_BC3:
		case EF_SIGNED_BC3:
		case EF_BC3_SRGB:
		case EF_BC7:
		case EF_BC7_SRGB:
		case EF_ETC2_A1BGR8:
		case EF_ETC2_A1BGR8_SRGB:
		case EF_ETC2_ABGR8:
		case EF_ETC2_ABGR8_SRGB:
			return 4;
		
		default:
			BOOST_ASSERT(!IsCompressedFormat(format));
			return (ChannelBits<0>(format) != 0) + (ChannelBits<1>(format) != 0)
				+ (ChannelBits<2>(format) != 0) + (ChannelBits<3>(format) != 0);
		}
	}
예제 #10
0
	void OGLTexture1D::UpdateSubresource1D(uint32_t array_index, uint32_t level,
		uint32_t x_offset, uint32_t width,
		void const * data)
	{
		OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());

		GLint gl_internalFormat;
		GLenum gl_format;
		GLenum gl_type;
		OGLMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

		re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
		re.BindTexture(0, target_type_, texture_);

		if (IsCompressedFormat(format_))
		{
			uint32_t const block_size = NumFormatBytes(format_) * 4;
			GLsizei const image_size = ((width + 3) / 4) * block_size;

			if (array_size_ > 1)
			{
				glCompressedTexSubImage2D(target_type_, level, x_offset, array_index,
					width, 1, gl_format, image_size, data);
			}
			else
			{
				glCompressedTexSubImage1D(target_type_, level, x_offset,
					width, gl_format, image_size, data);
			}
		}
		else
		{
			if (array_size_ > 1)
			{
				glTexSubImage2D(target_type_, level, x_offset, array_index, width, 1,
					gl_format, gl_type, data);
			}
			else
			{
				glTexSubImage1D(target_type_, level, x_offset, width,
					gl_format, gl_type, data);
			}
		}
	}
예제 #11
0
	inline uint8_t
	NumFormatBits(ElementFormat format)
	{
		switch (format)
		{
		case EF_BC1:
		case EF_SIGNED_BC1:
		case EF_BC1_SRGB:
		case EF_BC4:
		case EF_SIGNED_BC4:
		case EF_BC4_SRGB:
		case EF_ETC2_R11:
		case EF_SIGNED_ETC2_R11:
		case EF_ETC2_BGR8:
		case EF_ETC2_BGR8_SRGB:
		case EF_ETC2_A1BGR8:
		case EF_ETC2_A1BGR8_SRGB:
		case EF_ETC1:
			return 16;

		case EF_BC2:
		case EF_SIGNED_BC2:
		case EF_BC2_SRGB:
		case EF_BC3:
		case EF_SIGNED_BC3:
		case EF_BC3_SRGB:
		case EF_BC5:
		case EF_SIGNED_BC5:
		case EF_BC5_SRGB:
		case EF_BC6:
		case EF_SIGNED_BC6:
		case EF_BC7:
		case EF_BC7_SRGB:
		case EF_ETC2_GR11:
		case EF_SIGNED_ETC2_GR11:
		case EF_ETC2_ABGR8:
		case EF_ETC2_ABGR8_SRGB:
			return 32;
		
		default:
			BOOST_ASSERT(!IsCompressedFormat(format));
			return ChannelBits<0>(format) + ChannelBits<1>(format) + ChannelBits<2>(format) + ChannelBits<3>(format);
		}
	}
예제 #12
0
	D3D11TextureCube::D3D11TextureCube(uint32_t size, uint32_t numMipMaps, uint32_t array_size, ElementFormat format,
						uint32_t sample_count, uint32_t sample_quality, uint32_t access_hint)
					: D3D11Texture(TT_Cube, sample_count, sample_quality, access_hint)
	{
		if (0 == numMipMaps)
		{
			numMipMaps = 1;
			uint32_t w = size;
			while (w != 1)
			{
				++ numMipMaps;

				w = std::max<uint32_t>(1U, w / 2);
			}
		}
		num_mip_maps_ = numMipMaps;

		D3D11RenderEngine const & re = *checked_cast<D3D11RenderEngine const *>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		if (re.DeviceFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
		{
			if (!re.DeviceCaps().full_npot_texture_support
				&& (num_mip_maps_ > 1) && ((size & (size - 1)) != 0))
			{
				// height or width is not a power of 2 and multiple mip levels are specified. This is not supported at feature levels below 10.0.
				num_mip_maps_ = 1;
			}

			if ((num_mip_maps_ > 1) && IsCompressedFormat(format))
			{
				// height or width is not a multiply of 4 and multiple mip levels are specified. This is not supported at feature levels below 10.0.
				uint32_t clamped_num_mip_maps;
				for (clamped_num_mip_maps = 0; clamped_num_mip_maps < num_mip_maps_; ++ clamped_num_mip_maps)
				{
					uint32_t s = std::max<uint32_t>(1U, size >> clamped_num_mip_maps);
					if ((s & 0x3) != 0)
					{
						break;
					}
				}
				num_mip_maps_ = clamped_num_mip_maps;
			}
		}
예제 #13
0
	void OGLESTextureCube::UnmapCube(uint32_t array_index, CubeFaces face, uint32_t level)
	{
		switch (last_tma_)
		{
		case TMA_Read_Only:
			break;

		case TMA_Write_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLESMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				uint32_t const w = this->Width(level);

				OGLESRenderEngine& re = *checked_cast<OGLESRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
				re.BindTexture(0, target_type_, texture_);

				if (IsCompressedFormat(format_))
				{
					uint32_t const block_size = NumFormatBytes(format_) * 4;
					GLsizei const image_size = ((this->Width(level) + 3) / 4) * ((this->Height(level) + 3) / 4) * block_size;

					glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level,
						0, 0, w, w, gl_format, image_size, &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0]);
				}
				else
				{
					glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level,
						0, 0, w, w, gl_format, gl_type, &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0]);
				}
			}
			break;
		default:
			BOOST_ASSERT(false);
			break;
		}
	}
예제 #14
0
	void OGLESTextureCube::MapCube(uint32_t array_index, CubeFaces face, uint32_t level, TextureMapAccess tma,
					uint32_t x_offset, uint32_t y_offset, uint32_t /*width*/, uint32_t /*height*/,
					void*& data, uint32_t& row_pitch)
	{
		last_tma_ = tma;

		uint32_t const texel_size = NumFormatBytes(format_);
		uint32_t const w = this->Width(level);

		row_pitch = w * texel_size;

		uint8_t* p = &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0];
		if (IsCompressedFormat(format_))
		{
			uint32_t const block_size = NumFormatBytes(format_) * 4;
			data = p + (y_offset / 4) * row_pitch + (x_offset / 4 * block_size);
		}
		else
		{
			data = p + (y_offset * w + x_offset) * texel_size;
		}
	}
예제 #15
0
	void OGLESTextureCube::CopyToSubTextureCube(Texture& target,
			uint32_t dst_array_index, CubeFaces dst_face, uint32_t dst_level, uint32_t dst_x_offset, uint32_t dst_y_offset, uint32_t dst_width, uint32_t dst_height,
			uint32_t src_array_index, CubeFaces src_face, uint32_t src_level, uint32_t src_x_offset, uint32_t src_y_offset, uint32_t src_width, uint32_t src_height)
	{
		BOOST_ASSERT(type_ == target.Type());

		OGLESRenderEngine& re = *checked_cast<OGLESRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		if (glloader_GLES_VERSION_3_0() && (!IsCompressedFormat(format_) && (glloader_GLES_EXT_texture_rg() || (4 == NumComponents(format_)))))
		{
			GLuint fbo_src, fbo_dst;
			re.GetFBOForBlit(fbo_src, fbo_dst);

			GLuint old_fbo = re.BindFramebuffer();

			glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src);
			if (array_size_ > 1)
			{
				glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_, src_level, src_array_index * 6 + src_face - CF_Positive_X);
			}
			else
			{
				glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + src_face - CF_Positive_X, texture_, src_level);
			}

			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst);
			if (target.ArraySize() > 1)
			{
				glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, checked_cast<OGLESTexture*>(&target)->GLTexture(), dst_level, dst_array_index * 6 + dst_face - CF_Positive_X);
			}
			else
			{
				glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + dst_face - CF_Positive_X, checked_cast<OGLESTexture*>(&target)->GLTexture(), dst_level);
			}

			glBlitFramebuffer(src_x_offset, src_y_offset, src_x_offset + src_width, src_y_offset + src_height,
							dst_x_offset, dst_y_offset, dst_x_offset + dst_width, dst_y_offset + dst_height,
							GL_COLOR_BUFFER_BIT, ((src_width == dst_width) && (src_height == dst_height)) ? GL_NEAREST : GL_LINEAR);

			re.BindFramebuffer(old_fbo, true);
		}
		else
		{
			if ((src_width == dst_width) && (src_height == dst_height) && (format_ == target.Format()))
			{
				if (IsCompressedFormat(format_))
				{
					BOOST_ASSERT((0 == (src_x_offset & 0x3)) && (0 == (src_y_offset & 0x3)));
					BOOST_ASSERT((0 == (dst_x_offset & 0x3)) && (0 == (dst_y_offset & 0x3)));
					BOOST_ASSERT((0 == (src_width & 0x3)) && (0 == (src_height & 0x3)));
					BOOST_ASSERT((0 == (dst_width & 0x3)) && (0 == (dst_height & 0x3)));

					Texture::Mapper mapper_src(*this, src_array_index, src_face, src_level, TMA_Read_Only, 0, 0, this->Width(src_level), this->Height(src_level));
					Texture::Mapper mapper_dst(target, dst_array_index, dst_face, dst_level, TMA_Write_Only, 0, 0, target.Width(dst_level), target.Height(dst_level));

					uint32_t const block_size = NumFormatBytes(format_) * 4;
					uint8_t const * s = mapper_src.Pointer<uint8_t>() + (src_y_offset / 4) * mapper_src.RowPitch() + (src_x_offset / 4 * block_size);
					uint8_t* d = mapper_dst.Pointer<uint8_t>() + (dst_y_offset / 4) * mapper_dst.RowPitch() + (dst_x_offset / 4 * block_size);
					for (uint32_t y = 0; y < src_height; y += 4)
					{
						std::memcpy(d, s, src_width / 4 * block_size);

						s += mapper_src.RowPitch();
						d += mapper_dst.RowPitch();
					}
				}
				else
				{
					size_t const format_size = NumFormatBytes(format_);					

					Texture::Mapper mapper_src(*this, src_array_index, src_face, src_level, TMA_Read_Only, src_x_offset, src_y_offset, src_width, src_height);
					Texture::Mapper mapper_dst(target, dst_array_index, dst_face, dst_level, TMA_Write_Only, dst_x_offset, dst_y_offset, dst_width, dst_height);
					uint8_t const * s = mapper_src.Pointer<uint8_t>();
					uint8_t* d = mapper_dst.Pointer<uint8_t>();
					for (uint32_t y = 0; y < src_height; ++ y)
					{
						std::memcpy(d, s, src_width * format_size);

						s += mapper_src.RowPitch();
						d += mapper_dst.RowPitch();
					}
				}
			}
			else
			{
				this->ResizeTextureCube(target, dst_array_index, dst_face, dst_level, dst_x_offset, dst_y_offset, dst_width, dst_height,
						src_array_index, src_face, src_level, src_x_offset, src_y_offset, src_width, src_height, true);
			}
		}
	}
예제 #16
0
	void D3D12TextureCube::BuildMipSubLevels()
	{
		// TODO
		// Depth stencil formats
		// Compression formats
		if (IsDepthFormat(format_) || IsCompressedFormat(format_))
		{
			for (uint32_t index = 0; index < this->ArraySize(); ++ index)
			{
				for (int f = 0; f < 6; ++ f)
				{
					CubeFaces const face = static_cast<CubeFaces>(f);
					for (uint32_t level = 1; level < this->NumMipMaps(); ++ level)
					{
						this->ResizeTextureCube(*this, index, face, level, 0, 0, this->Width(level), this->Height(level),
							index, face, level - 1, 0, 0, this->Width(level - 1), this->Height(level - 1), true);
					}
				}
			}
		}
		else
		{
			D3D12RenderEngine& re = *checked_cast<D3D12RenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
			ID3D12Device*device = re.D3DDevice();
			ID3D12GraphicsCommandList* cmd_list = re.D3DRenderCmdList();

			auto const & effect = *re.BlitEffect();
			auto const & tech = *re.BilinearBlitTech();
			auto& pass = tech.Pass(0);
			pass.Bind(effect);
			D3D12ShaderObject& d3d12_so = *checked_cast<D3D12ShaderObject*>(pass.GetShaderObject(effect).get());

			D3D12RenderLayout& d3d12_rl = *checked_cast<D3D12RenderLayout*>(re.PostProcessRenderLayout().get());

			D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc;
			d3d12_so.UpdatePsoDesc(pso_desc);

			pso_desc.StreamOutput.pSODeclaration = nullptr;
			pso_desc.StreamOutput.NumEntries = 0;
			pso_desc.StreamOutput.pBufferStrides = nullptr;
			pso_desc.StreamOutput.NumStrides = 0;
			pso_desc.StreamOutput.RasterizedStream = 0;

			pso_desc.BlendState = checked_pointer_cast<D3D12RenderStateObject>(pass.GetRenderStateObject())->D3DBlendDesc();
			pso_desc.SampleMask = 0xFFFFFFFF;
			pso_desc.RasterizerState = checked_pointer_cast<D3D12RenderStateObject>(pass.GetRenderStateObject())->D3DRasterizerDesc();
			pso_desc.DepthStencilState = checked_pointer_cast<D3D12RenderStateObject>(pass.GetRenderStateObject())->D3DDepthStencilDesc();
			pso_desc.InputLayout.pInputElementDescs = &d3d12_rl.InputElementDesc()[0];
			pso_desc.InputLayout.NumElements = static_cast<UINT>(d3d12_rl.InputElementDesc().size());
			pso_desc.IBStripCutValue = (EF_R16UI == d3d12_rl.IndexStreamFormat())
				? D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF : D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;

			RenderLayout::topology_type tt = d3d12_rl.TopologyType();
			pso_desc.PrimitiveTopologyType = D3D12Mapping::MappingPriTopoType(tt);

			pso_desc.NumRenderTargets = 1;
			pso_desc.RTVFormats[0] = dxgi_fmt_;
			for (uint32_t i = pso_desc.NumRenderTargets; i < std::size(pso_desc.RTVFormats); ++ i)
			{
				pso_desc.RTVFormats[i] = DXGI_FORMAT_UNKNOWN;
			}
			pso_desc.DSVFormat = DXGI_FORMAT_UNKNOWN;
			pso_desc.SampleDesc.Count = 1;
			pso_desc.SampleDesc.Quality = 0;
			pso_desc.NodeMask = 0;
			pso_desc.CachedPSO.pCachedBlob = nullptr;
			pso_desc.CachedPSO.CachedBlobSizeInBytes = 0;
			pso_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;

			ID3D12PipelineStatePtr const & pso = re.CreateRenderPSO(pso_desc);

			re.SetPipelineState(pso.get());
			re.SetGraphicsRootSignature(d3d12_so.RootSignature());

			ID3D12DescriptorHeapPtr cbv_srv_uav_heap = re.CreateDynamicCBVSRVUAVDescriptorHeap(array_size_ * 6 * (num_mip_maps_ - 1));
			auto sampler_heap = d3d12_so.SamplerHeap();

			std::array<ID3D12DescriptorHeap*, 2> heaps;
			uint32_t num_heaps = 0;
			{
				heaps[num_heaps] = cbv_srv_uav_heap.get();
				++ num_heaps;
			}
			if (sampler_heap)
			{
				heaps[num_heaps] = sampler_heap;
				++ num_heaps;
			}
			re.SetDescriptorHeaps(ArrayRef<ID3D12DescriptorHeap*>(heaps.data(), num_heaps));

			if (sampler_heap)
			{
				D3D12_GPU_DESCRIPTOR_HANDLE gpu_sampler_handle = sampler_heap->GetGPUDescriptorHandleForHeapStart();
				cmd_list->SetGraphicsRootDescriptorTable(1, gpu_sampler_handle);
			}

			D3D12GraphicsBuffer& vb = *checked_cast<D3D12GraphicsBuffer*>(d3d12_rl.GetVertexStream(0).get());

			D3D12_VERTEX_BUFFER_VIEW vbv;
			vbv.BufferLocation = vb.GPUVirtualAddress();
			vbv.SizeInBytes = vb.Size();
			vbv.StrideInBytes = d3d12_rl.VertexSize(0);

			re.IASetVertexBuffers(0, vbv);

			re.IASetPrimitiveTopology(tt);

			D3D12_VIEWPORT vp;
			vp.TopLeftX = 0;
			vp.TopLeftY = 0;
			vp.MinDepth = 0;
			vp.MaxDepth = 1;

			D3D12_RECT scissor_rc;
			scissor_rc.left = 0;
			scissor_rc.top = 0;

			D3D12_RESOURCE_BARRIER barrier;
			barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
			barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;

			D3D12_CPU_DESCRIPTOR_HANDLE cpu_cbv_srv_uav_handle = cbv_srv_uav_heap->GetCPUDescriptorHandleForHeapStart();
			D3D12_GPU_DESCRIPTOR_HANDLE gpu_cbv_srv_uav_handle = cbv_srv_uav_heap->GetGPUDescriptorHandleForHeapStart();
			uint32_t const srv_desc_size = re.CBVSRVUAVDescSize();
			for (uint32_t index = 0; index < array_size_; ++ index)
			{
				for (int f = 0; f < 6; ++ f)
				{
					for (uint32_t level = 1; level < num_mip_maps_; ++ level)
					{
						cmd_list->SetGraphicsRootDescriptorTable(0, gpu_cbv_srv_uav_handle);

						UINT n = 0;
						D3D12_RESOURCE_BARRIER barriers[2];
						if (this->UpdateResourceBarrier(CalcSubresource(level - 1, index * 6 + f, 0, num_mip_maps_, array_size_),
							barrier, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE))
						{
							barriers[n] = barrier;
							++ n;
						}
						if (this->UpdateResourceBarrier(CalcSubresource(level, index * 6 + f, 0, num_mip_maps_, array_size_),
							barrier, D3D12_RESOURCE_STATE_RENDER_TARGET))
						{
							barriers[n] = barrier;
							++ n;
						}
						if (n > 0)
						{
							cmd_list->ResourceBarrier(n, barriers);
						}

						D3D12_CPU_DESCRIPTOR_HANDLE const & rt_handle = this->RetriveD3DRenderTargetView(index * 6 + f, 1, level)->Handle();

						D3D12_CPU_DESCRIPTOR_HANDLE const & sr_handle = this->RetriveD3DShaderResourceView(index * 6 + f, 1, level - 1, 1)->Handle();
						device->CopyDescriptorsSimple(1, cpu_cbv_srv_uav_handle, sr_handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

						cmd_list->OMSetRenderTargets(1, &rt_handle, false, nullptr);

						vp.Width = static_cast<float>(this->Width(level));
						vp.Height = static_cast<float>(this->Height(level));
						re.RSSetViewports(1, &vp);

						scissor_rc.right = this->Width(level);
						scissor_rc.bottom = this->Height(level);
						re.RSSetScissorRects(scissor_rc);

						cmd_list->DrawInstanced(4, 1, 0, 0);

						cpu_cbv_srv_uav_handle.ptr += srv_desc_size;
						gpu_cbv_srv_uav_handle.ptr += srv_desc_size;
					}
				}
			}

			pass.Unbind(effect);

			auto& fb = *checked_cast<D3D12FrameBuffer*>(re.CurFrameBuffer().get());
			fb.SetRenderTargets();
		}
	}
예제 #17
0
	void OGLESTexture2D::CreateHWResource(ElementInitData const * init_data)
	{
		uint32_t texel_size = NumFormatBytes(format_);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		glBindTexture(target_type_, texture_);
		for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
		{
			for (uint32_t level = 0; level < num_mip_maps_; ++ level)
			{
				uint32_t const w = this->Width(level);
				uint32_t const h = this->Height(level);

				if (IsCompressedFormat(format_))
				{
					uint32_t const block_size = NumFormatBytes(format_) * 4;
					GLsizei const image_size = ((w + 3) / 4) * ((h + 3) / 4) * block_size;

					void* ptr;
					if (nullptr == init_data)
					{
						tex_data_[array_index * num_mip_maps_ + level].resize(image_size, 0);
						ptr = nullptr;
					}
					else
					{
						tex_data_[array_index * num_mip_maps_ + level].resize(image_size);
						std::memcpy(&tex_data_[array_index * num_mip_maps_ + level][0],
							init_data[array_index * num_mip_maps_ + level].data, image_size);
						ptr = &tex_data_[array_index * num_mip_maps_ + level][0];
					}

					if (array_size_ > 1)
					{
						if (0 == array_index)
						{
							glCompressedTexImage3D(target_type_, level, glinternalFormat,
								w, h, array_size_, 0, image_size * array_size_, nullptr);
						}

						if (init_data != nullptr)
						{
							glCompressedTexSubImage3D(target_type_, level, 0, 0, array_index, w, h, 1,
								glformat, image_size, init_data[array_index * num_mip_maps_ + level].data);
						}
					}
					else
					{
						glCompressedTexImage2D(target_type_, level, glinternalFormat,
							w, h, 0, image_size, ptr);
					}
				}
				else
				{
					GLsizei const image_size = w * h * texel_size;

					void* ptr;
					if (nullptr == init_data)
					{
						tex_data_[array_index * num_mip_maps_ + level].resize(image_size, 0);
						ptr = nullptr;
					}
					else
					{
						tex_data_[array_index * num_mip_maps_ + level].resize(image_size);
						std::memcpy(&tex_data_[array_index * num_mip_maps_ + level][0],
							init_data[array_index * num_mip_maps_ + level].data, image_size);
						ptr = &tex_data_[array_index * num_mip_maps_ + level][0];
					}

					if (array_size_ > 1)
					{
						if (0 == array_index)
						{
							glTexImage3D(target_type_, level, glinternalFormat, w, h, array_size_, 0, glformat, gltype, nullptr);
						}

						if (init_data != nullptr)
						{
							glTexSubImage3D(target_type_, level, 0, 0, array_index, w, h, 1,
								glformat, gltype, init_data[array_index * num_mip_maps_ + level].data);
						}
					}
					else
					{
						glTexImage2D(target_type_, level, glinternalFormat, w, h, 0, glformat, gltype, ptr);
					}
				}
			}
		}

		hw_res_ready_ = true;
	}
예제 #18
0
	void OGLTexture1D::Unmap1D(uint32_t array_index, uint32_t level)
	{
		OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		switch (last_tma_)
		{
		case TMA_Read_Only:
			re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
			re.BindBuffer(GL_PIXEL_PACK_BUFFER, pbo_);
			glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
			break;

		case TMA_Write_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				uint32_t const w = this->Width(level);

				re.BindTexture(0, target_type_, texture_);

				re.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_);
				glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

				GLvoid* offset = reinterpret_cast<GLvoid*>(
					static_cast<GLintptr>(array_index * mipmap_start_offset_.back() + mipmap_start_offset_[level]));
				if (IsCompressedFormat(format_))
				{
					uint32_t const block_size = NumFormatBytes(format_) * 4;
					GLsizei const image_size = ((w + 3) / 4) * block_size;

					if (array_size_ > 1)
					{
						glCompressedTexSubImage2D(target_type_, level, 0, array_index,
							w, 1, gl_format, image_size, offset);
					}
					else
					{
						glCompressedTexSubImage1D(target_type_, level, 0,
							w, gl_format, image_size, offset);
					}
				}
				else
				{
					if (array_size_ > 1)
					{
						glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
							gl_format, gl_type, offset);
					}
					else
					{
						glTexSubImage1D(target_type_, level, 0, w, gl_format, gl_type, offset);
					}
				}
			}
			break;

		default:
			KFL_UNREACHABLE("Invalid texture map access mode");
		}
	}
예제 #19
0
	void OGLESTexture2D::CopyToSubTexture2D(Texture& target,
			uint32_t dst_array_index, uint32_t dst_level, uint32_t dst_x_offset, uint32_t dst_y_offset, uint32_t dst_width, uint32_t dst_height,
			uint32_t src_array_index, uint32_t src_level, uint32_t src_x_offset, uint32_t src_y_offset, uint32_t src_width, uint32_t src_height)
	{
		BOOST_ASSERT(type_ == target.Type());

		OGLESRenderEngine& re = *checked_cast<OGLESRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		if (glloader_GLES_VERSION_3_0() && ((sample_count_ > 1) && !IsCompressedFormat(format_) && (glloader_GLES_EXT_texture_rg() || (4 == NumComponents(format_)))))
		{
			GLuint fbo_src, fbo_dst;
			re.GetFBOForBlit(fbo_src, fbo_dst);

			GLuint old_fbo = re.BindFramebuffer();

			glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src);
			if (array_size_ > 1)
			{
				glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_, src_level, src_array_index);
			}
			else
			{
				if (sample_count_ <= 1)
				{
					glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target_type_, texture_, src_level);
				}
				else
				{
					glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER,
										GL_COLOR_ATTACHMENT0,
										GL_RENDERBUFFER, texture_);
				}
			}

			OGLESTexture& ogl_target = *checked_cast<OGLESTexture*>(&target);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst);
			if (array_size_ > 1)
			{
				glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ogl_target.GLTexture(), dst_level, dst_array_index);
			}
			else
			{
				glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ogl_target.GLType(), ogl_target.GLTexture(), dst_level);
			}

			glBlitFramebuffer(src_x_offset, src_y_offset, src_x_offset + src_width, src_y_offset + src_height,
							dst_x_offset, dst_y_offset, dst_x_offset + dst_width, dst_y_offset + dst_height,
							GL_COLOR_BUFFER_BIT, ((src_width == dst_width) && (src_height == dst_height)) ? GL_NEAREST : GL_LINEAR);

			re.BindFramebuffer(old_fbo, true);
		}
		else if ((src_width == dst_width) && (src_height == dst_height) && (format_ == target.Format()))
		{
			GLint gl_internalFormat;
			GLenum gl_format;
			GLenum gl_type;
			OGLESMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

			GLint gl_target_internal_format;
			GLenum gl_target_format;
			GLenum gl_target_type;
			OGLESMapping::MappingFormat(gl_target_internal_format, gl_target_format, gl_target_type, target.Format());

			if (IsCompressedFormat(format_))
			{
				BOOST_ASSERT((src_width == dst_width) && (src_height == dst_height));
				BOOST_ASSERT((0 == (src_x_offset & 0x3)) && (0 == (src_y_offset & 0x3)));
				BOOST_ASSERT((0 == (dst_x_offset & 0x3)) && (0 == (dst_y_offset & 0x3)));
				BOOST_ASSERT((0 == (src_width & 0x3)) && (0 == (src_height & 0x3)));
				BOOST_ASSERT((0 == (dst_width & 0x3)) && (0 == (dst_height & 0x3)));

				Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, src_x_offset, src_y_offset, src_width, src_height);
				Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, dst_x_offset, dst_y_offset, dst_width, dst_height);

				uint32_t const block_size = NumFormatBytes(format_) * 4;
				uint8_t const * s = mapper_src.Pointer<uint8_t>();
				uint8_t* d = mapper_dst.Pointer<uint8_t>();
				for (uint32_t y = 0; y < src_height; y += 4)
				{
					std::memcpy(d, s, src_width / 4 * block_size);

					s += mapper_src.RowPitch();
					d += mapper_dst.RowPitch();
				}
			}
			else
			{
				size_t const format_size = NumFormatBytes(format_);

				Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, src_x_offset, src_y_offset, src_width, src_height);
				Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, dst_x_offset, dst_y_offset, dst_width, dst_height);
				uint8_t const * s = mapper_src.Pointer<uint8_t>();
				uint8_t* d = mapper_dst.Pointer<uint8_t>();
				for (uint32_t y = 0; y < src_height; ++ y)
				{
					std::memcpy(d, s, src_width * format_size);

					s += mapper_src.RowPitch();
					d += mapper_dst.RowPitch();
				}
			}
		}
		else
		{
			this->ResizeTexture2D(target, dst_array_index, dst_level, dst_x_offset, dst_y_offset, dst_width, dst_height,
					src_array_index, src_level, src_x_offset, src_y_offset, src_width, src_height, true);
		}
	}
예제 #20
0
	void OGLESTexture3D::CreateHWResource(ElementInitData const * init_data)
	{
		uint32_t texel_size = NumFormatBytes(format_);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		glBindTexture(target_type_, texture_);
		for (uint32_t level = 0; level < num_mip_maps_; ++ level)
		{
			uint32_t const w = this->Width(level);
			uint32_t const h = this->Height(level);
			uint32_t const d = this->Depth(level);

			if (IsCompressedFormat(format_))
			{
				uint32_t const block_size = NumFormatBytes(format_) * 4;
				GLsizei const image_size = ((w + 3) / 4) * ((h + 3) / 4) * d * block_size;

				void* ptr;
				if (nullptr == init_data)
				{
					tex_data_[level].resize(image_size, 0);
					ptr = nullptr;
				}
				else
				{
					tex_data_[level].resize(image_size);
					std::memcpy(&tex_data_[level][0], init_data[level].data, image_size);
					ptr = &tex_data_[level][0];
				}
				if (glloader_GLES_VERSION_3_0())
				{
					glCompressedTexImage3D(target_type_, level, glinternalFormat,
						w, h, d, 0, image_size, ptr);
				}
				else
				{
					glCompressedTexImage3DOES(target_type_, level, glinternalFormat,
						w, h, d, 0, image_size, ptr);
				}
			}
			else
			{
				GLsizei const image_size = w * h * d * texel_size;

				void* ptr;
				if (nullptr == init_data)
				{
					tex_data_[level].resize(image_size, 0);
					ptr = nullptr;
				}
				else
				{
					tex_data_[level].resize(image_size);
					std::memcpy(&tex_data_[level][0], init_data[level].data, image_size);
					ptr = &tex_data_[level][0];
				}
				if (glloader_GLES_VERSION_3_0())
				{
					glTexImage3D(target_type_, level, glinternalFormat, w, h, d, 0, glformat, gltype, ptr);
				}
				else
				{
					glTexImage3DOES(target_type_, level, glinternalFormat, w, h, d, 0, glformat, gltype, ptr);
				}
			}
		}

		hw_res_ready_ = true;
	}
예제 #21
0
	void OGLESTexture3D::CopyToSubTexture3D(Texture& target,
			uint32_t dst_array_index, uint32_t dst_level, uint32_t dst_x_offset, uint32_t dst_y_offset, uint32_t dst_z_offset, uint32_t dst_width, uint32_t dst_height, uint32_t dst_depth,
			uint32_t src_array_index, uint32_t src_level, uint32_t src_x_offset, uint32_t src_y_offset, uint32_t src_z_offset, uint32_t src_width, uint32_t src_height, uint32_t src_depth)
	{
		KFL_UNUSED(dst_depth);

		BOOST_ASSERT(type_ == target.Type());
		BOOST_ASSERT(0 == src_array_index);
		BOOST_ASSERT(0 == dst_array_index);

		if ((src_width == dst_width) && (src_height == dst_height) && (src_depth == dst_depth) && (format_ == target.Format()))
		{
			if (IsCompressedFormat(format_))
			{
				BOOST_ASSERT((0 == (src_x_offset & 0x3)) && (0 == (src_y_offset & 0x3)));
				BOOST_ASSERT((0 == (dst_x_offset & 0x3)) && (0 == (dst_y_offset & 0x3)));
				BOOST_ASSERT((0 == (src_width & 0x3)) && (0 == (src_height & 0x3)));
				BOOST_ASSERT((0 == (dst_width & 0x3)) && (0 == (dst_height & 0x3)));

				for (uint32_t z = 0; z < src_depth; ++ z)
				{
					Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only,
						src_x_offset, src_y_offset, src_z_offset + z, src_width, src_height, 1);
					Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only,
						dst_x_offset, dst_y_offset, dst_z_offset + z, dst_width, dst_height, 1);

					uint32_t const block_size = NumFormatBytes(format_) * 4;
					uint8_t const * s = mapper_src.Pointer<uint8_t>();
					uint8_t* d = mapper_dst.Pointer<uint8_t>();
					for (uint32_t y = 0; y < src_height; y += 4)
					{
						std::memcpy(d, s, src_width / 4 * block_size);

						s += mapper_src.RowPitch();
						d += mapper_dst.RowPitch();
					}
				}
			}
			else
			{
				for (uint32_t z = 0; z < src_depth; ++ z)
				{
					size_t const format_size = NumFormatBytes(format_);

					Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only,
						src_x_offset, src_y_offset, src_z_offset + z, src_width, src_height, 1);
					Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only,
						dst_x_offset, dst_y_offset, dst_z_offset + z, dst_width, dst_height, 1);
					uint8_t const * s = mapper_src.Pointer<uint8_t>();
					uint8_t* d = mapper_dst.Pointer<uint8_t>();
					for (uint32_t y = 0; y < src_height; ++ y)
					{
						std::memcpy(d, s, src_width * format_size);

						s += mapper_src.RowPitch();
						d += mapper_dst.RowPitch();
					}
				}
			}
		}
		else
		{
			this->ResizeTexture3D(target, dst_array_index, dst_level, dst_x_offset, dst_y_offset, dst_z_offset, dst_width, dst_height, dst_depth,
				src_array_index, src_level, src_x_offset, src_y_offset, src_z_offset, src_width, src_height, src_depth, true);
		}
	}
예제 #22
0
	void OGLTexture1D::CopyToSubTexture1D(Texture& target,
			uint32_t dst_array_index, uint32_t dst_level, uint32_t dst_x_offset, uint32_t dst_width,
			uint32_t src_array_index, uint32_t src_level, uint32_t src_x_offset, uint32_t src_width)
	{
		BOOST_ASSERT(type_ == target.Type());
		
		if ((format_ == target.Format()) && !IsCompressedFormat(format_) && (glloader_GL_VERSION_4_3() || glloader_GL_ARB_copy_image())
			&& (src_width == dst_width) && (1 == sample_count_))
		{
			OGLTexture& ogl_target = *checked_cast<OGLTexture*>(&target);
			glCopyImageSubData(
				texture_, target_type_, src_level,
				src_x_offset, 0, src_array_index,
				ogl_target.GLTexture(), ogl_target.GLType(), dst_level,
				dst_x_offset, 0, dst_array_index, src_width, 1, 1);
		}
		else
		{
			OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
			if ((sample_count_ > 1) && !IsCompressedFormat(format_) && (glloader_GL_ARB_texture_rg() || (4 == NumComponents(format_))))
			{
				GLuint fbo_src, fbo_dst;
				re.GetFBOForBlit(fbo_src, fbo_dst);

				GLuint old_fbo = re.BindFramebuffer();

				glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src);
				if (array_size_ > 1)
				{
					glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_, src_level, src_array_index);
				}
				else
				{
					if (sample_count_ <= 1)
					{
						glFramebufferTexture1D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target_type_, texture_, src_level);
					}
					else
					{
						glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER,
											GL_COLOR_ATTACHMENT0,
											GL_RENDERBUFFER, texture_);
					}
				}

				OGLTexture& ogl_target = *checked_cast<OGLTexture*>(&target);
				glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst);
				if (array_size_ > 1)
				{
					glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ogl_target.GLTexture(), dst_level, dst_array_index);
				}
				else
				{
					glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target_type_, ogl_target.GLTexture(), dst_level);
				}

				glBlitFramebuffer(src_x_offset, 0, src_x_offset + src_width, 1,
								dst_x_offset, 0, dst_x_offset + dst_width, 1,
								GL_COLOR_BUFFER_BIT, (src_width == dst_width) ? GL_NEAREST : GL_LINEAR);

				re.BindFramebuffer(old_fbo, true);
			}
			else
			{
				if ((src_width == dst_width) && (format_ == target.Format()))
				{
					if (IsCompressedFormat(format_))
					{
						BOOST_ASSERT(0 == (src_x_offset & 0x3));
						BOOST_ASSERT(0 == (dst_x_offset & 0x3));
						BOOST_ASSERT(0 == (src_width & 0x3));
						BOOST_ASSERT(0 == (dst_width & 0x3));

						Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, 0, this->Width(src_level));
						Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, 0, target.Width(dst_level));

						uint32_t const block_size = NumFormatBytes(format_) * 4;
						uint8_t const * s = mapper_src.Pointer<uint8_t>() + (src_x_offset / 4 * block_size);
						uint8_t* d = mapper_dst.Pointer<uint8_t>() + (dst_x_offset / 4 * block_size);
						std::memcpy(d, s, src_width / 4 * block_size);
					}
					else
					{
						size_t const format_size = NumFormatBytes(format_);

						Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, src_x_offset, src_width);
						Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, dst_x_offset, dst_width);
						uint8_t const * s = mapper_src.Pointer<uint8_t>();
						uint8_t* d = mapper_dst.Pointer<uint8_t>();

						std::memcpy(d, s, src_width * format_size);
					}
				}
				else
				{
					this->ResizeTexture1D(target, dst_array_index, dst_level, dst_x_offset, dst_width,
						src_array_index, src_level, src_x_offset, src_width, true);
				}
			}
		}
	}
예제 #23
0
	void OGLTexture1D::CreateHWResource(ElementInitData const * init_data)
	{
		uint32_t texel_size = NumFormatBytes(format_);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		if (sample_count_ <= 1)
		{
			glBindTexture(target_type_, texture_);
			glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);

			OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
			for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
			{
				for (uint32_t level = 0; level < num_mip_maps_; ++ level)
				{
					uint32_t const w = this->Width(level);

					re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[array_index * num_mip_maps_ + level]);
					if (IsCompressedFormat(format_))
					{
						uint32_t const block_size = NumFormatBytes(format_) * 4;
						GLsizei const image_size = ((w + 3) / 4) * block_size;

						glBufferData(GL_PIXEL_UNPACK_BUFFER, image_size, nullptr, GL_STREAM_DRAW);
						re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

						if (array_size_ > 1)
						{
							if (0 == array_index)
							{
								glCompressedTexImage2D(target_type_, level, glinternalFormat,
									w, array_size_, 0, image_size * array_size_, nullptr);
							}

							if (init_data != nullptr)
							{
								glCompressedTexSubImage2D(target_type_, level, 0, array_index, w, 1,
									glformat, image_size, init_data[array_index * num_mip_maps_ + level].data);
							}
						}
						else
						{
							glCompressedTexImage1D(target_type_, level, glinternalFormat,
								w, 0, image_size, (nullptr == init_data) ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
						}
					}
					else
					{
						GLsizei const image_size = w * texel_size;

						glBufferData(GL_PIXEL_UNPACK_BUFFER, image_size, nullptr, GL_STREAM_DRAW);
						re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

						if (array_size_ > 1)
						{
							if (0 == array_index)
							{
								glTexImage2D(target_type_, level, glinternalFormat, w, array_size_, 0, glformat, gltype, nullptr);
							}

							if (init_data != nullptr)
							{
								glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
									glformat, gltype, init_data[array_index * num_mip_maps_ + level].data);
							}
						}
						else
						{
							glTexImage1D(target_type_, level, glinternalFormat, w, 0, glformat, gltype,
								(nullptr == init_data) ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
						}
					}
				}
			}
		}
		else
		{
			glBindRenderbuffer(GL_RENDERBUFFER, texture_);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, sample_count_, glinternalFormat, width_, 1);
		}

		hw_res_ready_ = true;
	}
예제 #24
0
	void OGLTexture1D::Unmap1D(uint32_t array_index, uint32_t level)
	{
		OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
		switch (last_tma_)
		{
		case TMA_Read_Only:
			re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
			re.BindBuffer(GL_PIXEL_PACK_BUFFER, pbos_[array_index * num_mip_maps_ + level]);
			glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
			break;

		case TMA_Write_Only:
		case TMA_Read_Write:
			{
				GLint gl_internalFormat;
				GLenum gl_format;
				GLenum gl_type;
				OGLMapping::MappingFormat(gl_internalFormat, gl_format, gl_type, format_);

				uint32_t const w = this->Width(level);

				re.BindTexture(0, target_type_, texture_);

				re.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[array_index * num_mip_maps_ + level]);
				glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

				if (IsCompressedFormat(format_))
				{
					uint32_t const block_size = NumFormatBytes(format_) * 4;
					GLsizei const image_size = ((w + 3) / 4) * block_size;

					if (array_size_ > 1)
					{
						glCompressedTexSubImage2D(target_type_, level, 0, array_index,
							w, 1, gl_format, image_size, nullptr);
					}
					else
					{
						glCompressedTexSubImage1D(target_type_, level, 0,
							w, gl_format, image_size, nullptr);
					}
				}
				else
				{
					if (array_size_ > 1)
					{
						glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
							gl_format, gl_type, nullptr);
					}
					else
					{
						glTexSubImage1D(target_type_, level, 0, w, gl_format, gl_type, nullptr);
					}
				}
			}
			break;

		default:
			BOOST_ASSERT(false);
			break;
		}
	}
예제 #25
0
size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalformat, int mip)
{
  if(!IsCompressedFormat(internalformat))
  {
    RDCERR("Not compressed format %s", ToStr::Get(internalformat).c_str());
    return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat));
  }

  uint32_t astc[2] = {0, 0};

  switch(internalformat)
  {
    // BC1
    case eGL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    case eGL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
    case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
      return (AlignUp4(w) * AlignUp4(h) * d) / 2;
    // BC2
    case eGL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
      return (AlignUp4(w) * AlignUp4(h) * d);
    // BC3
    case eGL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
    case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
      return (AlignUp4(w) * AlignUp4(h) * d);
    // BC4
    case eGL_COMPRESSED_RED_RGTC1:
    case eGL_COMPRESSED_SIGNED_RED_RGTC1:
      return (AlignUp4(w) * AlignUp4(h) * d) / 2;
    // BC5
    case eGL_COMPRESSED_RG_RGTC2:
    case eGL_COMPRESSED_SIGNED_RG_RGTC2:
      return (AlignUp4(w) * AlignUp4(h) * d);
    // BC6
    case eGL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
    case eGL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
      return (AlignUp4(w) * AlignUp4(h) * d);
    // BC7
    case eGL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
    case eGL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
      return (AlignUp4(w) * AlignUp4(h) * d);
    // ETC2
    case eGL_COMPRESSED_RGB8_ETC2:
    case eGL_COMPRESSED_SRGB8_ETC2:
    case eGL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case eGL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
      return (AlignUp4(w) * AlignUp4(h) * d) / 2;
    // EAC
    case eGL_COMPRESSED_RGBA8_ETC2_EAC:
    case eGL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: return (AlignUp4(w) * AlignUp4(h) * d);
    case eGL_COMPRESSED_R11_EAC:
    case eGL_COMPRESSED_SIGNED_R11_EAC: return (AlignUp4(w) * AlignUp4(h) * d) / 2;
    case eGL_COMPRESSED_RG11_EAC:
    case eGL_COMPRESSED_SIGNED_RG11_EAC: return (AlignUp4(w) * AlignUp4(h) * d);
    case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
      astc[0] = 4;
      astc[1] = 4;
      break;
    case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
      astc[0] = 5;
      astc[1] = 4;
      break;
    case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
      astc[0] = 5;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
      astc[0] = 6;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
      astc[0] = 6;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
      astc[0] = 8;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
      astc[0] = 8;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
      astc[0] = 8;
      astc[1] = 8;
      break;
    case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
      astc[0] = 10;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
      astc[0] = 10;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
      astc[0] = 10;
      astc[1] = 8;
      break;
    case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
      astc[0] = 10;
      astc[1] = 10;
      break;
    case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
      astc[0] = 12;
      astc[1] = 10;
      break;
    case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
      astc[0] = 12;
      astc[1] = 12;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
      astc[0] = 4;
      astc[1] = 4;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
      astc[0] = 5;
      astc[1] = 4;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
      astc[0] = 5;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
      astc[0] = 6;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
      astc[0] = 6;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
      astc[0] = 8;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
      astc[0] = 8;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
      astc[0] = 8;
      astc[1] = 8;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
      astc[0] = 10;
      astc[1] = 5;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
      astc[0] = 10;
      astc[1] = 6;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
      astc[0] = 10;
      astc[1] = 8;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
      astc[0] = 10;
      astc[1] = 10;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
      astc[0] = 12;
      astc[1] = 10;
      break;
    case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
      astc[0] = 12;
      astc[1] = 12;
      break;
    default: break;
  }

  if(astc[0] > 0 && astc[1] > 0)
  {
    uint32_t blocks[2] = {(w / astc[0]), (h / astc[1])};

    // how many blocks are needed - including any extra partial blocks
    blocks[0] += (w % astc[0]) ? 1 : 0;
    blocks[1] += (h % astc[1]) ? 1 : 0;

    // ASTC blocks are all 128 bits each
    return blocks[0] * blocks[1] * 16 * d;
  }

  RDCERR("Unrecognised compressed format %s", ToStr::Get(internalformat).c_str());
  return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat));
}
예제 #26
0
size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalformat, int mip)
{
	if(!IsCompressedFormat(internalformat))
	{
		RDCERR("Not compressed format");
		return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat));
	}

	switch(internalformat)
	{
		// BC1
		case eGL_COMPRESSED_RGB_S3TC_DXT1_EXT:
		case eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
		case eGL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
		case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
			return (AlignUp4(w) * AlignUp4(h) * d) / 2;
		// BC2
		case eGL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
		case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
			return (AlignUp4(w) * AlignUp4(h) * d);
		// BC3
		case eGL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
		case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
			return (AlignUp4(w) * AlignUp4(h) * d);
		// BC4
		case eGL_COMPRESSED_RED_RGTC1:
		case eGL_COMPRESSED_SIGNED_RED_RGTC1:
			return (AlignUp4(w) * AlignUp4(h) * d) / 2;
		// BC5
		case eGL_COMPRESSED_RG_RGTC2:
		case eGL_COMPRESSED_SIGNED_RG_RGTC2:
			return (AlignUp4(w) * AlignUp4(h) * d);
		// BC6
		case eGL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
		case eGL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
			return (AlignUp4(w) * AlignUp4(h) * d);
		// BC7
		case eGL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
		case eGL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
			return (AlignUp4(w) * AlignUp4(h) * d);
		// ETC2
		case eGL_COMPRESSED_RGB8_ETC2:
		case eGL_COMPRESSED_SRGB8_ETC2:
		case eGL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
		case eGL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
			return (AlignUp4(w) * AlignUp4(h) * d) / 2;
		// EAC
		case eGL_COMPRESSED_RGBA8_ETC2_EAC:
		case eGL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
			return (AlignUp4(w) * AlignUp4(h) * d);
		case eGL_COMPRESSED_R11_EAC:
		case eGL_COMPRESSED_SIGNED_R11_EAC:
			return (AlignUp4(w) * AlignUp4(h) * d) / 2;
		case eGL_COMPRESSED_RG11_EAC:
		case eGL_COMPRESSED_SIGNED_RG11_EAC:
			return (AlignUp4(w) * AlignUp4(h) * d);
		default:
			break;
	}

	RDCERR("Unrecognised compressed format");
	return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat));
}
예제 #27
0
	void OGLTexture1D::CreateHWResource(ArrayRef<ElementInitData> init_data, float4 const * clear_value_hint)
	{
		KFL_UNUSED(clear_value_hint);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		if (sample_count_ <= 1)
		{
			uint32_t const pbo_size = mipmap_start_offset_.back() * array_size_;
			if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
			{
				glTextureParameteri(texture_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);

				glNamedBufferStorage(pbo_, pbo_size, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);

				uint32_t const w0 = this->Width(0);

				if (array_size_ > 1)
				{
					glTextureStorage2D(texture_, num_mip_maps_, glinternalFormat, w0, array_size_);
				}
				else
				{
					glTextureStorage1D(texture_, num_mip_maps_, glinternalFormat, w0);
				}

				if (!init_data.empty())
				{
					for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
					{
						for (uint32_t level = 0; level < num_mip_maps_; ++ level)
						{
							uint32_t const w = this->Width(level);
							GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data;

							if (IsCompressedFormat(format_))
							{
								uint32_t const block_size = NumFormatBytes(format_) * 4;
								GLsizei const image_size = ((w + 3) / 4) * block_size;

								if (array_size_ > 1)
								{
									glCompressedTextureSubImage2D(texture_, level, 0, array_index,
										w, 1, glformat, image_size, data);
								}
								else
								{
									glCompressedTextureSubImage1D(texture_, level, 0,
										w, glformat, image_size, data);
								}
							}
							else
							{
								if (array_size_ > 1)
								{
									glTextureSubImage2D(texture_, level, 0, array_index, w, 1,
										glformat, gltype, data);
								}
								else
								{
									glTextureSubImage1D(texture_, level, 0, w, glformat, gltype, data);
								}
							}
						}
					}
				}
			}
			else
			{
				auto& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
				
				re.BindTexture(0, target_type_, texture_);
				glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);

				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_);
				if (glloader_GL_VERSION_4_4() || glloader_GL_ARB_buffer_storage())
				{
					glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_DYNAMIC_STORAGE_BIT);
				}
				else
				{
					glBufferData(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_STREAM_COPY);
				}
				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

				if (glloader_GL_VERSION_4_2() || glloader_GL_ARB_texture_storage())
				{
					uint32_t const w0 = this->Width(0);

					if (array_size_ > 1)
					{
						glTexStorage2D(target_type_, num_mip_maps_, glinternalFormat, w0, array_size_);
					}
					else
					{
						glTexStorage1D(target_type_, num_mip_maps_, glinternalFormat, w0);
					}

					if (!init_data.empty())
					{
						for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
						{
							for (uint32_t level = 0; level < num_mip_maps_; ++ level)
							{
								uint32_t const w = this->Width(level);
								GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data;

								if (IsCompressedFormat(format_))
								{
									uint32_t const block_size = NumFormatBytes(format_) * 4;
									GLsizei const image_size = ((w + 3) / 4) * block_size;

									if (array_size_ > 1)
									{
										glCompressedTexSubImage2D(target_type_, level, 0, array_index,
											w, 1, glformat, image_size, data);
									}
									else
									{
										glCompressedTexSubImage1D(target_type_, level, 0,
											w, glformat, image_size, data);
									}
								}
								else
								{
									if (array_size_ > 1)
									{
										glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, gltype, data);
									}
									else
									{
										glTexSubImage1D(target_type_, level, 0, w, glformat, gltype, data);
									}
								}
							}
						}
					}
				}
				else
				{
					for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
					{
						for (uint32_t level = 0; level < num_mip_maps_; ++ level)
						{
							uint32_t const w = this->Width(level);

							if (IsCompressedFormat(format_))
							{
								uint32_t const block_size = NumFormatBytes(format_) * 4;
								GLsizei const image_size = ((w + 3) / 4) * block_size;

								if (array_size_ > 1)
								{
									if (0 == array_index)
									{
										glCompressedTexImage2D(target_type_, level, glinternalFormat,
											w, array_size_, 0, image_size * array_size_, nullptr);
									}

									if (!init_data.empty())
									{
										glCompressedTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, image_size, init_data[array_index * num_mip_maps_ + level].data);
									}
								}
								else
								{
									glCompressedTexImage1D(target_type_, level, glinternalFormat,
										w, 0, image_size,
										init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
								}
							}
							else
							{
								if (array_size_ > 1)
								{
									if (0 == array_index)
									{
										glTexImage2D(target_type_, level, glinternalFormat, w, array_size_, 0, glformat, gltype, nullptr);
									}

									if (!init_data.empty())
									{
										glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, gltype, init_data[array_index * num_mip_maps_ + level].data);
									}
								}
								else
								{
									glTexImage1D(target_type_, level, glinternalFormat, w, 0, glformat, gltype,
										init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
								}
							}
						}
					}
				}
			}
		}
		else
		{
			glBindRenderbuffer(GL_RENDERBUFFER, texture_);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, sample_count_, glinternalFormat, width_, 1);
		}

		hw_res_ready_ = true;
	}
예제 #28
0
	void OGLESTextureCube::CreateHWResource(ElementInitData const * init_data)
	{
		uint32_t texel_size = NumFormatBytes(format_);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		glBindTexture(target_type_, texture_);
		for (uint32_t array_index = 0; array_index < array_size_; ++ array_index)
		{
			for (int face = 0; face < 6; ++ face)
			{
				for (uint32_t level = 0; level < num_mip_maps_; ++ level)
				{
					uint32_t const s = this->Width(level);

					if (IsCompressedFormat(format_))
					{
						uint32_t const block_size = NumFormatBytes(format_) * 4;
						GLsizei const image_size = ((s + 3) / 4) * ((s + 3) / 4) * block_size;

						void* ptr;
						if (nullptr == init_data)
						{
							tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size, 0);
							ptr = nullptr;
						}
						else
						{
							tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size);
							std::memcpy(&tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0],
								init_data[(array_index * 6 + face) * num_mip_maps_ + level].data, image_size);
							ptr = &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0];
						}

						if (array_size_ > 1)
						{
							if (0 == array_index)
							{
								glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat,
									s, s, array_size_, 0, image_size * array_size_, nullptr);
							}

							if (init_data != nullptr)
							{
								glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, 0, 0, array_index, s, s, 1,
									glformat, image_size, init_data[(array_index * 6 + face) * num_mip_maps_ + level].data);
							}
						}
						else
						{
							glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat,
								s, s, 0, image_size, ptr);
						}
					}
					else
					{
						GLsizei const image_size = s * s * texel_size;

						void* ptr;
						if (nullptr == init_data)
						{
							tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size, 0);
							ptr = nullptr;
						}
						else
						{
							tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size);
							std::memcpy(&tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0],
								init_data[face * num_mip_maps_ + level].data, image_size);
							ptr = &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0];
						}

						if (array_size_ > 1)
						{
							if (0 == array_index)
							{
								glTexImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat, s, s, array_size_, 0, glformat, gltype, nullptr);
							}

							if (init_data != nullptr)
							{
								glTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, 0, 0, array_index, s, s, 1,
									glformat, gltype, init_data[array_index * num_mip_maps_ + level].data);
							}
						}
						else
						{
							glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat,
								s, s, 0, glformat, gltype, ptr);
						}
					}
				}
			}
		}

		hw_res_ready_ = true;
	}
예제 #29
0
	OGLESTextureCube::OGLESTextureCube(uint32_t size, uint32_t numMipMaps, uint32_t array_size, ElementFormat format,
								uint32_t sample_count, uint32_t sample_quality, uint32_t access_hint, ElementInitData const * init_data)
					: OGLESTexture(TT_Cube, array_size, sample_count, sample_quality, access_hint)
	{
		if (IsSRGB(format))
		{
			format = this->SRGBToRGB(format);
		}

		format_ = format;

		if (0 == numMipMaps)
		{
			num_mip_maps_ = 1;
			uint32_t s = size;
			while (s > 1)
			{
				++ num_mip_maps_;

				s = std::max<uint32_t>(1U, s / 2);
			}
		}
		else
		{
			num_mip_maps_ = numMipMaps;
		}
		array_size_ = 1;

		uint32_t texel_size = NumFormatBytes(format_);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		glGenTextures(1, &texture_);
		glBindTexture(target_type_, texture_);
		glTexParameteri(target_type_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(target_type_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		if (glloader_GLES_VERSION_3_0())
		{
			glTexParameteri(target_type_, GL_TEXTURE_BASE_LEVEL, 0);
			glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);
		}
		else 
		if (glloader_GLES_APPLE_texture_max_level())
		{
			glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL_APPLE, num_mip_maps_ - 1);
		}

		tex_data_.resize(6 * num_mip_maps_);
		widths_.resize(6 * num_mip_maps_);
		for (int face = 0; face < 6; ++ face)
		{
			uint32_t s = size;
			for (uint32_t level = 0; level < num_mip_maps_; ++ level)
			{
				widths_[face * num_mip_maps_ + level] = s;

				if (IsCompressedFormat(format_))
				{
					int block_size;
					if ((EF_BC1 == format_) || (EF_SIGNED_BC1 == format_) || (EF_BC1_SRGB == format_)
						|| (EF_BC4 == format_) || (EF_SIGNED_BC4 == format_) || (EF_BC4_SRGB == format_))
					{
						block_size = 8;
					}
					else
					{
						block_size = 16;
					}

					GLsizei const image_size = ((s + 3) / 4) * ((s + 3) / 4) * block_size;

					if (nullptr == init_data)
					{
						tex_data_[face * num_mip_maps_ + level].resize(image_size, 0);
					}
					else
					{
						tex_data_[face * num_mip_maps_ + level].resize(image_size);
						std::memcpy(&tex_data_[face * num_mip_maps_ + level][0], init_data[face * num_mip_maps_ + level].data, image_size);
					}
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat,
						s, s, 0, image_size, &tex_data_[face * num_mip_maps_ + level][0]);
				}
				else
				{
					GLsizei const image_size = s * s * texel_size;

					if (nullptr == init_data)
					{
						tex_data_[face * num_mip_maps_ + level].resize(image_size, 0);
					}
					else
					{
						tex_data_[face * num_mip_maps_ + level].resize(image_size);
						std::memcpy(&tex_data_[face * num_mip_maps_ + level][0], init_data[face * num_mip_maps_ + level].data, image_size);
					}
					glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat,
						s, s, 0, glformat, gltype, &tex_data_[face * num_mip_maps_ + level][0]);
				}

				s = std::max(1U, s / 2);
			}
		}
	}