Add GECompressorBPTCBC7

This commit is contained in:
Benau 2022-08-25 15:13:23 +08:00
parent 3e2de9419e
commit 57c5446e55
9 changed files with 5131 additions and 0 deletions

View File

@ -64,6 +64,7 @@ endif()
set(GE_SOURCES
src/gl.c
src/ge_compressor_astc_4x4.cpp
src/ge_compressor_bptc_bc7.cpp
src/ge_compressor_s3tc_bc3.cpp
src/ge_culling_tool.cpp
src/ge_dx9_texture.cpp
@ -97,7 +98,22 @@ if(NOT APPLE OR DLOPEN_MOLTENVK)
set(GE_SOURCES ${GE_SOURCES} src/vulkan.c)
endif()
option(BC7_ISPC "Enable BC7 (BPTC) support (requires ispc and cmake >= 3.19)" OFF)
if(BC7_ISPC)
add_definitions(-DBC7_ISPC)
enable_language(ISPC)
set(CMAKE_ISPC_FLAGS "${CMAKE_ISPC_FLAGS} --opt=fast-math --opt=disable-assertions --pic")
set(GE_SOURCES
${GE_SOURCES}
src/bc7e.ispc
)
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
endif()
add_library(graphics_engine STATIC ${GE_SOURCES})
if(BC7_ISPC)
set_property(TARGET graphics_engine PROPERTY ISPC_INSTRUCTION_SETS avx2)
endif()
target_link_libraries(graphics_engine ${SQUISH_LIBRARY})

View File

@ -37,6 +37,8 @@ bool supportsComputeInMainQueue();
// ----------------------------------------------------------------------------
bool supportsS3TCBC3();
// ----------------------------------------------------------------------------
bool supportsBPTCBC7();
// ----------------------------------------------------------------------------
bool supportsASTC4x4();
}; // GEVulkanFeatures

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
#include "ge_compressor_bptc_bc7.hpp"
#include "ge_main.hpp"
#include "ge_vulkan_features.hpp"
#ifdef BC7_ISPC
#include <bc7e_ispc.h>
#endif
#include <algorithm>
#include <cassert>
namespace GE
{
// ============================================================================
void GECompressorBPTCBC7::init()
{
#ifdef BC7_ISPC
if (!GEVulkanFeatures::supportsBPTCBC7())
return;
ispc::bc7e_compress_block_init();
#endif
} // init
// ----------------------------------------------------------------------------
GECompressorBPTCBC7::GECompressorBPTCBC7(uint8_t* texture, unsigned channels,
const irr::core::dimension2d<irr::u32>& size,
bool normal_map)
: GEMipmapGenerator(texture, channels, size, normal_map)
{
#ifdef BC7_ISPC
assert(channels == 4);
size_t total_size = 0;
m_mipmap_sizes = 0;
for (unsigned i = 0; i < m_levels.size(); i++)
{
GEImageLevel& level = m_levels[i];
unsigned cur_size = get4x4CompressedTextureSize(level.m_dim.Width,
level.m_dim.Height);
total_size += cur_size;
if (i > 0)
m_mipmap_sizes += cur_size;
}
ispc::bc7e_compress_block_params p = {};
ispc::bc7e_compress_block_params_init_ultrafast(&p, true/*perceptual*/);
std::vector<GEImageLevel> compressed_levels;
m_compressed_data = new uint8_t[total_size];
uint8_t* cur_offset = m_compressed_data;
for (GEImageLevel& level : m_levels)
{
uint8_t* out = cur_offset;
for (unsigned y = 0; y < level.m_dim.Height; y += 4)
{
for (unsigned x = 0; x < level.m_dim.Width; x += 4)
{
// build the 4x4 block of pixels
uint32_t source_rgba[16] = {};
uint8_t* target_pixel = (uint8_t*)source_rgba;
for (unsigned py = 0; py < 4; py++)
{
for (unsigned px = 0; px < 4; px++)
{
// get the source pixel in the image
unsigned sx = x + px;
unsigned sy = y + py;
// enable if we're in the image
if (sx < level.m_dim.Width && sy < level.m_dim.Height)
{
uint8_t* rgba = (uint8_t*)level.m_data;
const unsigned pitch = level.m_dim.Width * 4;
uint8_t* source_pixel = rgba + pitch * sy + 4 * sx;
memcpy(target_pixel, source_pixel, 4);
}
// advance to the next pixel
target_pixel += 4;
}
}
ispc::bc7e_compress_blocks(1, (uint64_t*)out, source_rgba, &p);
out += 16;
}
}
unsigned cur_size = get4x4CompressedTextureSize(level.m_dim.Width,
level.m_dim.Height);
compressed_levels.push_back({ level.m_dim, cur_size, cur_offset });
cur_offset += cur_size;
}
freeMipmapCascade();
std::swap(compressed_levels, m_levels);
#endif
} // GECompressorBPTCBC7
}

View File

@ -0,0 +1,25 @@
#ifndef HEADER_GE_COMPRESSOR_BPTC_BC7_HPP
#define HEADER_GE_COMPRESSOR_BPTC_BC7_HPP
#include "ge_mipmap_generator.hpp"
namespace GE
{
class GECompressorBPTCBC7 : public GEMipmapGenerator
{
private:
uint8_t* m_compressed_data;
public:
// ------------------------------------------------------------------------
static void init();
// ------------------------------------------------------------------------
GECompressorBPTCBC7(uint8_t* texture, unsigned channels,
const irr::core::dimension2d<irr::u32>& size,
bool normal_map);
// ------------------------------------------------------------------------
~GECompressorBPTCBC7() { delete [] m_compressed_data; }
}; // GECompressorBPTCBC7
}
#endif

View File

@ -3,6 +3,7 @@
#include "ge_main.hpp"
#include "ge_mipmap_generator.hpp"
#include "ge_compressor_astc_4x4.hpp"
#include "ge_compressor_bptc_bc7.hpp"
#include "ge_compressor_s3tc_bc3.hpp"
#include "ge_texture.hpp"
#include "ge_vulkan_command_loader.hpp"
@ -156,6 +157,17 @@ void GEVulkanArrayTexture::reloadInternal(const std::vector<io::path>& list,
mipmap_generator = new GECompressorASTC4x4(texture_data, 4, m_size,
normal_map);
}
else if (texture_compression && GEVulkanFeatures::supportsBPTCBC7())
{
if (i == 0)
{
image_size = get4x4CompressedTextureSize(m_size.Width,
m_size.Height);
m_internal_format = VK_FORMAT_BC7_UNORM_BLOCK;
}
mipmap_generator = new GECompressorBPTCBC7(texture_data, 4, m_size,
normal_map);
}
else if (texture_compression && GEVulkanFeatures::supportsS3TCBC3())
{
if (i == 0)

View File

@ -1,6 +1,7 @@
#include "ge_vulkan_driver.hpp"
#include "ge_compressor_astc_4x4.hpp"
#include "ge_compressor_bptc_bc7.hpp"
#include "ge_main.hpp"
#include "ge_vulkan_2d_renderer.hpp"
@ -636,6 +637,7 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
GEVulkanShaderManager::getMeshTextureLayer(),
GEVulkanFeatures::supportsBindMeshTexturesAtOnce());
GECompressorASTC4x4::init();
GECompressorBPTCBC7::init();
GEVulkanFeatures::printStats();
}
catch (std::exception& e)

View File

@ -10,6 +10,7 @@
#include <vector>
#include "../source/Irrlicht/os.h"
#include <SDL_cpuinfo.h>
namespace GE
{
@ -28,6 +29,7 @@ bool g_supports_multi_draw_indirect = false;
bool g_supports_base_vertex_rendering = true;
bool g_supports_compute_in_main_queue = false;
bool g_supports_s3tc_bc3 = false;
bool g_supports_bptc_bc7 = false;
bool g_supports_astc_4x4 = false;
} // GEVulkanFeatures
@ -72,6 +74,16 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
VK_FORMAT_BC3_UNORM_BLOCK, &format_properties);
g_supports_s3tc_bc3 = format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
#ifdef BC7_ISPC
format_properties = {};
// We compile bc7e.ispc with avx2 on
if (SDL_HasAVX2() == SDL_TRUE)
{
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
VK_FORMAT_BC7_UNORM_BLOCK, &format_properties);
g_supports_bptc_bc7 = format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
}
#endif
format_properties = {};
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
VK_FORMAT_ASTC_4x4_UNORM_BLOCK, &format_properties);
@ -196,6 +208,9 @@ void GEVulkanFeatures::printStats()
os::Printer::log(
"Vulkan supports s3 texture compression (bc3, dxt5)",
g_supports_s3tc_bc3 ? "true" : "false");
os::Printer::log(
"Vulkan supports BPTC texture compression (bc7)",
g_supports_bptc_bc7 ? "true" : "false");
os::Printer::log(
"Vulkan supports adaptive scalable texture compression (4x4 block)",
supportsASTC4x4() ? "true" : "false");
@ -284,6 +299,12 @@ bool GEVulkanFeatures::supportsS3TCBC3()
return g_supports_s3tc_bc3;
} // supportsS3TCBC3
// ----------------------------------------------------------------------------
bool GEVulkanFeatures::supportsBPTCBC7()
{
return g_supports_bptc_bc7;
} // supportsBPTCBC7
// ----------------------------------------------------------------------------
bool GEVulkanFeatures::supportsASTC4x4()
{

View File

@ -3,6 +3,7 @@
#include "ge_main.hpp"
#include "ge_mipmap_generator.hpp"
#include "ge_compressor_astc_4x4.hpp"
#include "ge_compressor_bptc_bc7.hpp"
#include "ge_compressor_s3tc_bc3.hpp"
#include "ge_texture.hpp"
#include "ge_vulkan_command_loader.hpp"
@ -159,6 +160,14 @@ bool GEVulkanTexture::createTextureImage(uint8_t* texture_data,
mipmap_generator = new GECompressorASTC4x4(texture_data, channels,
m_size, normal_map);
}
else if (texture_compression && GEVulkanFeatures::supportsBPTCBC7())
{
image_size = get4x4CompressedTextureSize(m_size.Width,
m_size.Height);
m_internal_format = VK_FORMAT_BC7_UNORM_BLOCK;
mipmap_generator = new GECompressorBPTCBC7(texture_data, channels,
m_size, normal_map);
}
else if (texture_compression && GEVulkanFeatures::supportsS3TCBC3())
{
image_size = get4x4CompressedTextureSize(m_size.Width,