Blender V4.3
vk_data_conversion_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
8#include "vk_device.hh"
9
11
12namespace blender::gpu::tests {
13
14TEST(VulkanDataConversion, clamp_negative_to_zero)
15{
16 const uint32_t f32_2 = 0b11000000000000000000000000000000;
17 const uint32_t f32_inf_min = 0b11111111100000000000000000000000;
18 const uint32_t f32_inf_max = 0b01111111100000000000000000000000;
19 const uint32_t f32_nan = 0b11111111111111111111111111111111;
20
21 /* F32(-2) doesn't fit in F11 as F11 only supports unsigned values. Clamp to zero. */
22 const uint32_t f11_0_expected = 0b00000000000;
23 const uint32_t f11_2_expected = 0b10000000000;
24 const uint32_t f11_inf_expected = 0b11111000000;
25 const uint32_t f11_nan_expected = 0b11111111111;
26 {
28 EXPECT_EQ(f11_0, f11_0_expected);
30 EXPECT_EQ(f11_0b, f11_0_expected);
32 EXPECT_EQ(f11_inf, f11_inf_expected);
34 EXPECT_EQ(f11_nan, f11_nan_expected);
35 }
36
37 /* F32(-2) doesn't fit in F11 as F11 only supports unsigned values. Make absolute. */
38 {
40 EXPECT_EQ(f11_2, f11_2_expected);
42 EXPECT_EQ(f11_inf, f11_inf_expected);
44 EXPECT_EQ(f11_infb, f11_inf_expected);
46 EXPECT_EQ(f11_nan, f11_nan_expected);
47 }
48}
49
50TEST(VulkanDataConversion, infinity_upper)
51{
52 const uint32_t f32_inf = 0b01111111100000000000000000000000;
53
54 const uint32_t f11_inf_expected = 0b11111000000;
56 EXPECT_EQ(f11_inf, f11_inf_expected);
57
58 const uint32_t f10_inf_expected = 0b1111100000;
60 EXPECT_EQ(f10_inf, f10_inf_expected);
61}
62
63TEST(VulkanDataConversion, vertex_format_i32_as_float)
64{
65 GPUVertFormat source_format;
66 GPU_vertformat_clear(&source_format);
68 VertexFormat_pack(&source_format);
69
70 union TestData {
71 int2 pos_i;
72 float2 pos_fl;
73 };
74 TestData test_data[4];
75 test_data[0].pos_i = int2(0, 1);
76 test_data[1].pos_i = int2(1, 2);
77 test_data[2].pos_i = int2(2, 3);
78 test_data[3].pos_i = int2(3, 4);
79
80 VKWorkarounds workarounds = {};
81 VertexFormatConverter converter;
82 converter.init(&source_format, workarounds);
83
84 EXPECT_TRUE(converter.needs_conversion());
85
86 converter.convert(&test_data, &test_data, 4);
87
88 EXPECT_EQ(test_data[0].pos_fl, float2(0.0, 1.0));
89 EXPECT_EQ(test_data[1].pos_fl, float2(1.0, 2.0));
90 EXPECT_EQ(test_data[2].pos_fl, float2(2.0, 3.0));
91 EXPECT_EQ(test_data[3].pos_fl, float2(3.0, 4.0));
92}
93
94TEST(VulkanDataConversion, vertex_format_u32_as_float)
95{
96 GPUVertFormat source_format;
97 GPU_vertformat_clear(&source_format);
99 VertexFormat_pack(&source_format);
100
101 union TestData {
102 uint3 pos_u;
103 float3 pos_fl;
104 };
105 TestData test_data[4];
106 test_data[0].pos_u = uint3(0, 1, 2);
107 test_data[1].pos_u = uint3(1, 2, 3);
108 test_data[2].pos_u = uint3(2, 3, 4);
109 test_data[3].pos_u = uint3(3, 4, 5);
110
111 VKWorkarounds workarounds = {};
112 VertexFormatConverter converter;
113 converter.init(&source_format, workarounds);
114
115 EXPECT_TRUE(converter.needs_conversion());
116
117 converter.convert(&test_data, &test_data, 4);
118
119 EXPECT_EQ(test_data[0].pos_fl, float3(0.0, 1.0, 2.0));
120 EXPECT_EQ(test_data[1].pos_fl, float3(1.0, 2.0, 3.0));
121 EXPECT_EQ(test_data[2].pos_fl, float3(2.0, 3.0, 4.0));
122 EXPECT_EQ(test_data[3].pos_fl, float3(3.0, 4.0, 5.0));
123}
124
125TEST(VulkanDataConversion, vertex_format_r8g8b8)
126{
127 GPUVertFormat source_format;
128 GPU_vertformat_clear(&source_format);
130 VertexFormat_pack(&source_format);
131
132 struct SourceData {
134 uint8_t _pad;
135 };
136 struct DeviceData {
138 };
139
140 SourceData test_data_in[4];
141 test_data_in[0].color = uchar3(255, 0, 0);
142 test_data_in[1].color = uchar3(255, 255, 255);
143 test_data_in[2].color = uchar3(255, 0, 0);
144 test_data_in[3].color = uchar3(255, 255, 255);
145
146 VKWorkarounds workarounds = {};
147 VertexFormatConverter converter;
148 converter.init(&source_format, workarounds);
149
150 EXPECT_FALSE(converter.needs_conversion());
151
152 /* Enable workaround for r8g8b8 vertex formats. */
153 workarounds.vertex_formats.r8g8b8 = true;
154
155 converter.init(&source_format, workarounds);
156 EXPECT_TRUE(converter.needs_conversion());
157
158 DeviceData test_data_out[4];
159 converter.convert(test_data_out, test_data_in, 4);
160
161 EXPECT_EQ(test_data_out[0].color, uchar4(255, 0, 0, 255));
162 EXPECT_EQ(test_data_out[1].color, uchar4(255, 255, 255, 255));
163 EXPECT_EQ(test_data_out[2].color, uchar4(255, 0, 0, 255));
164 EXPECT_EQ(test_data_out[3].color, uchar4(255, 255, 255, 255));
165}
166
167TEST(VulkanDataConversion, vertex_format_multiple_attributes)
168{
169 GPUVertFormat source_format;
170 GPU_vertformat_clear(&source_format);
171 GPU_vertformat_attr_add(&source_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
173 GPU_vertformat_attr_add(&source_format, "flag", GPU_COMP_U32, 1, GPU_FETCH_INT);
174 VertexFormat_pack(&source_format);
175
176 struct SourceData {
177 float3 pos;
179 uint8_t _pad;
180 uint flag;
181 };
182 struct DeviceData {
183 float3 pos;
185 uint flag;
186 };
187
188 SourceData test_data_in[4];
189 test_data_in[0] = {float3(1.0, 2.0, 3.0), uchar3(255, 0, 0), 0, 0};
190 test_data_in[1] = {float3(4.0, 5.0, 6.0), uchar3(0, 255, 0), 0, 1};
191 test_data_in[2] = {float3(7.0, 8.0, 9.0), uchar3(0, 0, 255), 0, 2};
192 test_data_in[3] = {float3(10.0, 11.0, 12.0), uchar3(255, 255, 255), 0, 3};
193
194 VKWorkarounds workarounds = {};
195 workarounds.vertex_formats.r8g8b8 = true;
196 VertexFormatConverter converter;
197 converter.init(&source_format, workarounds);
198 EXPECT_TRUE(converter.needs_conversion());
199
200 DeviceData test_data_out[4];
201 converter.convert(test_data_out, test_data_in, 4);
202
203 DeviceData expected_data[4];
204 expected_data[0] = {float3(1.0, 2.0, 3.0), uchar4(255, 0, 0, 255), 0};
205 expected_data[1] = {float3(4.0, 5.0, 6.0), uchar4(0, 255, 0, 255), 1};
206 expected_data[2] = {float3(7.0, 8.0, 9.0), uchar4(0, 0, 255, 255), 2};
207 expected_data[3] = {float3(10.0, 11.0, 12.0), uchar4(255, 255, 255, 255), 3};
208 for (int i : IndexRange(4)) {
209 EXPECT_EQ(test_data_out[i].pos, expected_data[i].pos);
210 EXPECT_EQ(test_data_out[i].color, expected_data[i].color);
211 EXPECT_EQ(test_data_out[i].flag, expected_data[i].flag);
212 }
213}
214
215TEST(VulkanDataConversion, texture_rgb16f_as_floats_to_rgba16f)
216{
217 const size_t num_pixels = 4;
218 const float input[] = {
219 1.0,
220 0.5,
221 0.2,
222
223 0.2,
224 1.0,
225 0.3,
226
227 0.4,
228 0.2,
229 1.0,
230
231 1.0,
232 1.0,
233 1.0,
234 };
235
236 uint64_t device[num_pixels];
237 convert_host_to_device(device, input, num_pixels, GPU_DATA_FLOAT, GPU_RGB16F, GPU_RGBA16F);
238
239 float read_back[num_pixels * 3];
240 convert_device_to_host(read_back, device, num_pixels, GPU_DATA_FLOAT, GPU_RGB16F, GPU_RGBA16F);
241
242 for (int i : IndexRange(num_pixels * 3)) {
243 EXPECT_NEAR(input[i], read_back[i], 0.01);
244 }
245}
246
247TEST(VulkanDataConversion, texture_rgb32f_as_floats_to_rgba32f)
248{
249 const size_t num_pixels = 4;
250 const float input[] = {
251 1.0,
252 0.5,
253 0.2,
254
255 0.2,
256 1.0,
257 0.3,
258
259 0.4,
260 0.2,
261 1.0,
262
263 1.0,
264 1.0,
265 1.0,
266 };
267
268 float device[num_pixels * 4];
269 convert_host_to_device(device, input, num_pixels, GPU_DATA_FLOAT, GPU_RGB32F, GPU_RGBA32F);
270
271 float read_back[num_pixels * 3];
272 convert_device_to_host(read_back, device, num_pixels, GPU_DATA_FLOAT, GPU_RGB32F, GPU_RGBA32F);
273
274 for (int i : IndexRange(num_pixels * 3)) {
275 EXPECT_NEAR(input[i], read_back[i], 0.01);
276 }
277}
278
279} // namespace blender::gpu::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
unsigned int uint
@ GPU_DATA_FLOAT
@ GPU_RGB32F
@ GPU_RGB16F
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
void GPU_vertformat_clear(GPUVertFormat *)
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U32
@ GPU_COMP_U8
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
void VertexFormat_pack(GPUVertFormat *format)
static Vector< int32_t > test_data()
TEST(VulkanDataConversion, clamp_negative_to_zero)
void convert_host_to_device(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, eGPUTextureFormat host_texture_format, eGPUTextureFormat device_format)
void convert_device_to_host(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, eGPUTextureFormat host_texture_format, eGPUTextureFormat device_format)
uint32_t convert_float_formats(uint32_t value)
blender::VecBase< uint8_t, 3 > uchar3
VecBase< uint32_t, 3 > uint3
blender::VecBase< uint8_t, 4 > uchar4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
unsigned int uint32_t
Definition stdint.h:80
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
struct blender::gpu::VKWorkarounds::@669 vertex_formats
void init(const GPUVertFormat *vertex_format, const VKWorkarounds &workarounds)
void convert(void *device_data, const void *src_data, const uint vertex_len) const
uint8_t flag
Definition wm_window.cc:138