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';
|
export { default } from './avif_enc';
|
||||||
|
@ -1,20 +1,30 @@
|
|||||||
CODEC_URL = https://chromium.googlesource.com/codecs/libwebp2/+archive/c90b5b476004c9a98731ae1c175cebab5de50fbf.tar.gz
|
CODEC_URL = https://chromium.googlesource.com/codecs/libwebp2/+archive/c90b5b476004c9a98731ae1c175cebab5de50fbf.tar.gz
|
||||||
CODEC_DIR = node_modules/wp2
|
CODEC_DIR = node_modules/wp2
|
||||||
CODEC_BUILD_DIR := $(CODEC_DIR)/.build
|
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
|
||||||
CODEC_OUT := $(CODEC_BUILD_DIR)/libwebp2.a
|
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_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_WASM := $(OUT_JS:.js=.wasm)
|
||||||
|
OUT_WORKER := $(OUT_JS:.js=.worker.js)
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(OUT_JS)
|
all: $(OUT_JS)
|
||||||
|
|
||||||
%.js: %.cpp $(CODEC_OUT)
|
# Define dependencies for all variations of build artifacts.
|
||||||
$(CXX) \
|
$(filter enc/%,$(OUT_JS)): enc/wp2_enc.o
|
||||||
-I $(CODEC_DIR) \
|
$(filter dec/%,$(OUT_JS)): dec/wp2_dec.o
|
||||||
${CXXFLAGS} \
|
enc/wp2_enc.js dec/wp2_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp2.a
|
||||||
${LDFLAGS} \
|
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 \
|
--bind \
|
||||||
--closure 1 \
|
--closure 1 \
|
||||||
-s ALLOW_MEMORY_GROWTH=1 \
|
-s ALLOW_MEMORY_GROWTH=1 \
|
||||||
@ -26,25 +36,43 @@ all: $(OUT_JS)
|
|||||||
-o $@ \
|
-o $@ \
|
||||||
$+
|
$+
|
||||||
|
|
||||||
$(CODEC_OUT): $(CODEC_BUILD_DIR)/Makefile
|
%.o: %.cpp $(CODEC_DIR)/CMakeLists.txt
|
||||||
cd $(CODEC_BUILD_DIR) && \
|
$(CXX) \
|
||||||
$(MAKE)
|
$(CXXFLAGS) \
|
||||||
|
-I $(CODEC_DIR) \
|
||||||
|
-o $@ \
|
||||||
|
$<
|
||||||
|
|
||||||
$(CODEC_BUILD_DIR)/Makefile: $(CODEC_DIR)/CMakeLists.txt
|
%/libwebp2.a: %/Makefile
|
||||||
mkdir -p $(CODEC_BUILD_DIR)
|
$(MAKE) -C $(@D)
|
||||||
cd $(CODEC_BUILD_DIR) && \
|
|
||||||
|
# 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 \
|
emcmake cmake \
|
||||||
-DWP2_ENABLE_SIMD=0 \
|
$(CMAKE_FLAGS) \
|
||||||
-DWP2_BUILD_TESTS=0 \
|
-DWP2_BUILD_TESTS=0 \
|
||||||
-DWP2_ENABLE_TESTS=0 \
|
-DWP2_ENABLE_TESTS=0 \
|
||||||
-DWP2_BUILD_EXAMPLES=0 \
|
-DWP2_BUILD_EXAMPLES=0 \
|
||||||
-DWP2_BUILD_EXTRAS=0 \
|
-DWP2_BUILD_EXTRAS=0 \
|
||||||
../
|
-B $(@D) \
|
||||||
|
$(<D)
|
||||||
|
|
||||||
$(CODEC_DIR)/CMakeLists.txt:
|
$(CODEC_DIR)/CMakeLists.txt:
|
||||||
mkdir -p $(CODEC_DIR)
|
mkdir -p $(CODEC_DIR)
|
||||||
curl -sL $(CODEC_URL) | tar xz -C $(CODEC_DIR)
|
curl -sL $(CODEC_URL) | tar xz -C $(CODEC_DIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(OUT_JS) $(OUT_WASM)
|
$(RM) $(OUT_JS) $(OUT_WASM) $(OUT_WORKER)
|
||||||
$(MAKE) -C $(CODEC_BUILD_DIR) clean
|
$(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/bind.h>
|
||||||
#include <emscripten/val.h>
|
#include <emscripten/val.h>
|
||||||
|
#include <emscripten/threading.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "src/wp2/encode.h"
|
#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;
|
WP2::MemoryWriter memory_writer;
|
||||||
|
config.thread_level = emscripten_num_logical_cores() - 1;
|
||||||
status = WP2::Encode(src, &memory_writer, config);
|
status = WP2::Encode(src, &memory_writer, config);
|
||||||
if (status != WP2_STATUS_OK) {
|
if (status != WP2_STATUS_OK) {
|
||||||
return val::null();
|
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');
|
if (!result) throw new Error('Encoding error');
|
||||||
|
|
||||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
return result.buffer;
|
||||||
return result.buffer as ArrayBuffer;
|
|
||||||
}
|
}
|
||||||
|
@ -10,24 +10,56 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import wp2Encoder, { WP2Module } from 'codecs/wp2/enc/wp2_enc';
|
import type { 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 { EncodeOptions } from '../shared/meta';
|
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>;
|
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(
|
export default async function encode(
|
||||||
data: ImageData,
|
data: ImageData,
|
||||||
options: EncodeOptions,
|
options: EncodeOptions,
|
||||||
): Promise<ArrayBuffer> {
|
): Promise<ArrayBuffer> {
|
||||||
if (!emscriptenModule) {
|
if (!emscriptenModule) emscriptenModule = init();
|
||||||
emscriptenModule = initEmscriptenModule(wp2Encoder, wasmUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
const module = await emscriptenModule;
|
const module = await emscriptenModule;
|
||||||
const result = module.encode(data.data, data.width, data.height, options);
|
const result = module.encode(data.data, data.width, data.height, options);
|
||||||
|
|
||||||
if (!result) throw new Error('Encoding error.');
|
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