Add GECompressorS3TCBC3
This commit is contained in:
parent
4f32435ef2
commit
b4b0ddc620
@ -242,6 +242,21 @@ else()
|
||||
set(ENET_LIBRARIES "enet")
|
||||
endif()
|
||||
|
||||
if(NOT SERVER_ONLY)
|
||||
if(USE_SYSTEM_SQUISH)
|
||||
find_library(SQUISH_LIBRARY NAMES squish libsquish)
|
||||
find_path(SQUISH_INCLUDEDIR NAMES squish.h PATHS)
|
||||
endif()
|
||||
if (NOT SQUISH_LIBRARY OR NOT SQUISH_INCLUDEDIR)
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/libsquish")
|
||||
include_directories(BEFORE "${PROJECT_SOURCE_DIR}/lib/libsquish")
|
||||
SET(SQUISH_LIBRARY squish)
|
||||
else()
|
||||
include_directories("${SQUISH_INCLUDEDIR}")
|
||||
MESSAGE(STATUS "Use system libsquish: ${SQUISH_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT SERVER_ONLY)
|
||||
find_library(SHADERC_LIBRARY NAMES shaderc_shared libshaderc_shared)
|
||||
find_path(SHADERC_INCLUDEDIR NAMES shaderc/shaderc.hpp PATHS)
|
||||
@ -322,21 +337,6 @@ else()
|
||||
MESSAGE(STATUS "Use system libmcpp: ${MCPP_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT SERVER_ONLY)
|
||||
if(USE_SYSTEM_SQUISH)
|
||||
find_library(SQUISH_LIBRARY NAMES squish libsquish)
|
||||
find_path(SQUISH_INCLUDEDIR NAMES squish.h PATHS)
|
||||
endif()
|
||||
if (NOT SQUISH_LIBRARY OR NOT SQUISH_INCLUDEDIR)
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/libsquish")
|
||||
include_directories(BEFORE "${PROJECT_SOURCE_DIR}/lib/libsquish")
|
||||
SET(SQUISH_LIBRARY squish)
|
||||
else()
|
||||
include_directories("${SQUISH_INCLUDEDIR}")
|
||||
MESSAGE(STATUS "Use system libsquish: ${SQUISH_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT SERVER_ONLY)
|
||||
# SDL2
|
||||
find_library(SDL2_LIBRARY NAMES SDL2 libSDL2)
|
||||
|
@ -24,6 +24,7 @@ endif()
|
||||
|
||||
set(GE_SOURCES
|
||||
src/gl.c
|
||||
src/ge_compressor_s3tc_bc3.cpp
|
||||
src/ge_culling_tool.cpp
|
||||
src/ge_dx9_texture.cpp
|
||||
src/ge_main.cpp
|
||||
@ -55,3 +56,5 @@ if(NOT APPLE OR DLOPEN_MOLTENVK)
|
||||
endif()
|
||||
|
||||
add_library(graphics_engine STATIC ${GE_SOURCES})
|
||||
|
||||
target_link_libraries(graphics_engine ${SQUISH_LIBRARY})
|
||||
|
@ -13,6 +13,7 @@ struct GEConfig
|
||||
{
|
||||
bool m_disable_npot_texture;
|
||||
bool m_convert_irrlicht_mesh;
|
||||
bool m_texture_compression;
|
||||
};
|
||||
|
||||
void setVideoDriver(irr::video::IVideoDriver* driver);
|
||||
@ -34,6 +35,12 @@ inline size_t getPadding(size_t in, size_t alignment)
|
||||
else
|
||||
return alignment - mod;
|
||||
}
|
||||
inline int get4x4CompressedTextureSize(int width, int height)
|
||||
{
|
||||
int blockcount = ((width + 3) / 4) * ((height + 3) / 4);
|
||||
int blocksize = 4 * 4;
|
||||
return blockcount * blocksize;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
98
lib/graphics_engine/src/ge_compressor_s3tc_bc3.cpp
Normal file
98
lib/graphics_engine/src/ge_compressor_s3tc_bc3.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "ge_compressor_s3tc_bc3.hpp"
|
||||
#include "ge_main.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <squish.h>
|
||||
static_assert(squish::kColourClusterFit == (1 << 5), "Wrong header");
|
||||
static_assert(squish::kColourRangeFit == (1 << 6), "Wrong header");
|
||||
static_assert(squish::kColourIterativeClusterFit == (1 << 8), "Wrong header");
|
||||
|
||||
// ============================================================================
|
||||
extern "C" void squishCompressImage(uint8_t* rgba, int width, int height,
|
||||
int pitch, void* blocks, unsigned flags)
|
||||
{
|
||||
// This function is copied from CompressImage in libsquish to avoid omp
|
||||
// if enabled by shared libsquish, because we are already using
|
||||
// multiple thread
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
// initialise the block output
|
||||
uint8_t* target_block = reinterpret_cast<uint8_t*>(blocks);
|
||||
target_block += ((y >> 2) * ((width + 3) >> 2)) * 16;
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
// build the 4x4 block of pixels
|
||||
uint8_t source_rgba[16 * 4];
|
||||
uint8_t* target_pixel = source_rgba;
|
||||
int mask = 0;
|
||||
for (int py = 0; py < 4; py++)
|
||||
{
|
||||
for (int px = 0; px < 4; px++)
|
||||
{
|
||||
// get the source pixel in the image
|
||||
int sx = x + px;
|
||||
int sy = y + py;
|
||||
// enable if we're in the image
|
||||
if (sx < width && sy < height)
|
||||
{
|
||||
// copy the rgba value
|
||||
uint8_t* source_pixel = rgba + pitch * sy + 4 * sx;
|
||||
memcpy(target_pixel, source_pixel, 4);
|
||||
// enable this pixel
|
||||
mask |= (1 << (4 * py + px));
|
||||
}
|
||||
// advance to the next pixel
|
||||
target_pixel += 4;
|
||||
}
|
||||
}
|
||||
// compress it into the output
|
||||
squish::CompressMasked(source_rgba, mask, target_block, flags);
|
||||
// advance
|
||||
target_block += 16;
|
||||
}
|
||||
}
|
||||
} // squishCompressImage
|
||||
|
||||
namespace GE
|
||||
{
|
||||
// ----------------------------------------------------------------------------
|
||||
GECompressorS3TCBC3::GECompressorS3TCBC3(uint8_t* texture, unsigned channels,
|
||||
const irr::core::dimension2d<irr::u32>& size,
|
||||
bool normal_map)
|
||||
: GEMipmapGenerator(texture, channels, size, normal_map)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<GEImageLevel> compressed_levels;
|
||||
m_compressed_data = new uint8_t[total_size];
|
||||
uint8_t* cur_offset = m_compressed_data;
|
||||
const unsigned tc_flag = squish::kDxt5 | squish::kColourRangeFit;
|
||||
|
||||
for (GEImageLevel& level : m_levels)
|
||||
{
|
||||
squishCompressImage((uint8_t*)level.m_data, level.m_dim.Width,
|
||||
level.m_dim.Height, level.m_dim.Width * channels,
|
||||
cur_offset, tc_flag);
|
||||
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);
|
||||
} // GECompressorS3TCBC3
|
||||
|
||||
}
|
23
lib/graphics_engine/src/ge_compressor_s3tc_bc3.hpp
Normal file
23
lib/graphics_engine/src/ge_compressor_s3tc_bc3.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef HEADER_GE_COMPRESSOR_S3TC_BC3_HPP
|
||||
#define HEADER_GE_COMPRESSOR_S3TC_BC3_HPP
|
||||
|
||||
#include "ge_mipmap_generator.hpp"
|
||||
|
||||
namespace GE
|
||||
{
|
||||
class GECompressorS3TCBC3 : public GEMipmapGenerator
|
||||
{
|
||||
private:
|
||||
uint8_t* m_compressed_data;
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
GECompressorS3TCBC3(uint8_t* texture, unsigned channels,
|
||||
const irr::core::dimension2d<irr::u32>& size,
|
||||
bool normal_map);
|
||||
// ------------------------------------------------------------------------
|
||||
~GECompressorS3TCBC3() { delete [] m_compressed_data; }
|
||||
}; // GECompressorS3TCBC3
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@ class GEMipmapGenerator
|
||||
private:
|
||||
imMipmapCascade* m_cascade;
|
||||
|
||||
protected:
|
||||
unsigned m_mipmap_sizes;
|
||||
|
||||
std::vector<GEImageLevel> m_levels;
|
||||
@ -87,7 +88,7 @@ public:
|
||||
m_levels[i].m_data = m_cascade->mipmap[i];
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
~GEMipmapGenerator() { freeMipmapCascade(); }
|
||||
virtual ~GEMipmapGenerator() { freeMipmapCascade(); }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned getMipmapSizes() const { return m_mipmap_sizes; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -26,6 +26,7 @@ uint32_t g_max_sampler_supported = 0;
|
||||
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;
|
||||
} // GEVulkanFeatures
|
||||
|
||||
// ============================================================================
|
||||
@ -65,6 +66,10 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
|
||||
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
|
||||
VK_FORMAT_R8_UNORM, &format_properties);
|
||||
g_supports_r8_blit = format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
||||
format_properties = {};
|
||||
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
|
||||
VK_FORMAT_BC3_UNORM_BLOCK, &format_properties);
|
||||
g_supports_s3tc_bc3 = format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||
|
||||
uint32_t extension_count;
|
||||
vkEnumerateDeviceExtensionProperties(vk->getPhysicalDevice(), NULL,
|
||||
@ -182,6 +187,9 @@ void GEVulkanFeatures::printStats()
|
||||
os::Printer::log(
|
||||
"Vulkan supports compute in main queue",
|
||||
g_supports_compute_in_main_queue ? "true" : "false");
|
||||
os::Printer::log(
|
||||
"Vulkan supports s3 texture compression (bc3, dxt5)",
|
||||
g_supports_s3tc_bc3 ? "true" : "false");
|
||||
os::Printer::log(
|
||||
"Vulkan descriptor indexes can be dynamically non-uniform",
|
||||
g_supports_non_uniform_indexing ? "true" : "false");
|
||||
@ -261,4 +269,10 @@ bool GEVulkanFeatures::supportsComputeInMainQueue()
|
||||
return g_supports_compute_in_main_queue;
|
||||
} // supportsComputeInMainQueue
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GEVulkanFeatures::supportsS3TCBC3()
|
||||
{
|
||||
return g_supports_s3tc_bc3;
|
||||
} // supportsS3TCBC3
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ bool supportsMultiDrawIndirect();
|
||||
bool supportsBaseVertexRendering();
|
||||
// ----------------------------------------------------------------------------
|
||||
bool supportsComputeInMainQueue();
|
||||
// ----------------------------------------------------------------------------
|
||||
bool supportsS3TCBC3();
|
||||
}; // GEVulkanFeatures
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ge_main.hpp"
|
||||
#include "ge_mipmap_generator.hpp"
|
||||
#include "ge_compressor_s3tc_bc3.hpp"
|
||||
#include "ge_texture.hpp"
|
||||
#include "ge_vulkan_command_loader.hpp"
|
||||
#include "ge_vulkan_features.hpp"
|
||||
@ -121,8 +122,20 @@ bool GEVulkanTexture::createTextureImage(uint8_t* texture_data,
|
||||
{
|
||||
const bool normal_map = (std::string(NamedPath.getPtr()).find(
|
||||
"_Normal.") != std::string::npos);
|
||||
mipmap_generator = new GEMipmapGenerator(texture_data, channels,
|
||||
m_size, normal_map);
|
||||
bool texture_compression = getGEConfig()->m_texture_compression;
|
||||
if (texture_compression && GEVulkanFeatures::supportsS3TCBC3())
|
||||
{
|
||||
image_size = get4x4CompressedTextureSize(m_size.Width,
|
||||
m_size.Height);
|
||||
m_internal_format = VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
mipmap_generator = new GECompressorS3TCBC3(texture_data, channels,
|
||||
m_size, normal_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
mipmap_generator = new GEMipmapGenerator(texture_data, channels,
|
||||
m_size, normal_map);
|
||||
}
|
||||
mipmap_data_size = mipmap_generator->getMipmapSizes();
|
||||
}
|
||||
|
||||
|
@ -712,54 +712,9 @@ void SPTexture::generateHQMipmap(void* in,
|
||||
#endif
|
||||
} // generateHQMipmap
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SPTexture::squishCompressImage(uint8_t* rgba, int width, int height,
|
||||
int pitch, void* blocks, unsigned flags)
|
||||
{
|
||||
#if !(defined(SERVER_ONLY) || defined(MOBILE_STK))
|
||||
// This function is copied from CompressImage in libsquish to avoid omp
|
||||
// if enabled by shared libsquish, because we are already using
|
||||
// multiple thread
|
||||
for (int y = 0; y < height; y += 4)
|
||||
{
|
||||
// initialise the block output
|
||||
uint8_t* target_block = reinterpret_cast<uint8_t*>(blocks);
|
||||
target_block += ((y >> 2) * ((width + 3) >> 2)) * 16;
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
// build the 4x4 block of pixels
|
||||
uint8_t source_rgba[16 * 4];
|
||||
uint8_t* target_pixel = source_rgba;
|
||||
int mask = 0;
|
||||
for (int py = 0; py < 4; py++)
|
||||
{
|
||||
for (int px = 0; px < 4; px++)
|
||||
{
|
||||
// get the source pixel in the image
|
||||
int sx = x + px;
|
||||
int sy = y + py;
|
||||
// enable if we're in the image
|
||||
if (sx < width && sy < height)
|
||||
{
|
||||
// copy the rgba value
|
||||
uint8_t* source_pixel = rgba + pitch * sy + 4 * sx;
|
||||
memcpy(target_pixel, source_pixel, 4);
|
||||
// enable this pixel
|
||||
mask |= (1 << (4 * py + px));
|
||||
}
|
||||
// advance to the next pixel
|
||||
target_pixel += 4;
|
||||
}
|
||||
}
|
||||
// compress it into the output
|
||||
squish::CompressMasked(source_rgba, mask, target_block, flags);
|
||||
// advance
|
||||
target_block += 16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // squishCompressImage
|
||||
|
||||
// ============================================================================
|
||||
extern "C" void squishCompressImage(uint8_t* rgba, int width, int height,
|
||||
int pitch, void* blocks, unsigned flags);
|
||||
// ----------------------------------------------------------------------------
|
||||
std::vector<std::pair<core::dimension2du, unsigned> >
|
||||
SPTexture::compressTexture(std::shared_ptr<video::IImage>& image)
|
||||
|
@ -38,6 +38,10 @@ class Material;
|
||||
|
||||
using namespace irr;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
extern "C" void squishCompressImage(uint8_t* rgba, int width, int height,
|
||||
int pitch, void* blocks, unsigned flags);
|
||||
|
||||
namespace SP
|
||||
{
|
||||
|
||||
@ -58,9 +62,6 @@ private:
|
||||
|
||||
const bool m_undo_srgb;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void squishCompressImage(uint8_t* rgba, int width, int height, int pitch,
|
||||
void* blocks, unsigned flags);
|
||||
// ------------------------------------------------------------------------
|
||||
void generateHQMipmap(void* in,
|
||||
const std::vector<std::pair<core::dimension2du,
|
||||
|
Loading…
Reference in New Issue
Block a user