Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
_mipmap_gen.h
Go to the documentation of this file.
1#pragma once
2
3#include "Utility/IMoveOnly.h"
4#include "Frame/TFrame.h"
7#include "Math/math.h"
8
9#include <cstddef>
10#include <future>
11#include <vector>
12#include <algorithm>
13#include <memory>
14
15namespace ph
16{
17
18class mipmapgen final : private IMoveOnly
19{
20public:
21 mipmapgen(const std::size_t numThreads);
23 {
24 m_workers.waitAllWorks();
25 }
26
27 // Generates a series of MIP levels from specified source frame.
28 // Mipmaps are stored in the returned vector, where level 0 is source frame.
29 // Each level is in half dimension (floored) of its previous level, and the
30 // last one is guaranteed to be 1x1.
31
32 template<typename T, std::size_t N>
33 using Mipmaps = std::vector<TFrame<T, N>>;
34
35 template<typename T, std::size_t N>
36 inline auto genMipmaps(const TFrame<T, N>& source)
37 -> std::future<Mipmaps<T, N>>
38 {
39 // Using shared_ptr here because if we move a std::promise to some lambda
40 // and use it to construct a Work, which is a std::function, then we can
41 // not satisfy the CopyConstructible requirement that a std::function
42 // needs.
43 auto promisedMipmaps = std::make_shared<std::promise<Mipmaps<T, N>>>();
44
45 std::future<Mipmaps<T, N>> futureMipmaps = promisedMipmaps->get_future();
46
47 m_workers.queueWork([workingResult = promisedMipmaps, src = source]()
48 {
49 TFrame<T, N> level0;
50 if(math::is_power_of_2(src.widthPx()) && math::is_power_of_2(src.heightPx()))
51 {
52 level0 = src;
53 }
54 else
55 {
56 const uint32 newWidthPx = math::next_power_of_2(src.widthPx());
57 const uint32 newHeightPx = math::next_power_of_2(src.heightPx());
58 level0 = TFrame<T, N>(newWidthPx, newHeightPx);
59
60 src.sample(level0, math::TConstant2D<float64>(1.0), 2);
61 }
62
63 const std::size_t numMipmapLevels = 1 + math::log2_floor(std::max(level0.widthPx(), level0.heightPx()));
64 Mipmaps<T, N> mipmaps(numMipmapLevels);
65 mipmaps[0] = level0;
66 for(std::size_t level = 1; level < numMipmapLevels; ++level)
67 {
68 auto& previous = mipmaps[level - 1];
69 auto& current = mipmaps[level];
70
71 current = TFrame<T, N>(std::max(static_cast<uint32>(1), previous.widthPx() / 2),
72 std::max(static_cast<uint32>(1), previous.heightPx() / 2));
73 previous.sample(current, math::TConstant2D<float64>(1.0), 2);
74 }
75
76 workingResult->set_value(std::move(mipmaps));
77 });
78
79 return std::move(futureMipmaps);
80 }
81
82private:
83 FixedSizeThreadPool m_workers;
84};
85
86}// end namespace ph
A thread pool where works are accessed concurrently by blocking other threads. A thread pool that con...
Definition FixedSizeThreadPool.h:21
void queueWork(const Work &work)
Queue up a work to the pool. Workers start to process the work right away. The works are guaranteed t...
Definition FixedSizeThreadPool.cpp:50
void waitAllWorks()
Blocks until all queued works are finished. Should not be called on worker thread....
Definition FixedSizeThreadPool.cpp:129
Marks the derived class as move only.
Definition IMoveOnly.h:23
Definition TFrame.h:21
uint32 heightPx() const
Definition TFrame.ipp:440
uint32 widthPx() const
Definition TFrame.ipp:434
Definition TConstant2D.h:10
Definition _mipmap_gen.h:19
~mipmapgen()
Definition _mipmap_gen.h:22
mipmapgen(const std::size_t numThreads)
Definition _mipmap_gen.cpp:6
std::vector< TFrame< T, N > > Mipmaps
Definition _mipmap_gen.h:33
auto genMipmaps(const TFrame< T, N > &source) -> std::future< Mipmaps< T, N > >
Definition _mipmap_gen.h:36
Miscellaneous math utilities.
uint32 next_power_of_2(uint32 value)
Gets the minimum power of 2 value that is >= value.
Definition math.h:167
T log2_floor(const T value)
Calculate a positive number's base 2 logarithm (floored).
Definition math.h:187
The root for all renderer implementations.
Definition EEngineProject.h:6