forked from AcademySoftwareFoundation/OpenShadingLanguage
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbatched_texture.h
More file actions
287 lines (256 loc) · 11.8 KB
/
batched_texture.h
File metadata and controls
287 lines (256 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/wide.h>
OSL_NAMESPACE_ENTER
namespace Tex {
using OIIO::Tex::InterpMode;
using OIIO::Tex::MipMode;
using OIIO::Tex::Wrap;
} // namespace Tex
struct UniformTextureOptions {
// Options that must be the same for all points we're texturing at once
int firstchannel = 0; ///< First channel of the lookup
int subimage = 0; ///< Subimage or face ID
ustring subimagename; ///< Subimage name
Tex::Wrap swrap = Tex::Wrap::Default; ///< Wrap mode in the s direction
Tex::Wrap twrap = Tex::Wrap::Default; ///< Wrap mode in the t direction
Tex::Wrap rwrap
= Tex::Wrap::Default; ///< Wrap mode in the r direction (volumetric)
Tex::MipMode mipmode = Tex::MipMode::Default; ///< Mip mode
Tex::InterpMode interpmode
= Tex::InterpMode::SmartBicubic; ///< Interpolation mode
int anisotropic = 32; ///< Maximum anisotropic ratio
int conservative_filter = 1; ///< True: over-blur rather than alias
float fill = 0.0f; ///< Fill value for missing channels
const float* missingcolor = nullptr; ///< Color for missing texture
};
template<int WidthT> struct VaryingTextureOptions {
Block<float, WidthT> sblur; ///< Blur amount
Block<float, WidthT> tblur;
Block<float, WidthT> rblur; // For 3D volume texture lookups only:
Block<float, WidthT> swidth; ///< Multiplier for derivatives
Block<float, WidthT> twidth;
Block<float, WidthT> rwidth; // For 3D volume texture lookups only:
Block<float, WidthT> rnd; // For stochastic sampling
};
static_assert(std::alignment_of<VaryingTextureOptions<16>>::value
== VecReg<16>::alignment,
"Expect alignment of data member to set alignment of struct");
static_assert(std::alignment_of<VaryingTextureOptions<8>>::value
== VecReg<8>::alignment,
"Expect alignment of data member to set alignment of struct");
static_assert(std::alignment_of<VaryingTextureOptions<4>>::value
== VecReg<4>::alignment,
"Expect alignment of data member to set alignment of struct");
template<int WidthT> struct BatchedTextureOptions {
VaryingTextureOptions<WidthT> varying;
UniformTextureOptions uniform;
// Options set INTERNALLY by libtexture after the options are passed
// by the user. Users should not attempt to alter these!
int private_envlayout = 0; // Layout for environment wrap
// Implementation detail
// keep order synchronized to the data members in this structure
enum class LLVMMemberIndex {
sblur = 0,
tblur,
rblur,
swidth,
twidth,
rwidth,
rnd,
firstchannel,
subimage,
subimagename,
swrap,
twrap,
rwrap,
mipmode,
interpmode,
anisotropic,
conservative_filter,
fill,
missingcolor,
private_envlayout,
count
};
};
static_assert(std::alignment_of<BatchedTextureOptions<16>>::value
== VecReg<16>::alignment,
"Expect alignment of data member to set alignment of struct");
static_assert(std::alignment_of<BatchedTextureOptions<8>>::value
== VecReg<8>::alignment,
"Expect alignment of data member to set alignment of struct");
static_assert(std::alignment_of<BatchedTextureOptions<4>>::value
== VecReg<4>::alignment,
"Expect alignment of data member to set alignment of struct");
#ifdef OIIO_TEXTURE_SIMD_BATCH_WIDTH
// Code here is to validate our OSL BatchedTextureOptions<WidthT> is binary compatible
// and safe to reinterpret_cast<TextureOptBatch*>
static_assert((OIIO::Tex::BatchWidth == 16) || (OIIO::Tex::BatchWidth == 8)
|| (OIIO::Tex::BatchWidth == 4),
"This validation requires OIIO_TEXTURE_SIMD_BATCH_WIDTH=16");
namespace validate_offsets {
OSL_PRAGMA_WARNING_PUSH
OSL_GCC_PRAGMA(GCC diagnostic ignored "-Winvalid-offsetof")
typedef BatchedTextureOptions<OIIO::Tex::BatchWidth> BTO;
static constexpr size_t uniform_offset = offsetof(BTO, uniform);
static constexpr size_t varying_offset = offsetof(BTO, varying);
typedef VaryingTextureOptions<OIIO::Tex::BatchWidth> VTO;
static_assert(offsetof(OIIO::TextureOptBatch, sblur) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, tblur) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, rblur) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, swidth) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, twidth) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, rwidth) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, rnd) % 64 == 0,
"oops unaligned wide variable");
static_assert(sizeof(OIIO::TextureOptBatch)
== sizeof(BatchedTextureOptions<16>),
"BatchedTextureOptions size differs from OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, sblur)
== varying_offset + offsetof(VTO, sblur),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, tblur)
== varying_offset + offsetof(VTO, tblur),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, rblur)
== varying_offset + offsetof(VTO, rblur),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, swidth)
== varying_offset + offsetof(VTO, swidth),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, twidth)
== varying_offset + offsetof(VTO, twidth),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, rwidth)
== varying_offset + offsetof(VTO, rwidth),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, firstchannel)
== uniform_offset + offsetof(UniformTextureOptions, firstchannel),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, subimage)
== uniform_offset + offsetof(UniformTextureOptions, subimage),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, subimagename)
== uniform_offset + offsetof(UniformTextureOptions, subimagename),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, swrap)
== uniform_offset + offsetof(UniformTextureOptions, swrap),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, twrap)
== uniform_offset + offsetof(UniformTextureOptions, twrap),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, rwrap)
== uniform_offset + offsetof(UniformTextureOptions, rwrap),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, mipmode)
== uniform_offset + offsetof(UniformTextureOptions, mipmode),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, interpmode)
== uniform_offset + offsetof(UniformTextureOptions, interpmode),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, anisotropic)
== uniform_offset + offsetof(UniformTextureOptions, anisotropic),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, conservative_filter)
== uniform_offset
+ offsetof(UniformTextureOptions, conservative_filter),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, fill)
== uniform_offset + offsetof(UniformTextureOptions, fill),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
static_assert(
offsetof(OIIO::TextureOptBatch, missingcolor)
== uniform_offset + offsetof(UniformTextureOptions, missingcolor),
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
OSL_PRAGMA_WARNING_POP
} // namespace validate_offsets
#endif
// The wrapper class itself exists to get the 3 different MaskedDataRef classes
// to all share the same mask value (after inlining) vs. 3 different copies
// NOTE: detection and access to derivatives for result and alpha can be done
// using methods "has_derivs", "maskedDx()", and "maskedDy()"
// Detection of nchannels shouldn't be necessary, instead check results().is<float>() or results.is<Color3>()
template<int WidthT> class BatchedTextureOutputs {
public:
explicit BatchedTextureOutputs(void* result, bool resultHasDerivs,
int chans, void* alpha, bool alphaHasDerivs,
void* errormessage, Mask<WidthT> mask)
: m_result(result)
, m_resultHasDerivs(resultHasDerivs)
, m_resultType((chans == 1) ? TypeFloat : TypeColor)
, m_alpha(alpha)
, m_alphaHasDerivs(alphaHasDerivs)
, m_errormessage(errormessage)
, m_mask(mask)
{
ASSERT(chans == 1 || chans == 3);
}
OSL_FORCEINLINE Mask<WidthT> mask() const { return m_mask; }
// The return value will be Masked<float, WidthT> or Masked<Vec3, WidthT>
OSL_FORCEINLINE MaskedData<WidthT> result()
{
return MaskedData<WidthT>(m_resultType, m_resultHasDerivs, m_mask,
m_result);
}
// The return value maybe invalid or be Masked<float, WidthT>
OSL_FORCEINLINE MaskedData<WidthT> alpha()
{
return MaskedData<WidthT>(TypeFloat, m_alphaHasDerivs, m_mask, m_alpha);
}
// The return value maybe invalid or be Masked<ustring, WidthT>
OSL_FORCEINLINE MaskedData<WidthT> errormessage()
{
return MaskedData<WidthT>(TypeString, false, m_mask, m_errormessage);
}
private:
void* m_result;
bool m_resultHasDerivs;
TypeDesc m_resultType;
void* m_alpha;
bool m_alphaHasDerivs;
void* m_errormessage;
Mask<WidthT> m_mask;
};
#define __OSL_USING_BATCHED_TEXTURE(WIDTH_OF_OSL_DATA) \
using BatchedTextureOutputs \
= OSL_NAMESPACE::BatchedTextureOutputs<WIDTH_OF_OSL_DATA>; \
using BatchedTextureOptions \
= OSL_NAMESPACE::BatchedTextureOptions<WIDTH_OF_OSL_DATA>;
#undef OSL_USING_DATA_WIDTH
#ifdef __OSL_USING_SHADERGLOBALS
# define OSL_USING_DATA_WIDTH(WIDTH_OF_OSL_DATA) \
__OSL_USING_WIDE(WIDTH_OF_OSL_DATA) \
__OSL_USING_SHADERGLOBALS(WIDTH_OF_OSL_DATA) \
__OSL_USING_BATCHED_TEXTURE(WIDTH_OF_OSL_DATA)
#else
# define OSL_USING_DATA_WIDTH(WIDTH_OF_OSL_DATA) \
__OSL_USING_WIDE(WIDTH_OF_OSL_DATA) \
__OSL_USING_BATCHED_TEXTURE(WIDTH_OF_OSL_DATA)
#endif
OSL_NAMESPACE_EXIT