Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/cvtt/ConvectionKernels_IndexSelectorHDR.h
9896 views
1
#pragma once
2
#ifndef __CVTT_INDEXSELECTORHDR_H__
3
#define __CVTT_INDEXSELECTORHDR_H__
4
5
#include "ConvectionKernels_ParallelMath.h"
6
#include "ConvectionKernels_IndexSelector.h"
7
8
namespace cvtt
9
{
10
namespace Internal
11
{
12
ParallelMath::SInt16 UnscaleHDRValueSigned(const ParallelMath::SInt16 &v);
13
ParallelMath::UInt15 UnscaleHDRValueUnsigned(const ParallelMath::UInt16 &v);
14
15
template<int TVectorSize>
16
class IndexSelectorHDR : public IndexSelector<TVectorSize>
17
{
18
public:
19
typedef ParallelMath::UInt15 MUInt15;
20
typedef ParallelMath::UInt16 MUInt16;
21
typedef ParallelMath::UInt31 MUInt31;
22
typedef ParallelMath::SInt16 MSInt16;
23
typedef ParallelMath::SInt32 MSInt32;
24
typedef ParallelMath::Float MFloat;
25
26
private:
27
28
MUInt15 InvertSingle(const MUInt15& anIndex) const
29
{
30
MUInt15 inverted = m_maxValueMinusOne - anIndex;
31
return ParallelMath::Select(m_isInverted, inverted, anIndex);
32
}
33
34
void ReconstructHDRSignedUninverted(const MUInt15 &index, MSInt16* pixel) const
35
{
36
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
37
38
for (int ch = 0; ch < TVectorSize; ch++)
39
{
40
MSInt16 ep0 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[0][ch]);
41
MSInt16 ep1 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[1][ch]);
42
43
MSInt32 pixel32 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
44
45
pixel32 = ParallelMath::RightShift(pixel32 + ParallelMath::MakeSInt32(32), 6);
46
47
pixel[ch] = UnscaleHDRValueSigned(ParallelMath::ToSInt16(pixel32));
48
}
49
}
50
51
void ReconstructHDRUnsignedUninverted(const MUInt15 &index, MSInt16* pixel) const
52
{
53
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
54
55
for (int ch = 0; ch < TVectorSize; ch++)
56
{
57
MUInt16 ep0 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[0][ch]);
58
MUInt16 ep1 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[1][ch]);
59
60
MUInt31 pixel31 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
61
62
pixel31 = ParallelMath::RightShift(pixel31 + ParallelMath::MakeUInt31(32), 6);
63
64
pixel[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::ToUInt16(pixel31)));
65
}
66
}
67
68
MFloat ErrorForInterpolatorComponent(int index, int ch, const MFloat *pixel) const
69
{
70
MFloat diff = pixel[ch] - m_reconstructedInterpolators[index][ch];
71
return diff * diff;
72
}
73
74
MFloat ErrorForInterpolator(int index, const MFloat *pixel) const
75
{
76
MFloat error = ErrorForInterpolatorComponent(index, 0, pixel);
77
for (int ch = 1; ch < TVectorSize; ch++)
78
error = error + ErrorForInterpolatorComponent(index, ch, pixel);
79
return error;
80
}
81
82
public:
83
84
void InitHDR(int range, bool isSigned, bool fastIndexing, const float *channelWeights)
85
{
86
assert(range <= 16);
87
88
m_range = range;
89
90
m_isInverted = ParallelMath::MakeBoolInt16(false);
91
m_maxValueMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(range - 1));
92
93
if (!fastIndexing)
94
{
95
for (int i = 0; i < range; i++)
96
{
97
MSInt16 recon2CL[TVectorSize];
98
99
if (isSigned)
100
ReconstructHDRSignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
101
else
102
ReconstructHDRUnsignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
103
104
for (int ch = 0; ch < TVectorSize; ch++)
105
m_reconstructedInterpolators[i][ch] = ParallelMath::TwosCLHalfToFloat(recon2CL[ch]) * channelWeights[ch];
106
}
107
}
108
}
109
110
void ReconstructHDRSigned(const MUInt15 &index, MSInt16* pixel) const
111
{
112
ReconstructHDRSignedUninverted(InvertSingle(index), pixel);
113
}
114
115
void ReconstructHDRUnsigned(const MUInt15 &index, MSInt16* pixel) const
116
{
117
ReconstructHDRUnsignedUninverted(InvertSingle(index), pixel);
118
}
119
120
void ConditionalInvert(const ParallelMath::Int16CompFlag &invert)
121
{
122
m_isInverted = invert;
123
}
124
125
MUInt15 SelectIndexHDRSlow(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope*) const
126
{
127
MUInt15 index = ParallelMath::MakeUInt15(0);
128
129
MFloat bestError = ErrorForInterpolator(0, pixel);
130
for (int i = 1; i < m_range; i++)
131
{
132
MFloat error = ErrorForInterpolator(i, pixel);
133
ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError);
134
ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(errorBetter), ParallelMath::MakeUInt15(static_cast<uint16_t>(i)));
135
bestError = ParallelMath::Min(bestError, error);
136
}
137
138
return InvertSingle(index);
139
}
140
141
MUInt15 SelectIndexHDRFast(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const
142
{
143
return InvertSingle(this->SelectIndexLDR(pixel, rtn));
144
}
145
146
private:
147
MFloat m_reconstructedInterpolators[16][TVectorSize];
148
ParallelMath::Int16CompFlag m_isInverted;
149
MUInt15 m_maxValueMinusOne;
150
int m_range;
151
};
152
}
153
}
154
#endif
155
156
157