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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# git apply needs the patches as they are stored (LF): with core.autocrlf, a checkout would
# give them CRLF, and one with an empty context line is then "corrupt" and skipped.
*.patch text eol=lf
64 changes: 46 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,18 @@ function(add_tslang_android_app name media)
if (TARGET donut_shaders)
add_dependencies(${name}_apk donut_shaders)
endif()
# What the executable is made to depend on after this (the copies of the media of the samples'
# checkouts: <name>_media and the like), the APK packages too, and `tools/android.py build`
# builds APKs, not executables: taken at the end of the file, when all of it is known. (A
# deferred call's arguments are evaluated when it runs, hence the EVAL.)
cmake_language(EVAL CODE "cmake_language(DEFER CALL add_tslang_apk_dependencies [[${name}]])")
endfunction()

function(add_tslang_apk_dependencies name)
get_target_property(dependencies ${name} MANUALLY_ADDED_DEPENDENCIES)
if (dependencies)
add_dependencies(${name}_apk ${dependencies})
endif()
endfunction()

# The files the examples' .ts files compile in, which their objects have to be rebuilt after: a
Expand Down Expand Up @@ -2639,6 +2651,19 @@ donut_compile_shaders_all_platforms(
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/collision.hlsl
OUTPUT_BASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders/collision
)
# DirectXMath is the Windows SDK's; on Android it is fetched at configure time (DIRECTXMATH_FETCH_TAG;
# headers only, not its CMake project), with core/sal/sal.h for the annotations it uses.
if (ANDROID)
set(DIRECTXMATH_FETCH_TAG "jun2026" CACHE STRING "Git tag of DirectXMath, which collision uses on Android")
FetchContent_Declare(directxmath
GIT_REPOSITORY https://github.com/microsoft/DirectXMath.git
GIT_TAG ${DIRECTXMATH_FETCH_TAG}
GIT_SHALLOW TRUE
SOURCE_SUBDIR Inc)
FetchContent_MakeAvailable(directxmath)
set_source_files_properties(core/directx_collision.cpp PROPERTIES
INCLUDE_DIRECTORIES "${directxmath_SOURCE_DIR}/Inc;${CMAKE_CURRENT_SOURCE_DIR}/core/sal")
endif()
add_tslang_example(collision core/directx_collision.cpp MEDIA fonts)

# Port of NVIDIA's DXR tutorial 14 (Refit, github.com/NVIDIAGameWorks/DxrTutorials): three
Expand Down Expand Up @@ -2901,24 +2926,27 @@ endfunction()
# over a scene of PBRT models (a house, cars, a dragon, a spaceship: the sample's parser, in
# core/pbrt) and procedural grass a compute shader regenerates every frame; a specular path tracer
# makes the G-buffer. Its assets (~140 MB) are the sample's, from DIRECTX_GRAPHICS_SAMPLES_DIR.
# Ray tracing pipelines: D3D12 or Vulkan.
file(GLOB DENOISED_RTAO_SHADER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/denoised_rtao/*)
donut_compile_shaders(
TARGET denoised_rtao_shaders
PROJECT_NAME "Denoised RTAO"
CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/shaders/denoised_rtao.cfg
SOURCES ${DENOISED_RTAO_SHADER_SOURCES}
DXIL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders/denoised_rtao/dxil
SPIRV_DXC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders/denoised_rtao/spirv
SHADERMAKE_OPTIONS_SPIRV "--vulkanMemoryLayout dx"
)
add_tslang_example(denoised_rtao core/directx_math.ts core/pbrt_scene.ts core/denoised_rtao.cpp core/pbrt/PBRTParser.cpp core/pbrt/PlyParser.cpp
MEDIA denoised_rtao)
add_dxgs_media_directory(denoised_rtao denoised_rtao
Samples/Desktop/D3D12Raytracing/src/D3D12RaytracingRealTimeDenoisedAmbientOcclusion/Assets)
add_tslang_example_test(denoised_rtao)
add_tslang_example_test(denoised_rtao SUFFIX raw ARGS -raw)
add_tslang_example_test(denoised_rtao SUFFIX shaded ARGS -shaded)
# Ray tracing pipelines: D3D12 or Vulkan. Windows only: the textures are loaded through WIC, and the
# PBRT parser takes its definitions from windows.h.
if (WIN32)
file(GLOB DENOISED_RTAO_SHADER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/denoised_rtao/*)
donut_compile_shaders(
TARGET denoised_rtao_shaders
PROJECT_NAME "Denoised RTAO"
CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/shaders/denoised_rtao.cfg
SOURCES ${DENOISED_RTAO_SHADER_SOURCES}
DXIL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders/denoised_rtao/dxil
SPIRV_DXC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders/denoised_rtao/spirv
SHADERMAKE_OPTIONS_SPIRV "--vulkanMemoryLayout dx"
)
add_tslang_example(denoised_rtao core/directx_math.ts core/pbrt_scene.ts core/denoised_rtao.cpp core/pbrt/PBRTParser.cpp core/pbrt/PlyParser.cpp
MEDIA denoised_rtao)
add_dxgs_media_directory(denoised_rtao denoised_rtao
Samples/Desktop/D3D12Raytracing/src/D3D12RaytracingRealTimeDenoisedAmbientOcclusion/Assets)
add_tslang_example_test(denoised_rtao)
add_tslang_example_test(denoised_rtao SUFFIX raw ARGS -raw)
add_tslang_example_test(denoised_rtao SUFFIX shaded ARGS -shaded)
endif()

# Port of DirectX-Graphics-Samples' D3D12Multithreading: a room of 1025 draws lit by three moving
# spotlights, the first casting shadows, its shadow pass and scene pass recorded by three worker
Expand Down
48 changes: 24 additions & 24 deletions core/fbc_cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ namespace

#define INSET_BC5_BBOX() \
static const int INSET_ALPHA_SHIFT = 5; \
__declspec(align(16)) static const uint16_t s_insetNormal3DcRound[8] = { ((1<<(INSET_ALPHA_SHIFT-1))-1), ((1<<(INSET_ALPHA_SHIFT-1))-1), 0, 0, 0, 0, 0, 0 }; \
__declspec(align(16)) static const uint16_t s_insetNormal3DcMask[8] = { 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; \
__declspec(align(16)) static const uint16_t s_insetNormal3DcShiftUp[8] = { 1 << INSET_ALPHA_SHIFT, 1 << INSET_ALPHA_SHIFT, 1, 1, 1, 1, 1, 1 }; \
__declspec(align(16)) static const uint16_t s_insetNormal3DcShiftDown[8] = { 1 << (16 - INSET_ALPHA_SHIFT), 1 << (16 - INSET_ALPHA_SHIFT), 0, 0, 0, 0, 0, 0 }; \
alignas(16) static const uint16_t s_insetNormal3DcRound[8] = { ((1<<(INSET_ALPHA_SHIFT-1))-1), ((1<<(INSET_ALPHA_SHIFT-1))-1), 0, 0, 0, 0, 0, 0 }; \
alignas(16) static const uint16_t s_insetNormal3DcMask[8] = { 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; \
alignas(16) static const uint16_t s_insetNormal3DcShiftUp[8] = { 1 << INSET_ALPHA_SHIFT, 1 << INSET_ALPHA_SHIFT, 1, 1, 1, 1, 1, 1 }; \
alignas(16) static const uint16_t s_insetNormal3DcShiftDown[8] = { 1 << (16 - INSET_ALPHA_SHIFT), 1 << (16 - INSET_ALPHA_SHIFT), 0, 0, 0, 0, 0, 0 }; \
\
const __m128i zero = _mm_setzero_si128(); \
minColor = _mm_unpacklo_epi8( minColor, zero ); \
Expand All @@ -163,10 +163,10 @@ namespace
maxColor = _mm_packus_epi16( maxColor, maxColor );

#define EMIT_COLOR_INDICES() \
__declspec(align(16)) static const uint8_t s_colorMask[16] = { 0xF8, 0xFC, 0xF8, 0, 0, 0, 0, 0, 0xF8, 0xFC, 0xF8, 0, 0, 0, 0, 0 }; \
__declspec(align(16)) static const uint16_t s_word_div3[8] = { (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1 }; \
__declspec(align(16)) static const uint16_t s_word_1[8] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; \
__declspec(align(16)) static const uint16_t s_word_2[8] = { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2 }; \
alignas(16) static const uint8_t s_colorMask[16] = { 0xF8, 0xFC, 0xF8, 0, 0, 0, 0, 0, 0xF8, 0xFC, 0xF8, 0, 0, 0, 0, 0 }; \
alignas(16) static const uint16_t s_word_div3[8] = { (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1, (1<<16)/3+1 }; \
alignas(16) static const uint16_t s_word_1[8] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; \
alignas(16) static const uint16_t s_word_2[8] = { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2 }; \
\
maxColor = _mm_and_si128( maxColor, reinterpret_cast<const __m128i*>(s_colorMask)[0] ); \
maxColor = _mm_unpacklo_epi8( maxColor, zero ); \
Expand Down Expand Up @@ -365,21 +365,21 @@ namespace
result = _mm_or_si128(result, t2);

#define EMIT_ALPHA_INDICES_VARS() \
__declspec(align(16)) static const uint8_t s_byte_1[16] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; \
__declspec(align(16)) static const uint8_t s_byte_2[16] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; \
__declspec(align(16)) static const uint8_t s_byte_7[16] = { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }; \
__declspec(align(16)) static const uint16_t s_word_div7[8] = { (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1 }; \
__declspec(align(16)) static const uint16_t s_word_div14[8] = { (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1 }; \
__declspec(align(16)) static const uint16_t s_word_scaleA[8] = { 6, 6, 5, 5, 4, 4, 0, 0 }; \
__declspec(align(16)) static const uint16_t s_word_scaleB[8] = { 1, 1, 2, 2, 3, 3, 0, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask0[4] = { 7<<0, 0, 7<<0, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask1[4] = { 7<<3, 0, 7<<3, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask2[4] = { 7<<6, 0, 7<<6, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask3[4] = { 7<<9, 0, 7<<9, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask4[4] = { 7<<12, 0, 7<<12, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask5[4] = { 7<<15, 0, 7<<15, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask6[4] = { 7<<18, 0, 7<<18, 0 }; \
__declspec(align(16)) static const uint32_t s_alphaMask7[4] = { 7<<21, 0, 7<<21, 0 }; \
alignas(16) static const uint8_t s_byte_1[16] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; \
alignas(16) static const uint8_t s_byte_2[16] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; \
alignas(16) static const uint8_t s_byte_7[16] = { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }; \
alignas(16) static const uint16_t s_word_div7[8] = { (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1, (1<<16)/7+1 }; \
alignas(16) static const uint16_t s_word_div14[8] = { (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1, (1<<16)/14+1 }; \
alignas(16) static const uint16_t s_word_scaleA[8] = { 6, 6, 5, 5, 4, 4, 0, 0 }; \
alignas(16) static const uint16_t s_word_scaleB[8] = { 1, 1, 2, 2, 3, 3, 0, 0 }; \
alignas(16) static const uint32_t s_alphaMask0[4] = { 7<<0, 0, 7<<0, 0 }; \
alignas(16) static const uint32_t s_alphaMask1[4] = { 7<<3, 0, 7<<3, 0 }; \
alignas(16) static const uint32_t s_alphaMask2[4] = { 7<<6, 0, 7<<6, 0 }; \
alignas(16) static const uint32_t s_alphaMask3[4] = { 7<<9, 0, 7<<9, 0 }; \
alignas(16) static const uint32_t s_alphaMask4[4] = { 7<<12, 0, 7<<12, 0 }; \
alignas(16) static const uint32_t s_alphaMask5[4] = { 7<<15, 0, 7<<15, 0 }; \
alignas(16) static const uint32_t s_alphaMask6[4] = { 7<<18, 0, 7<<18, 0 }; \
alignas(16) static const uint32_t s_alphaMask7[4] = { 7<<21, 0, 7<<21, 0 }; \
__m128i maxa, mina, mid, mid_div_14, ab1, ab2, ab3, ab4, ab5, ab6, ab7, resulta;

#define EMIT_ALPHA_INDICES(alpha) \
Expand Down Expand Up @@ -592,7 +592,7 @@ namespace

void CompressBC5U(const Image& src, Image& dst)
{
__declspec(align(16)) static const uint32_t s_mask[4] = { 0xff, 0xff, 0xff, 0xff };
alignas(16) static const uint32_t s_mask[4] = { 0xff, 0xff, 0xff, 0xff };

const uint8_t* pSource = src.pixels;
uint8_t* pDestination = dst.pixels;
Expand Down
13 changes: 12 additions & 1 deletion core/fbc_cpu_compat.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// What the Xbox ATG FastBlockCompress sample's CPU compressor (fbc_cpu.cpp, fbc_cpu.h) took from the
// sample's precompiled header: the few DXGI / D3D12 / COM definitions it uses, with the values of
// the Windows SDK, without Windows headers (the example builds for Android too), plus aligned
// allocation and SSE2.
// allocation, SSE2, and (the compressor without SSE2: ARM) memcpy_s.

#pragma once

Expand Down Expand Up @@ -79,6 +79,17 @@ inline void FbcAlignedFree(void* p)
#endif
}

#ifndef _WIN32
// The CRT's bounds-checked copy, which the compressor's C fallback uses.
inline int memcpy_s(void* dest, size_t destSize, const void* src, size_t count)
{
if (count > destSize)
return 34; // ERANGE
memcpy(dest, src, count);
return 0;
}
#endif

#define _aligned_malloc FbcAlignedMalloc

struct aligned_deleter { void operator()(void* p) { FbcAlignedFree(p); } };
16 changes: 16 additions & 0 deletions core/sal/sal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// The Microsoft source-code annotations DirectXMath and DirectXCollision use, as nothing: DirectXMath
// includes "sal.h", which only the Windows SDK has. Its README asks non-Windows builds to provide
// one; this is on core/directx_collision.cpp's include path on Android only (see CMakeLists.txt).

#pragma once

#define _Analysis_assume_(expr)
#define _In_
#define _In_reads_(size)
#define _In_reads_bytes_(size)
#define _Out_
#define _Out_opt_
#define _Out_writes_(size)
#define _Out_writes_bytes_(size)
#define _Success_(expr)
#define _Use_decl_annotations_
4 changes: 3 additions & 1 deletion examples/fast_block_compress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ namespace FastBlockCompress {
// interior), alpha (1024x1024 RGBA: the recycle bin and book with alpha), normal (1024x1024 RG:
// normal map texture). Each comes with offline BC and BC7 versions, named after it.
const IMAGE_NAMES = ["opaque_1024", "opaque_512", "alpha", "normal"];
// Their files' extensions, as the sample has them (Android's file names are case-sensitive).
const IMAGE_EXTENSIONS = [".DDS", ".dds", ".DDS", ".dds"];
const IMAGE_OFFLINE_EXTENSIONS = [".DDS", ".DDS", ".DDS", ".DDS"];
const IMAGE_BC7_EXTENSIONS = [".dds", ".dds", ".dds", ".dds"];
const IMAGE_FORMATS = [Format.BC1_UNORM, Format.BC1_UNORM, Format.BC3_UNORM, Format.BC5_UNORM];

Expand Down Expand Up @@ -512,7 +514,7 @@ namespace FastBlockCompress {
}

const bcName = formatName(image.format).toLowerCase();
const offlineBC = this.app.loadTexture(commandList, MEDIA_DIR + name + "_offline_" + bcName + IMAGE_EXTENSIONS[index], 0);
const offlineBC = this.app.loadTexture(commandList, MEDIA_DIR + name + "_offline_" + bcName + IMAGE_OFFLINE_EXTENSIONS[index], 0);
const offlineBC7 = this.app.loadTexture(commandList, MEDIA_DIR + name + "_offline_bc7" + IMAGE_BC7_EXTENSIONS[index], 0);
if (!offlineBC || !offlineBC7) {
return null;
Expand Down