Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ option(SOURCEPP_USE_VCRYPTPP "Build vcryptpp library" ${SOURC
option(SOURCEPP_USE_VPKPP "Build vpkpp library" ${SOURCEPP_LIBS_START_ENABLED})
option(SOURCEPP_USE_VTFPP "Build vtfpp library" ${SOURCEPP_LIBS_START_ENABLED})

option(SOURCEPP_BUILD_BENCHMARKS "Build benchmarks for supported libraries" OFF)
option(SOURCEPP_BUILD_C_WRAPPERS "Build C wrappers for supported libraries" OFF)
option(SOURCEPP_BUILD_WITH_OPENCL "Build with support for GPU compute" OFF)
option(SOURCEPP_BUILD_WITH_TBB "Build with support for std::execution" OFF)
option(SOURCEPP_BUILD_TESTS "Build tests for supported libraries" OFF)
option(SOURCEPP_BUILD_WIN7_COMPAT "Build with Windows 7 compatibility" OFF)
option(SOURCEPP_BUILD_BENCHMARKS "Build benchmarks for supported libraries" OFF)
option(SOURCEPP_BUILD_C_WRAPPERS "Build C wrappers for supported libraries" OFF)
option(SOURCEPP_BUILD_WITH_OPENCL "Build with support for GPU compute" OFF)
option(SOURCEPP_BUILD_WITH_TBB "Build with support for std::execution" OFF)
option(SOURCEPP_BUILD_WITH_THREADS "Build with support for std::thread" ON)
option(SOURCEPP_BUILD_TESTS "Build tests for supported libraries" OFF)
option(SOURCEPP_BUILD_WIN7_COMPAT "Build with Windows 7 compatibility" OFF)

option(SOURCEPP_LINK_STATIC_MSVC_RUNTIME "Link to static MSVC runtime library" OFF)

Expand Down Expand Up @@ -145,5 +146,5 @@ endif()
# Print options
print_options(OPTIONS
USE_BSPPP USE_DMXPP USE_GAMEPP USE_KVPP USE_MDLPP USE_STEAMPP USE_TOOLPP USE_VCRYPTPP USE_VPKPP USE_VTFPP
BUILD_BENCHMARKS BUILD_C_WRAPPERS BUILD_WITH_OPENCL BUILD_WITH_TBB BUILD_TESTS BUILD_WIN7_COMPAT
BUILD_BENCHMARKS BUILD_C_WRAPPERS BUILD_WITH_OPENCL BUILD_WITH_TBB BUILD_WITH_THREADS BUILD_TESTS BUILD_WIN7_COMPAT
LINK_STATIC_MSVC_RUNTIME)
62 changes: 62 additions & 0 deletions bench/vtfpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,66 @@ void BM_vtflib_create_2048x2048_compressed(benchmark::State& state) {
}
BENCHMARK(BM_vtflib_create_2048x2048_compressed);

void BM_vtfpp_compute_reflectivity_2048x2048_1(benchmark::State& state) {
VTF vtf{ASSET_ROOT "vtfpp/fmt/RGBA8888.vtf"};
vtf.setSize(2048, 2048, ImageConversion::ResizeFilter::BILINEAR);

for ([[maybe_unused]] auto _ : state) {
vtf.computeReflectivity();
}
}
BENCHMARK(BM_vtfpp_compute_reflectivity_2048x2048_1);

void BM_vtflib_compute_reflectivity_2048x2048_1(benchmark::State& state) {
VTFLib::CVTFFile vtf;
vtf.Create(2048, 2048, 1, 1, 1, IMAGE_FORMAT_RGBA8888, true, true, true);

for ([[maybe_unused]] auto _: state) {
benchmark::DoNotOptimize(vtf.ComputeReflectivity());
}
}
BENCHMARK(BM_vtflib_compute_reflectivity_2048x2048_1);

void BM_vtfpp_compute_reflectivity_2048x2048_8(benchmark::State& state) {
VTF vtf{ASSET_ROOT "vtfpp/fmt/RGBA8888.vtf"};
vtf.setFrameCount(8);
vtf.setSize(2048, 2048, ImageConversion::ResizeFilter::BILINEAR);

for ([[maybe_unused]] auto _ : state) {
vtf.computeReflectivity();
}
}
BENCHMARK(BM_vtfpp_compute_reflectivity_2048x2048_8);

void BM_vtflib_compute_reflectivity_2048x2048_8(benchmark::State& state) {
VTFLib::CVTFFile vtf;
vtf.Create(2048, 2048, 8, 1, 1, IMAGE_FORMAT_RGBA8888, true, true, true);

for ([[maybe_unused]] auto _: state) {
benchmark::DoNotOptimize(vtf.ComputeReflectivity());
}
}
BENCHMARK(BM_vtflib_compute_reflectivity_2048x2048_8);

void BM_vtfpp_compute_reflectivity_2048x2048_64(benchmark::State& state) {
VTF vtf{ASSET_ROOT "vtfpp/fmt/RGBA8888.vtf"};
vtf.setFrameCount(64);
vtf.setSize(2048, 2048, ImageConversion::ResizeFilter::BILINEAR);

for ([[maybe_unused]] auto _ : state) {
vtf.computeReflectivity();
}
}
BENCHMARK(BM_vtfpp_compute_reflectivity_2048x2048_64);

void BM_vtflib_compute_reflectivity_2048x2048_64(benchmark::State& state) {
VTFLib::CVTFFile vtf;
vtf.Create(2048, 2048, 64, 1, 1, IMAGE_FORMAT_RGBA8888, true, true, true);

for ([[maybe_unused]] auto _: state) {
benchmark::DoNotOptimize(vtf.ComputeReflectivity());
}
}
BENCHMARK(BM_vtflib_compute_reflectivity_2048x2048_64);

} // namespace
37 changes: 30 additions & 7 deletions bench/vtfpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from _bench import get_lib_name, find_bench_executable, read_data


def create_plot_conversions_256x256_to_rgba8888(exe: str, data: pd.DataFrame) -> None:
df = data[~data['name'].apply(lambda name: ('convert_256x256' not in name and 'to' not in name) or ('DXT' in name or 'BC' in name or 'ATI' in name))]
def create_plot_conversions_to_rgba8888(exe: str, data: pd.DataFrame) -> None:
df = data[data['name'].apply(lambda name: 'convert' in name and 'to' in name and 'DXT' not in name and 'BC' not in name and 'ATI' not in name)]

df['library'] = df['name'].apply(lambda x: 'vtfpp' if 'vtfpp' in x else 'vtflib')
df['benchmark'] = df['name'].apply(lambda x: x.split('_')[-3])
Expand All @@ -28,8 +28,8 @@ def create_plot_conversions_256x256_to_rgba8888(exe: str, data: pd.DataFrame) ->
plt.savefig(str(pathlib.Path(exe).parent / (get_lib_name(__file__) + '_bench_conversions_256x256_to_rgba8888.png')))


def create_plot_creation_2048x2048(exe: str, data: pd.DataFrame) -> None:
df = data[~data['name'].apply(lambda name: 'create_2048x2048' not in name)]
def create_plot_creation(exe: str, data: pd.DataFrame) -> None:
df = data[data['name'].apply(lambda name: 'create' in name)]

df['library'] = df['name'].apply(lambda x: 'vtfpp' if 'vtfpp' in x else 'vtflib')
df['benchmark'] = df['name'].apply(lambda x: x.split('_')[-1].capitalize())
Expand All @@ -40,7 +40,7 @@ def create_plot_creation_2048x2048(exe: str, data: pd.DataFrame) -> None:
df_merged = df_vtfpp[['real_time']].join(df_vtflib[['real_time']], lsuffix='_vtfpp', rsuffix='_vtflib')

df_merged.plot(kind='bar', figsize=(10, 6))
plt.title('VTFPP - Creation (2048x2048)')
plt.title('VTFPP - Creation (2048x2048 RGBA8888)')
plt.xlabel('Type')
plt.ylabel('Time (ms)')
plt.xticks(rotation=45, ha='right')
Expand All @@ -50,14 +50,37 @@ def create_plot_creation_2048x2048(exe: str, data: pd.DataFrame) -> None:
plt.savefig(str(pathlib.Path(exe).parent / (get_lib_name(__file__) + '_bench_creation_2048x2048_rgba8888.png')))


def create_plot_compute_reflectivity(exe: str, data: pd.DataFrame) -> None:
df = data[data['name'].apply(lambda name: 'compute_reflectivity' in name)]

df['library'] = df['name'].apply(lambda x: 'vtfpp' if 'vtfpp' in x else 'vtflib')
df['benchmark'] = df['name'].apply(lambda x: x.split('_')[-1] + ' Frame' + ('s' if int(x.split('_')[-1]) > 1 else ''))
df['real_time'] = df['real_time'].apply(lambda x: x / 1000000)

df_vtfpp = df[df['library'] == 'vtfpp'].set_index('benchmark')
df_vtflib = df[df['library'] == 'vtflib'].set_index('benchmark')
df_merged = df_vtfpp[['real_time']].join(df_vtflib[['real_time']], lsuffix='_vtfpp', rsuffix='_vtflib')

df_merged.plot(kind='bar', figsize=(10, 6))
plt.title('VTFPP - Compute Reflectivity (2048x2048 RGBA8888)')
plt.xlabel('Type')
plt.ylabel('Time (ms)')
plt.xticks(rotation=45, ha='right')
plt.legend(['vtfpp', 'vtflib'])
plt.tight_layout()

plt.savefig(str(pathlib.Path(exe).parent / (get_lib_name(__file__) + '_bench_compute_reflectivity_2048x2048_rgba8888.png')))


def main() -> None:
exe = find_bench_executable(__file__)
if not exe:
exit(1)
data = read_data(exe, __file__)

create_plot_conversions_256x256_to_rgba8888(exe, data)
create_plot_creation_2048x2048(exe, data)
create_plot_conversions_to_rgba8888(exe, data)
create_plot_creation(exe, data)
create_plot_compute_reflectivity(exe, data)


if __name__ == '__main__':
Expand Down
18 changes: 18 additions & 0 deletions ext/_ext.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,21 @@ function(sourcepp_add_tbb TARGET)
endif()
endif()
endfunction()


# Threads
if(SOURCEPP_BUILD_WITH_THREADS)
set(CMAKE_THREAD_PREFER_PTHREAD ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
if(NOT Threads_FOUND)
set(SOURCEPP_BUILD_WITH_THREADS OFF CACHE INTERNAL "" FORCE)
endif()
endif()

function(sourcepp_add_threads TARGET)
if(SOURCEPP_BUILD_WITH_THREADS)
target_compile_definitions(${TARGET} PRIVATE SOURCEPP_BUILD_WITH_THREADS)
target_link_libraries(${TARGET} PRIVATE Threads::Threads)
endif()
endfunction()
61 changes: 46 additions & 15 deletions src/vtfpp/VTF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include <cstring>
#include <unordered_map>

#ifdef SOURCEPP_BUILD_WITH_THREADS
#include <future>
#endif

#include <BufferStream.h>
#include <miniz.h>

Expand Down Expand Up @@ -614,33 +618,60 @@ void VTF::setReflectivity(sourcepp::math::Vec3f newReflectivity) {
}

void VTF::computeReflectivity() {
const auto faceCount = this->getFaceCount();
this->reflectivity = {};
for (int j = 0; j < this->frameCount; j++) {
static constexpr auto getReflectivityForFrame = [](VTF& vtf, uint16_t frame, uint8_t faceCount) {
static constexpr auto getReflectivityForPixel = [](ImagePixel::RGBA8888* pixel) -> math::Vec3f {
// http://markjstock.org/doc/gsd_talk_11_notes.pdf page 11
math::Vec3f ref{static_cast<float>(pixel->r), static_cast<float>(pixel->g), static_cast<float>(pixel->b)};
ref /= 255.f * 0.9f;
ref[0] *= ref[0];
ref[1] *= ref[1];
ref[2] *= ref[2];
return ref;
};

math::Vec3f facesOut{};
for (int k = 0; k < faceCount; k++) {
math::Vec3f slicesOut{};
for (int l = 0; l < this->sliceCount; l++) {
auto rgba8888Data = this->getImageDataAsRGBA8888(0, j, k, l);

for (int l = 0; l < vtf.getSliceCount(); l++) {
auto rgba8888Data = vtf.getImageDataAsRGBA8888(0, frame, k, l);
math::Vec3f sliceOut{};
for (uint64_t i = 0; i < rgba8888Data.size(); i += 4) {
// http://markjstock.org/doc/gsd_talk_11_notes.pdf page 11
math::Vec3f pixel{static_cast<float>(rgba8888Data[i]), static_cast<float>(rgba8888Data[i+1]), static_cast<float>(rgba8888Data[i+2])};
pixel /= 255.f * 0.9f;
pixel[0] *= pixel[0];
pixel[1] *= pixel[1];
pixel[2] *= pixel[2];
sliceOut += pixel;
sliceOut += getReflectivityForPixel(reinterpret_cast<ImagePixel::RGBA8888*>(rgba8888Data.data() + i));
}
sliceOut /= rgba8888Data.size() / (ImageFormatDetails::bpp(ImageFormat::RGBA8888) / 8);
slicesOut += sliceOut;
}
facesOut += slicesOut / this->sliceCount;
facesOut += slicesOut / vtf.getSliceCount();
}
return facesOut / faceCount;
};

const auto faceCount = this->getFaceCount();

#ifdef SOURCEPP_BUILD_WITH_THREADS
if (this->frameCount > 1) {
this->reflectivity = {};
std::vector<std::future<math::Vec3f>> futures;
futures.reserve(this->frameCount);
for (int i = 0; i < this->frameCount; i++) {
futures.push_back(std::async(std::launch::async, [this, i, faceCount] {
return getReflectivityForFrame(*this, i, faceCount);
}));
}
for (auto& future : futures) {
this->reflectivity += future.get();
}
this->reflectivity += facesOut / faceCount;
this->reflectivity /= this->frameCount;
} else {
this->reflectivity = getReflectivityForFrame(*this, 0, faceCount) / this->frameCount;
}
#else
this->reflectivity = {};
for (int i = 0; i < this->frameCount; i++) {
this->reflectivity += getReflectivityForFrame(*this, i, faceCount);
}
this->reflectivity /= this->frameCount;
#endif
}

float VTF::getBumpMapScale() const {
Expand Down
1 change: 1 addition & 0 deletions src/vtfpp/_vtfpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ add_pretty_parser(vtfpp
target_include_directories(vtfpp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/ext/stb/include")

sourcepp_add_tbb(vtfpp)
sourcepp_add_threads(vtfpp)
target_link_compressonator(vtfpp)