diff --git a/src/apps/cli.cpp b/src/apps/cli.cpp index 73582eab..b7e986d8 100644 --- a/src/apps/cli.cpp +++ b/src/apps/cli.cpp @@ -111,7 +111,7 @@ using namespace luisa::render; int main(int argc, char *argv[]) { log_level_info(); - // luisa::log_level_verbose(); + luisa::log_level_verbose(); luisa::compute::Context context{argv[0]}; auto macros = parse_cli_macros(argc, argv); for (auto &&[k, v] : macros) { diff --git a/src/base/differentiation.cpp b/src/base/differentiation.cpp index ed4a7070..45369bfd 100644 --- a/src/base/differentiation.cpp +++ b/src/base/differentiation.cpp @@ -2,6 +2,7 @@ // Created by Mike Smith on 2022/3/9. // +#include "dsl/builtin.h" #include #include @@ -109,8 +110,7 @@ Differentiation::TexturedParameter Differentiation::parameter(const Image _counter_size = (_counter_size + pixel_count + 3u) & ~0b11u; _param_buffer_size = (_param_buffer_size + param_count + 3u) & ~0b11u; _gradient_buffer_size = (_gradient_buffer_size + param_count + 3u) & ~0b11u; - return _textured_params.emplace_back(TexturedParameter{ - param_index, image, s, grad_offset, param_offset, counter_offset, range}); + return _textured_params.emplace_back(param_index, image, s, grad_offset, param_offset, counter_offset, range); } void Differentiation::materialize(CommandBuffer &command_buffer) noexcept { diff --git a/src/textures/CMakeLists.txt b/src/textures/CMakeLists.txt index f5a51f59..23e699a3 100644 --- a/src/textures/CMakeLists.txt +++ b/src/textures/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(luisa-render-textures INTERFACE) luisa_render_add_plugin(constant CATEGORY texture SOURCES constant.cpp) luisa_render_add_plugin(image CATEGORY texture SOURCES image.cpp) +luisa_render_add_plugin(placeholder CATEGORY texture SOURCES placeholder.cpp) luisa_render_add_plugin(swizzle CATEGORY texture SOURCES swizzle.cpp) luisa_render_add_plugin(checkerboard CATEGORY texture SOURCES checkerboard.cpp) diff --git a/src/textures/constant.cpp b/src/textures/constant.cpp index b52d3e82..ba4faf8e 100644 --- a/src/textures/constant.cpp +++ b/src/textures/constant.cpp @@ -119,7 +119,7 @@ class ConstantTextureInstance final : public Texture::Instance { return spec->decode_illuminant(swl, enc); } void backward(const Interaction &it, const SampledWavelengths &swl, - Expr, Expr grad) const noexcept override { + Expr time, Expr grad) const noexcept override { if (_diff_param) { // $if(_diff_param->index() == 1u) { // device_log("diff param ({}) , grad in accumulate: ({}, {}, {})", diff --git a/src/textures/placeholder.cpp b/src/textures/placeholder.cpp new file mode 100644 index 00000000..81d2fff9 --- /dev/null +++ b/src/textures/placeholder.cpp @@ -0,0 +1,164 @@ +// +// Created by Mike Smith on 2022/3/23. +// + +#include "core/logging.h" +#include "dsl/stmt.h" +#include "runtime/stream.h" +#include +#include +#include +#include +#include +#include + +namespace luisa::render { + +using namespace luisa::compute; + +class PlaceholderTexture final : public Texture { + +private: + float2 _uv_scale; + float2 _uv_offset; + uint2 _resolution; + TextureSampler _sampler{}; + uint _channels; + +public: + PlaceholderTexture(Scene *scene, const SceneNodeDesc *desc) noexcept + : Texture{scene, desc}, + _channels{std::clamp(desc->property_uint_or_default("channels", 4u), 1u, 4u)} { + auto filter = desc->property_string_or_default("filter", "bilinear"); + auto address = desc->property_string_or_default("address", "repeat"); + for (auto &c : filter) { c = static_cast(tolower(c)); } + for (auto &c : address) { c = static_cast(tolower(c)); } + auto address_mode = [&address, desc] { + for (auto &c : address) { c = static_cast(tolower(c)); } + if (address == "zero") { return TextureSampler::Address::ZERO; } + if (address == "edge") { return TextureSampler::Address::EDGE; } + if (address == "mirror") { return TextureSampler::Address::MIRROR; } + if (address == "repeat") { return TextureSampler::Address::REPEAT; } + LUISA_ERROR( + "Invalid texture address mode '{}'. [{}]", + address, desc->source_location().string()); + }(); + auto filter_mode = [&filter, desc] { + for (auto &c : filter) { c = static_cast(tolower(c)); } + if (filter == "point") { return TextureSampler::Filter::POINT; } + if (filter == "bilinear") { return TextureSampler::Filter::LINEAR_POINT; } + if (filter == "trilinear") { return TextureSampler::Filter::LINEAR_LINEAR; } + if (filter == "anisotropic" || filter == "aniso") { return TextureSampler::Filter::ANISOTROPIC; } + LUISA_ERROR( + "Invalid texture filter mode '{}'. [{}]", + filter, desc->source_location().string()); + }(); + _sampler = {filter_mode, address_mode}; + _uv_scale = desc->property_float2_or_default( + "uv_scale", lazy_construct([desc] { + return make_float2(desc->property_float_or_default( + "uv_scale", 1.0f)); + })); + _uv_offset = desc->property_float2_or_default( + "uv_offset", lazy_construct([desc] { + return make_float2(desc->property_float_or_default( + "uv_offset", 0.0f)); + })); + _resolution = desc->property_uint2_or_default( + "resolution", lazy_construct([desc] { + return make_uint2(desc->property_uint_or_default( + "resolution", 1024u)); + })); + _resolution = clamp(_resolution, 1u, 16384u); + } + [[nodiscard]] luisa::string_view impl_type() const noexcept override { return LUISA_RENDER_PLUGIN_NAME; } + [[nodiscard]] bool is_black() const noexcept override { return false; } + [[nodiscard]] bool is_constant() const noexcept override { return false; } + [[nodiscard]] auto uv_scale() const noexcept { return _uv_scale; } + [[nodiscard]] auto uv_offset() const noexcept { return _uv_offset; } + [[nodiscard]] auto resolution() const noexcept { return _resolution; } + [[nodiscard]] uint channels() const noexcept override { return _channels; } + [[nodiscard]] luisa::unique_ptr build(Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept override; +}; + +class PlaceholderTextureInstance final : public Texture::Instance { + +private: + const Image &_image; + luisa::optional _diff_param; + uint _texture_id{}; + +private: + [[nodiscard]] Float2 _compute_uv(const Interaction &it) const noexcept { + auto texture = node(); + auto uv_scale = texture->uv_scale(); + auto uv_offset = texture->uv_offset(); + return it.uv() * uv_scale + uv_offset; + } + +public: + PlaceholderTextureInstance(Pipeline &pipeline, CommandBuffer &command_buffer, + const Texture *texture, const Image &image, TextureSampler sampler, + luisa::optional param) noexcept + : Texture::Instance{pipeline, texture}, + _image{image}, _diff_param{std::move(param)} { + static thread_local Kernel2D fill = [](ImageFloat image) noexcept { + image.write(dispatch_id().xy(), make_float4(.5f, .5f, .5f, 1.f)); + }; + auto fill_image = pipeline.device().compile(fill); + command_buffer << fill_image(_image).dispatch(_image.size()) << synchronize(); + _texture_id = pipeline.register_bindless(_image, sampler); + } + [[nodiscard]] Float4 evaluate( + const Interaction &it, const SampledWavelengths &swl, Expr time) const noexcept override { + auto uv = _compute_uv(it); + return pipeline().tex2d(_texture_id).sample(uv);// TODO: LOD + } + [[nodiscard]] SampledSpectrum eval_grad(const Interaction &it, + const SampledWavelengths &swl, + Expr time, + Expr grad) const noexcept override { + if (_diff_param) { + if (node()->render_grad_map()) { + auto grads = (grad[0] + grad[1] + grad[2]); + return {swl.dimension(), ite(isnan(grads), 0.f, grads)}; + } else { + return {swl.dimension(), 0.f}; + } + } else { + return {swl.dimension(), 0.f}; + } + } + void backward(const Interaction &it, const SampledWavelengths &swl, + Expr time, Expr grad) const noexcept override { + if (_diff_param) { + auto uv = _compute_uv(it); + pipeline().differentiation()->accumulate(*_diff_param, uv, grad); + } + } + [[nodiscard]] luisa::string diff_param_identifier() const noexcept override { + return _diff_param ? _diff_param->identifier() : non_differrentiable_identifier; + } +}; + +luisa::unique_ptr PlaceholderTexture::build(Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept { + auto storage = PixelStorage::FLOAT4; + if (_channels == 1u) { + storage = PixelStorage::FLOAT1; + } else if (_channels == 2u) { + storage = PixelStorage::FLOAT2; + } + auto device_image = pipeline.create>(storage, _resolution); + luisa::optional param; + if (requires_gradients()) { + param.emplace(pipeline.differentiation()->parameter( + *device_image, _sampler, range())); + } + return luisa::make_unique( + pipeline, command_buffer, this, + *device_image, _sampler, std::move(param)); +} + +}// namespace luisa::render + +LUISA_RENDER_MAKE_SCENE_NODE_PLUGIN(luisa::render::PlaceholderTexture)