Skip to content
Open
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
54 changes: 54 additions & 0 deletions 37_HLSLSamplingTests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
set(NBL_INCLUDE_SEARCH_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)

include(common RESULT_VARIABLE RES)
if(NOT RES)
message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory")
endif()

nbl_create_executable_project("" "" "${NBL_INCLUDE_SEARCH_DIRECTORIES}" "" "${NBL_EXECUTABLE_PROJECT_CREATION_PCH_TARGET}")

if(NBL_EMBED_BUILTIN_RESOURCES)
set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData)
set(RESOURCE_DIR "app_resources")

get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)

file(GLOB_RECURSE BUILTIN_RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}" CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}/*")
foreach(RES_FILE ${BUILTIN_RESOURCE_FILES})
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "${RES_FILE}")
endforeach()

ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}")

LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_})
endif()

set(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/auto-gen")

set(JSON [=[
[
{
"INPUT": "app_resources/test_compile.comp.hlsl",
"KEY": "shader",
"COMPILE_OPTIONS": ["-T", "cs_6_8"],
"DEPENDS": [],
"CAPS": []
}
]
]=])

NBL_CREATE_NSC_COMPILE_RULES(
TARGET ${EXECUTABLE_NAME}SPIRV
LINK_TO ${EXECUTABLE_NAME}
BINARY_DIR ${OUTPUT_DIRECTORY}
MOUNT_POINT_DEFINE NBL_THIS_EXAMPLE_BUILD_MOUNT_POINT
COMMON_OPTIONS -I ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VAR KEYS
INCLUDE nbl/this_example/builtin/build/spirv/keys.hpp
NAMESPACE nbl::this_example::builtin::build
INPUTS ${JSON}
)
79 changes: 79 additions & 0 deletions 37_HLSLSamplingTests/app_resources/test_compile.comp.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Compile test: instantiate sampling types to verify DXC compilation
#include <nbl/builtin/hlsl/sampling/concentric_mapping.hlsl>
#include <nbl/builtin/hlsl/sampling/linear.hlsl>
#include <nbl/builtin/hlsl/sampling/bilinear.hlsl>
#include <nbl/builtin/hlsl/sampling/uniform_spheres.hlsl>
#include <nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl>
#include <nbl/builtin/hlsl/sampling/box_muller_transform.hlsl>
#include <nbl/builtin/hlsl/sampling/spherical_triangle.hlsl>
#include <nbl/builtin/hlsl/sampling/projected_spherical_triangle.hlsl>
#include <nbl/builtin/hlsl/sampling/spherical_rectangle.hlsl>
using namespace nbl::hlsl;

[[vk::binding(0, 0)]] RWStructuredBuffer<float32_t4> output;

[numthreads(1, 1, 1)]
void main()
{
float32_t2 u2 = float32_t2(0.5, 0.5);
float32_t3 u3 = float32_t3(0.5, 0.5, 0.5);
float32_t4 acc = float32_t4(0, 0, 0, 0);

// concentric mapping (free function)
float32_t2 concentric = sampling::concentricMapping<float32_t>(u2);
acc.xy += concentric;

// Linear
sampling::Linear<float32_t> lin = sampling::Linear<float32_t>::create(u2);
acc.x += lin.generate(0.5f);

// Bilinear
sampling::Bilinear<float32_t> bilinear = sampling::Bilinear<float32_t>::create(float32_t4(1, 2, 3, 4));
float32_t rcpPdf;
float32_t2 bilSample = bilinear.generate(rcpPdf, u2);
acc.xy += bilSample;
acc.z += rcpPdf;

// UniformHemisphere
acc.xyz += sampling::UniformHemisphere<float32_t>::generate(u2);

// UniformSphere
acc.xyz += sampling::UniformSphere<float32_t>::generate(u2);

// ProjectedHemisphere
acc.xyz += sampling::ProjectedHemisphere<float32_t>::generate(u2);

// ProjectedSphere
acc.xyz += sampling::ProjectedSphere<float32_t>::generate(u3);

// BoxMullerTransform
sampling::BoxMullerTransform<float32_t> bmt;
bmt.stddev = 1.0;
acc.xy += bmt(u2);

// SphericalTriangle
shapes::SphericalTriangle<float32_t> shapeTri;
shapeTri.vertex0 = float32_t3(1, 0, 0);
shapeTri.vertex1 = float32_t3(0, 1, 0);
shapeTri.vertex2 = float32_t3(0, 0, 1);
sampling::SphericalTriangle<float32_t> sphTri = sampling::SphericalTriangle<float32_t>::create(shapeTri);
float32_t stRcpPdf;
acc.xyz += sphTri.generate(stRcpPdf, u2);
acc.w += stRcpPdf;

// SphericalRectangle
shapes::SphericalRectangle<float32_t> shapeRect;
shapeRect.r0 = float32_t3(-0.5, -0.5, -1.0);
sampling::SphericalRectangle<float32_t> sphRect = sampling::SphericalRectangle<float32_t>::create(shapeRect);
float32_t srS;
acc.xy += sphRect.generate(float32_t2(1.0, 1.0), u2, srS);
acc.z += srS;

// ProjectedSphericalTriangle — skipped: pre-existing bug in computeBilinearPatch(receiverNormal, isBSDF)
sampling::ProjectedSphericalTriangle<float32_t> projTri = sampling::ProjectedSphericalTriangle<float32_t>::create(shapeTri);
float32_t ptRcpPdf;
// acc.xyz += projTri.generate(ptRcpPdf, float32_t3(0.0f, 0.0f, 1.0f), true, u2);
acc.w += ptRcpPdf;

output[0] = acc;
}
121 changes: 121 additions & 0 deletions 37_HLSLSamplingTests/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include <nabla.h>

#include "nbl/examples/examples.hpp"
#include "nbl/this_example/builtin/build/spirv/keys.hpp"

using namespace nbl;
using namespace core;
using namespace system;
using namespace asset;
using namespace video;
using namespace nbl::hlsl;
using namespace nbl::examples;

// sampling headers (HLSL/C++ compatible)
#include "nbl/builtin/hlsl/sampling/concentric_mapping.hlsl"
#include "nbl/builtin/hlsl/sampling/linear.hlsl"
#include "nbl/builtin/hlsl/sampling/bilinear.hlsl"
#include "nbl/builtin/hlsl/sampling/uniform_spheres.hlsl"
#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl"
#include "nbl/builtin/hlsl/sampling/box_muller_transform.hlsl"
#include "nbl/builtin/hlsl/sampling/spherical_triangle.hlsl"
#include "nbl/builtin/hlsl/sampling/projected_spherical_triangle.hlsl"
#include "nbl/builtin/hlsl/sampling/spherical_rectangle.hlsl"

// concepts header — include AFTER sampler headers, and only in the test
#include "nbl/builtin/hlsl/sampling/concepts.hlsl"

class HLSLSamplingTests final : public application_templates::MonoDeviceApplication, public BuiltinResourcesApplication
{
using device_base_t = application_templates::MonoDeviceApplication;
using asset_base_t = BuiltinResourcesApplication;

public:
HLSLSamplingTests(const path& _localInputCWD, const path& _localOutputCWD, const path& _sharedInputCWD, const path& _sharedOutputCWD) :
system::IApplicationFramework(_localInputCWD, _localOutputCWD, _sharedInputCWD, _sharedOutputCWD) {}

inline bool onAppInitialized(smart_refctd_ptr<ISystem>&& system) override
{
if (!device_base_t::onAppInitialized(smart_refctd_ptr(system)))
return false;

if (!asset_base_t::onAppInitialized(std::move(system)))
return false;

// test compile with dxc
{
IAssetLoader::SAssetLoadParams lp = {};
lp.logger = m_logger.get();
lp.workingDirectory = "app_resources";
auto key = nbl::this_example::builtin::build::get_spirv_key<"shader">(m_device.get());
auto bundle = m_assetMgr->getAsset(key.c_str(), lp);

const auto assets = bundle.getContents();
if (assets.empty())
{
m_logger->log("Could not load shader!", ILogger::ELL_ERROR);
return false;
}

auto shader = IAsset::castDown<IShader>(assets[0]);
if (!shader)
{
m_logger->log("compile shader test failed!", ILogger::ELL_ERROR);
return false;
}

m_logger->log("Shader compilation test passed.", ILogger::ELL_INFO);
}

// ================================================================
// Compile-time concept verification via static_assert
// ================================================================

// --- BasicSampler (level 1) --- generate(domain_type) -> codomain_type
static_assert(sampling::concepts::BasicSampler<sampling::Linear<float>>);
static_assert(sampling::concepts::BasicSampler<sampling::UniformHemisphere<float>>);
static_assert(sampling::concepts::BasicSampler<sampling::UniformSphere<float>>);
static_assert(sampling::concepts::BasicSampler<sampling::ProjectedHemisphere<float>>);
static_assert(sampling::concepts::BasicSampler<sampling::ProjectedSphere<float>>);

// TODO: remaining samplers need generate(domain_type)->codomain_type overload to satisfy BasicSampler:
// Bilinear - generate takes (rcpPdf, u), needs single-arg overload
// SphericalTriangle - generate takes (rcpPdf, u), needs single-arg overload
// SphericalRectangle - generate takes (extents, uv, S), needs single-arg overload
// BoxMullerTransform - uses operator() instead of generate
// ProjectedSphericalTriangle - generate takes (rcpPdf, normal, isBSDF, u)
// Concentric_mapping - is a free function, needs to be wrapped in a struct with concept type aliases

// TODO: higher-level concepts require method refactoring:
// --- BackwardDensitySampler (level 3) --- needs generate(domain_type)->sample_type, forwardPdf, backwardPdf
// static_assert(sampling::concepts::BackwardDensitySampler<sampling::SphericalRectangle<float>>);
// static_assert(sampling::concepts::BackwardDensitySampler<sampling::SphericalTriangle<float>>);
// static_assert(sampling::concepts::BackwardDensitySampler<sampling::BoxMullerTransform<float>>);
// static_assert(sampling::concepts::BackwardDensitySampler<sampling::ProjectedSphericalTriangle<float>>);
// --- BijectiveSampler (level 4) --- needs + invertGenerate(codomain_type)->inverse_sample_type
// static_assert(sampling::concepts::BijectiveSampler<sampling::Linear<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::Bilinear<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::UniformHemisphere<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::UniformSphere<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::ProjectedHemisphere<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::ProjectedSphere<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::SphericalTriangle<float>>);
// static_assert(sampling::concepts::BijectiveSampler<sampling::ConcentricMapping<float>>);



m_logger->log("All sampling concept tests passed.", ILogger::ELL_INFO);
return true;
}

void workLoopBody() override {}

bool keepRunning() override { return false; }

bool onAppTerminated() override
{
return device_base_t::onAppTerminated();
}
};

NBL_MAIN_FUNC(HLSLSamplingTests)
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ if(NBL_BUILD_EXAMPLES)

add_subdirectory(34_DebugDraw)

add_subdirectory(37_HLSLSamplingTests)
add_subdirectory(38_EXRSplit)
if (NBL_BUILD_MITSUBA_LOADER)
# if (NBL_BUILD_OPTIX)
Expand Down