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; } }
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 ); } }
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; } }
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); }
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; } }
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; } }
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; } }
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; } }
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); } }
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); } } }
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); } }
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; } }
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; } }
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; } }
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); } } }
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(); } }
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; }
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"); } }
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); } }
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; }
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); } }
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); } } } }
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; }
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; } }
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)); }
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)); }
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; }
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; }
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); } } }