Skip to content

Commit

Permalink
add qoi-fu_cxx
Browse files Browse the repository at this point in the history
  • Loading branch information
wx257osn2 committed Feb 4, 2024
1 parent 61c5c0f commit 34fb816
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 22 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "rapid-qoi/rapid-qoi"]
path = rapid-qoi/rapid-qoi
url = https://github.com/zakarumych/rapid-qoi
[submodule "qoi-fu/qoi-fu"]
path = qoi-fu/qoi-fu
url = https://github.com/pfusik/qoi-fu
23 changes: 23 additions & 0 deletions LICENSES/qoi-fu.LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// QOI.fu - encoder and decoder of the "Quite OK Image" format
//
// Copyright (C) 2021-2024 Piotr Fusik
//
// MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
all: libqoi libqoixx libqoi_rust librapid_qoi benchmark
all: libqoi libqoixx libqoi_rust librapid_qoi libqoi_fu_cxx benchmark

benchmark: benchmark/bin/benchmark

Expand All @@ -10,21 +10,25 @@ libqoi_rust: qoi-rust/target/release/libqoi_rust.a

librapid_qoi: rapid-qoi/target/release/librapid_qoi.a

libqoi_fu_cxx: qoi-fu/libqoi_fu_cxx.a

clean:
cd qoi && make clean && cd ..
cd qoixx && make clean && cd ..
cd qoi-rust && cargo clean && cd ..
cd rapid-qoi && cargo clean && cd ..
cd qoi-fu && make clean && cd ..
cd benchmark && make clean && cd ..

install_libraries: libqoi libqoixx libqoi_rust librapid_qoi
install_libraries: libqoi libqoixx libqoi_rust librapid_qoi libqoi_fu_cxx
cp qoi/qoi/qoi.h benchmark/include
cp qoi/libqoi.a benchmark/lib
cp qoixx/libqoixx.a benchmark/lib
cp qoi-rust/target/release/libqoi_rust.a benchmark/lib
cp rapid-qoi/target/release/librapid_qoi.a benchmark/lib
cp qoi-fu/libqoi_fu_cxx.a benchmark/lib

.PHONY: all benchmark libqoi libqoixx libqoi_rust librapid_qoi install_libraries clean
.PHONY: all benchmark libqoi libqoixx libqoi_rust librapid_qoi libqoi_fu_cxx install_libraries clean

qoi/libqoi.a: qoi/qoi/qoi.h qoi/qoi.c qoi/Makefile
cd qoi && make
Expand All @@ -38,5 +42,8 @@ qoi-rust/target/release/libqoi_rust.a: qoi-rust/src/lib.rs qoi-rust/Cargo.toml
rapid-qoi/target/release/librapid_qoi.a: rapid-qoi/src/lib.rs rapid-qoi/Cargo.toml rapid-qoi/rapid-qoi/src/decode.rs rapid-qoi/rapid-qoi/src/encode.rs rapid-qoi/rapid-qoi/src/lib.rs
cd rapid-qoi && cargo build --release

qoi-fu/libqoi_fu_cxx.a: qoi-fu/qoi-fu/transpiled/QOI.hpp qoi-fu/qoi-fu/transpiled/QOI.cpp qoi-fu/qoi-fu.cpp qoi-fu/Makefile
cd qoi-fu && make

benchmark/bin/benchmark: install_libraries benchmark/src/qoibench.cpp benchmark/Makefile
cd benchmark && make
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Cross-language benchmark for [QOI](https://github.com/phoboslab/qoi) implementat
- [`qoixx`](https://github.com/wx257osn2/qoixx)
- [`qoi-rust`](https://github.com/aldanor/qoi-rust)
- [`rapid-qoi`](https://github.com/zakarumych/rapid-qoi)
- [`qoi-fu`](https://github.com/pfusik/qoi-fu)
- `qoi-fu_cxx` : implementation transpiled to C++

## Usage

Expand All @@ -22,7 +24,7 @@ Cross-language benchmark for [QOI](https://github.com/phoboslab/qoi) implementat
- On Host
- Prerequisites:
- `gcc` for `qoi`
- `g++` supporting `-std=c++2a` for `qoixx`
- `g++` supporting `-std=c++2a` for `qoixx` and `qoi-fu_cxx`
- `cargo` and Rust toolchains for `qoi-rust` and `rapid-qoi`
- `make`
- ```console
Expand Down
4 changes: 2 additions & 2 deletions benchmark/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ clean:

.PHONY: qoibench clean

bin/qoibench: src/qoibench.cpp include/implementations.hpp include/implementation_macro.hpp lib/libqoi.a lib/libqoixx.a lib/libqoi_rust.a lib/librapid_qoi.a
$(CXX) -std=c++2a -Wall -Wextra -pedantic-errors -O3 -march=native -mtune=native -I .dependencies/stb -I include -o$@ $< -Llib -lqoi -lqoixx -lqoi_rust -lrapid_qoi -pthread -ldl
bin/qoibench: src/qoibench.cpp include/implementations.hpp include/implementation_macro.hpp lib/libqoi.a lib/libqoixx.a lib/libqoi_rust.a lib/librapid_qoi.a lib/libqoi_fu_cxx.a
$(CXX) -std=c++2a -Wall -Wextra -pedantic-errors -O3 -march=native -mtune=native -I .dependencies/stb -I include -o$@ $< -Llib -lqoi -lqoixx -lqoi_rust -lrapid_qoi -lqoi_fu_cxx -pthread -ldl
12 changes: 7 additions & 5 deletions benchmark/include/implementations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
#include"qoixx.h"
#include"qoi_rust.h"
#include"rapid-qoi.h"
#include"qoi-fu_cxx.h"

#define IMPLEMENTATIONS \
/*(name str, name ident, pixel format of 3ch) */ \
/*("qoi", qoi, rgb) */ \
("qoixx", qoixx, rgb) \
("qoi-rust", qoi_rust, rgb) \
("rapid-qoi", rapid_qoi, rgb) \
/*(name str, name ident, pixel format of 3ch) */ \
/*("qoi", qoi, rgb) */ \
("qoixx", qoixx, rgb) \
("qoi-rust", qoi_rust, rgb) \
("rapid-qoi", rapid_qoi, rgb) \
("qoi-fu_cxx", qoi_fu_cxx, argb_int)

#endif//IMPLEMENTATIONS_HPP_INCLUDED_
19 changes: 19 additions & 0 deletions benchmark/include/qoi-fu_cxx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef QOI_FU_CXX_H_INCLUDED_
#define QOI_FU_CXX_H_INCLUDED_

#define QOI_NO_STDIO
#include "qoi.h"

#ifdef __cplusplus
extern "C" {
#endif

extern void* qoi_fu_cxx_encode(const void* data, const qoi_desc* desc, int* out_len);
extern void* qoi_fu_cxx_decode(const void* data, int size, qoi_desc* desc, int channels);
extern void qoi_fu_cxx_free(void* ptr);

#ifdef __cplusplus
}
#endif

#endif//QOI_FU_CXX_H_INCLUDED_
22 changes: 11 additions & 11 deletions benchmark/src/qoibench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,17 +402,17 @@ static inline benchmark_result_t benchmark_directory(const std::filesystem::path
static inline int help(const char* argv_0, std::ostream& os = std::cout){
os << "Usage: " << argv_0 << " <iterations> <directory> [options...]\n"
"Options:\n"
" --nowarmup .... don't perform a warmup run\n"
" --noverify .... don't verify qoi roundtrip\n"
" --noencode .... don't run encoders\n"
" --nodecode .... don't run decoders\n"
" --norecurse ... don't descend into directories\n"
" --onlytotals .. don't print individual image results\n"
" --nohalt ...... don't stop if some implementation fail validation\n"
" --threads=n ... multithread execution, where n is threads count (default = 1)\n"
" when n = 0 or a value greater than the hardware-supported concurrency,\n"
" the maximum number of parallel threads supported by the hardware\n"
" will be launched.\n"
" --nowarmup ..... don't perform a warmup run\n"
" --noverify ..... don't verify qoi roundtrip\n"
" --noencode ..... don't run encoders\n"
" --nodecode ..... don't run decoders\n"
" --norecurse .... don't descend into directories\n"
" --onlytotals ... don't print individual image results\n"
" --nohalt ....... don't stop if some implementation fail validation\n"
" --threads=n .... multithread execution, where n is threads count (default = 1)\n"
" when n = 0 or a value greater than the hardware-supported concurrency,\n"
" the maximum number of parallel threads supported by the hardware\n"
" will be launched.\n"
HELP(IMPLEMENTATIONS)
"Examples\n"
" ./" << argv_0 << " 10 images/textures/\n"
Expand Down
2 changes: 2 additions & 0 deletions qoi-fu/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*.o
/libqoi_fu_cxx.a
15 changes: 15 additions & 0 deletions qoi-fu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
libqoi_fu_cxx.a: qoi-fu.cpp.o QOI.cpp.o
$(AR) rcs $@ $^

CXX_FLAGS:=-std=c++2a -O3 -march=native -mtune=native -Wall -Wextra -pedantic-errors -DNDEBUG

qoi-fu.cpp.o: qoi-fu.cpp
$(CXX) -c $(CXX_FLAGS) -I qoi-fu/transpiled -o$@ $<

QOI.cpp.o: qoi-fu/transpiled/QOI.cpp
$(CXX) -c $(CXX_FLAGS) -o$@ $<

clean:
$(RM) -f libqoi_fu_cxx.a qoi-fu.cpp.o QOI.cpp.o

.PHONY: clean
1 change: 1 addition & 0 deletions qoi-fu/qoi-fu
Submodule qoi-fu added at 487073
70 changes: 70 additions & 0 deletions qoi-fu/qoi-fu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include"QOI.hpp"
#include<cassert>
#include<stack>

typedef struct{
unsigned int width;
unsigned int height;
unsigned char channels;
unsigned char colorspace;
}qoi_desc;

template<typename Accessor, typename Accessor::type Member>
struct access_private_member{
friend typename Accessor::type get(Accessor){
return Member;
}
};

struct encoder_accessor{
using type = std::shared_ptr<uint8_t[]> QOIEncoder::*;
friend type get(encoder_accessor);
};

struct decoder_accessor{
using type = std::shared_ptr<int[]> QOIDecoder::*;
friend type get(decoder_accessor);
};

template struct access_private_member<encoder_accessor, &QOIEncoder::encoded>;
template struct access_private_member<decoder_accessor, &QOIDecoder::pixels>;

namespace{

thread_local std::stack<std::shared_ptr<void>> qoi_fu_results;

}

extern "C"{

void* qoi_fu_cxx_encode(const void* data, const qoi_desc* desc, int* out_len){
QOIEncoder encoder;
if(!encoder.encode(desc->width, desc->height, static_cast<const int*>(data), desc->channels == 4, desc->colorspace == 1))
return nullptr;
*out_len = encoder.getEncodedSize();
auto result = std::move(encoder.*get(encoder_accessor{}));
const auto ptr = result.get();
qoi_fu_results.push(std::move(result));
return ptr;
}

void* qoi_fu_cxx_decode(const void* data, int size, qoi_desc* desc, int){
QOIDecoder decoder;
if(!decoder.decode(static_cast<const uint8_t*>(data), size))
return nullptr;
desc->width = decoder.getWidth();
desc->height = decoder.getHeight();
desc->channels = decoder.hasAlpha() ? 4 : 3;
desc->colorspace = decoder.isLinearColorspace() ? 1 : 0;
auto result = std::move(decoder.*get(decoder_accessor{}));
const auto ptr = result.get();
qoi_fu_results.push(std::move(result));
return ptr;
}

void qoi_fu_cxx_free([[maybe_unused]] void* ptr){
assert(ptr == qoi_fu_results.top().get());
qoi_fu_results.pop();
}

}

0 comments on commit 34fb816

Please sign in to comment.