Support threads and threads+SIMD in WebP2
This commit is contained in:

committed by
Ingvar Stepanyan

parent
24d241564e
commit
a951096aaa
1
codecs/avif/enc/avif_enc_mt.d.ts
vendored
1
codecs/avif/enc/avif_enc_mt.d.ts
vendored
@ -1,2 +1 @@
|
||||
export * from './avif_enc';
|
||||
export { default } from './avif_enc';
|
||||
|
@ -1,20 +1,30 @@
|
||||
CODEC_URL = https://chromium.googlesource.com/codecs/libwebp2/+archive/c90b5b476004c9a98731ae1c175cebab5de50fbf.tar.gz
|
||||
CODEC_DIR = node_modules/wp2
|
||||
CODEC_BUILD_DIR := $(CODEC_DIR)/.build
|
||||
CODEC_OUT := $(CODEC_BUILD_DIR)/libwebp2.a
|
||||
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
|
||||
CODEC_BASELINE_BUILD_DIR := $(CODEC_BUILD_ROOT)/baseline
|
||||
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt
|
||||
CODEC_MT_SIMD_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt-simd
|
||||
|
||||
OUT_JS = enc/wp2_enc.js dec/wp2_dec.js
|
||||
OUT_WASM = $(OUT_JS:.js=.wasm)
|
||||
OUT_JS = enc/wp2_enc.js enc/wp2_enc_mt.js enc/wp2_enc_mt_simd.js dec/wp2_dec.js
|
||||
OUT_WASM := $(OUT_JS:.js=.wasm)
|
||||
OUT_WORKER := $(OUT_JS:.js=.worker.js)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OUT_JS)
|
||||
|
||||
%.js: %.cpp $(CODEC_OUT)
|
||||
$(CXX) \
|
||||
-I $(CODEC_DIR) \
|
||||
${CXXFLAGS} \
|
||||
${LDFLAGS} \
|
||||
# Define dependencies for all variations of build artifacts.
|
||||
$(filter enc/%,$(OUT_JS)): enc/wp2_enc.o
|
||||
$(filter dec/%,$(OUT_JS)): dec/wp2_dec.o
|
||||
enc/wp2_enc.js dec/wp2_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp2.a
|
||||
enc/wp2_enc_mt.js: $(CODEC_MT_BUILD_DIR)/libwebp2.a
|
||||
enc/wp2_enc_mt_simd.js: $(CODEC_MT_SIMD_BUILD_DIR)/libwebp2.a
|
||||
# Link multithreaded builds with -pthread.
|
||||
enc/wp2_enc_mt.js enc/wp2_enc_mt_simd.js: LDFLAGS+=-pthread
|
||||
|
||||
$(OUT_JS):
|
||||
$(LD) \
|
||||
$(LDFLAGS) \
|
||||
--bind \
|
||||
--closure 1 \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
@ -26,25 +36,43 @@ all: $(OUT_JS)
|
||||
-o $@ \
|
||||
$+
|
||||
|
||||
$(CODEC_OUT): $(CODEC_BUILD_DIR)/Makefile
|
||||
cd $(CODEC_BUILD_DIR) && \
|
||||
$(MAKE)
|
||||
%.o: %.cpp $(CODEC_DIR)/CMakeLists.txt
|
||||
$(CXX) \
|
||||
$(CXXFLAGS) \
|
||||
-I $(CODEC_DIR) \
|
||||
-o $@ \
|
||||
$<
|
||||
|
||||
$(CODEC_BUILD_DIR)/Makefile: $(CODEC_DIR)/CMakeLists.txt
|
||||
mkdir -p $(CODEC_BUILD_DIR)
|
||||
cd $(CODEC_BUILD_DIR) && \
|
||||
%/libwebp2.a: %/Makefile
|
||||
$(MAKE) -C $(@D)
|
||||
|
||||
# Disable SIMD for non-SIMD builds.
|
||||
$(CODEC_BASELINE_BUILD_DIR)/Makefile $(CODEC_MT_BUILD_DIR)/Makefile: CMAKE_FLAGS+=-DWP2_ENABLE_SIMD=0
|
||||
|
||||
# Disable threads for the single-threaded build.
|
||||
$(CODEC_BASELINE_BUILD_DIR)/Makefile: CMAKE_FLAGS+=-DCMAKE_DISABLE_FIND_PACKAGE_Threads=1
|
||||
|
||||
# The line below should be unnecessary in the future.
|
||||
# See https://github.com/emscripten-core/emscripten/issues/12714 for -msimd128.
|
||||
# See https://github.com/emscripten-core/emscripten/issues/12746 for -msse4.2.
|
||||
$(CODEC_MT_SIMD_BUILD_DIR)/Makefile: CXXFLAGS+=-msimd128 -msse4.2
|
||||
|
||||
%/Makefile: $(CODEC_DIR)/CMakeLists.txt
|
||||
emcmake cmake \
|
||||
-DWP2_ENABLE_SIMD=0 \
|
||||
$(CMAKE_FLAGS) \
|
||||
-DWP2_BUILD_TESTS=0 \
|
||||
-DWP2_ENABLE_TESTS=0 \
|
||||
-DWP2_BUILD_EXAMPLES=0 \
|
||||
-DWP2_BUILD_EXTRAS=0 \
|
||||
../
|
||||
-B $(@D) \
|
||||
$(<D)
|
||||
|
||||
$(CODEC_DIR)/CMakeLists.txt:
|
||||
mkdir -p $(CODEC_DIR)
|
||||
curl -sL $(CODEC_URL) | tar xz -C $(CODEC_DIR)
|
||||
|
||||
clean:
|
||||
$(RM) $(OUT_JS) $(OUT_WASM)
|
||||
$(MAKE) -C $(CODEC_BUILD_DIR) clean
|
||||
$(RM) $(OUT_JS) $(OUT_WASM) $(OUT_WORKER)
|
||||
$(MAKE) -C $(CODEC_BASELINE_BUILD_DIR) clean
|
||||
$(MAKE) -C $(CODEC_MT_BUILD_DIR) clean
|
||||
$(MAKE) -C $(CODEC_MT_SIMD_BUILD_DIR) clean
|
||||
|
1185
codecs/wp2/dec/wp2_dec.js
generated
1185
codecs/wp2/dec/wp2_dec.js
generated
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,5 +1,6 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include <emscripten/threading.h>
|
||||
#include <cstdio>
|
||||
#include "src/wp2/encode.h"
|
||||
|
||||
@ -42,6 +43,7 @@ val encode(std::string image_in, int image_width, int image_height, WP2Options o
|
||||
}
|
||||
|
||||
WP2::MemoryWriter memory_writer;
|
||||
config.thread_level = emscripten_num_logical_cores() - 1;
|
||||
status = WP2::Encode(src, &memory_writer, config);
|
||||
if (status != WP2_STATUS_OK) {
|
||||
return val::null();
|
||||
|
1277
codecs/wp2/enc/wp2_enc.js
generated
1277
codecs/wp2/enc/wp2_enc.js
generated
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -44,6 +44,5 @@ export default async function encode(
|
||||
|
||||
if (!result) throw new Error('Encoding error');
|
||||
|
||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||
return result.buffer as ArrayBuffer;
|
||||
return result.buffer;
|
||||
}
|
||||
|
@ -10,24 +10,56 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import wp2Encoder, { WP2Module } from 'codecs/wp2/enc/wp2_enc';
|
||||
import wasmUrl from 'url:codecs/wp2/enc/wp2_enc.wasm';
|
||||
import { initEmscriptenModule } from 'features/worker-utils';
|
||||
import type { WP2Module } from 'codecs/wp2/enc/wp2_enc';
|
||||
import type { EncodeOptions } from '../shared/meta';
|
||||
|
||||
import { initEmscriptenModule } from 'features/worker-utils';
|
||||
import { threads, simd } from 'wasm-feature-detect';
|
||||
|
||||
import wasmUrl from 'url:codecs/wp2/enc/wp2_enc.wasm';
|
||||
|
||||
import wasmUrlWithMT from 'url:codecs/wp2/enc/wp2_enc_mt.wasm';
|
||||
import workerUrl from 'omt:codecs/wp2/enc/wp2_enc_mt.worker.js';
|
||||
|
||||
import wasmUrlWithMTAndSIMD from 'url:codecs/wp2/enc/wp2_enc_mt_simd.wasm';
|
||||
import workerUrlWithSIMD from 'omt:codecs/wp2/enc/wp2_enc_mt_simd.worker.js';
|
||||
|
||||
let emscriptenModule: Promise<WP2Module>;
|
||||
|
||||
async function init() {
|
||||
if (await threads()) {
|
||||
if (await simd()) {
|
||||
const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt_simd');
|
||||
return initEmscriptenModule(
|
||||
wp2Encoder.default,
|
||||
wasmUrlWithMTAndSIMD,
|
||||
workerUrlWithSIMD,
|
||||
);
|
||||
}
|
||||
const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt');
|
||||
return initEmscriptenModule(
|
||||
wp2Encoder.default,
|
||||
wasmUrlWithMT,
|
||||
workerUrl,
|
||||
);
|
||||
}
|
||||
const wp2Encoder = await import('codecs/wp2/enc/wp2_enc');
|
||||
return initEmscriptenModule(
|
||||
wp2Encoder.default,
|
||||
wasmUrl,
|
||||
);
|
||||
}
|
||||
|
||||
export default async function encode(
|
||||
data: ImageData,
|
||||
options: EncodeOptions,
|
||||
): Promise<ArrayBuffer> {
|
||||
if (!emscriptenModule) {
|
||||
emscriptenModule = initEmscriptenModule(wp2Encoder, wasmUrl);
|
||||
}
|
||||
if (!emscriptenModule) emscriptenModule = init();
|
||||
|
||||
const module = await emscriptenModule;
|
||||
const result = module.encode(data.data, data.width, data.height, options);
|
||||
|
||||
if (!result) throw new Error('Encoding error.');
|
||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||
return result.buffer as ArrayBuffer;
|
||||
|
||||
return result.buffer;
|
||||
}
|
||||
|
Reference in New Issue
Block a user