diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 73137636f6e..c9ac7de1910 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -841,9 +841,11 @@ if(WITH_GTESTS) tests/gpu_testing.cc tests/framebuffer_test.cc + tests/immediate_test.cc tests/index_buffer_test.cc tests/push_constants_test.cc tests/shader_test.cc + tests/state_blend_test.cc tests/storage_buffer_test.cc tests/texture_test.cc diff --git a/source/blender/gpu/tests/immediate_test.cc b/source/blender/gpu/tests/immediate_test.cc new file mode 100644 index 00000000000..64fa79b21b6 --- /dev/null +++ b/source/blender/gpu/tests/immediate_test.cc @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "GPU_framebuffer.h" +#include "GPU_immediate.h" +#include "GPU_shader_builtin.h" +#include "gpu_testing.hh" + +#include "BLI_math_vector.hh" + +namespace blender::gpu::tests { + +static constexpr int Size = 256; + +static void test_immediate_one_plane() +{ + GPUOffScreen *offscreen = GPU_offscreen_create(Size, + Size, + false, + GPU_RGBA16F, + GPU_TEXTURE_USAGE_ATTACHMENT | + GPU_TEXTURE_USAGE_HOST_READ, + nullptr); + BLI_assert(offscreen != nullptr); + GPU_offscreen_bind(offscreen, false); + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + float4 color(1.0, 0.5, 0.25, 1.0); + immUniformColor4fv(color); + immBegin(GPU_PRIM_TRI_STRIP, 4); + immVertex3f(pos, -1.0f, 1.0f, 0.0f); + immVertex3f(pos, 1.0f, 1.0f, 0.0f); + immVertex3f(pos, -1.0f, -1.0f, 0.0f); + immVertex3f(pos, 1.0f, -1.0f, 0.0f); + immEnd(); + + GPU_offscreen_unbind(offscreen, false); + GPU_flush(); + + /* Read back data and perform some basic tests. */ + float read_data[4 * Size * Size]; + GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_data); + for (int pixel_index = 0; pixel_index < Size * Size; pixel_index++) { + float4 read_color = float4(&read_data[pixel_index * 4]); + EXPECT_EQ(read_color, color); + } + + GPU_offscreen_free(offscreen); +} +GPU_TEST(immediate_one_plane) + +/** + * Draws two planes with two different colors. + * - Tests that both planes are stored in the same buffer (depends on backend). + * - Test that data of the first plane isn't overwritten by the second plane. + * (push constants, buffer, bind points etc.) + */ +static void test_immediate_two_planes() +{ + GPUOffScreen *offscreen = GPU_offscreen_create(Size, + Size, + false, + GPU_RGBA16F, + GPU_TEXTURE_USAGE_ATTACHMENT | + GPU_TEXTURE_USAGE_HOST_READ, + nullptr); + BLI_assert(offscreen != nullptr); + GPU_offscreen_bind(offscreen, false); + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + float4 color(1.0, 0.5, 0.25, 1.0); + immUniformColor4fv(color); + immBegin(GPU_PRIM_TRI_STRIP, 4); + immVertex3f(pos, -1.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, -1.0f, -1.0f, 0.0f); + immVertex3f(pos, 0.0f, -1.0f, 0.0f); + immEnd(); + + float4 color2(0.25, 0.5, 1.0, 1.0); + immUniformColor4fv(color2); + immBegin(GPU_PRIM_TRI_STRIP, 4); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, 1.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, -1.0f, 0.0f); + immVertex3f(pos, 1.0f, -1.0f, 0.0f); + immEnd(); + + GPU_offscreen_unbind(offscreen, false); + GPU_flush(); + + /* Read back data and perform some basic tests. + * Not performing detailed tests as there might be driver specific limitations. */ + float read_data[4 * Size * Size]; + GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_data); + int64_t color_num = 0; + int64_t color2_num = 0; + for (int pixel_index = 0; pixel_index < Size * Size; pixel_index++) { + float4 read_color = float4(&read_data[pixel_index * 4]); + if (read_color == color) { + color_num++; + } + else if (read_color == color2) { + color2_num++; + } + else { + EXPECT_TRUE(read_color == color || read_color == color2); + } + } + EXPECT_TRUE(color_num > 0); + EXPECT_TRUE(color2_num > 0); + + GPU_offscreen_free(offscreen); +} +GPU_TEST(immediate_two_planes) + +} // namespace blender::gpu::tests diff --git a/source/blender/gpu/tests/state_blend_test.cc b/source/blender/gpu/tests/state_blend_test.cc new file mode 100644 index 00000000000..70571dceaeb --- /dev/null +++ b/source/blender/gpu/tests/state_blend_test.cc @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "gpu_testing.hh" + +#include "GPU_batch.h" +#include "GPU_batch_presets.h" +#include "GPU_framebuffer.h" +#include "GPU_matrix.h" + +#include "BLI_math_vector.hh" + +#include "intern/draw_cache.h" + +namespace blender::gpu::tests { + +template +void blend_test(float4 source_a, float4 source_b, float4 expected_result) +{ + GPUOffScreen *offscreen = GPU_offscreen_create(1, + 1, + false, + GPU_RGBA16F, + GPU_TEXTURE_USAGE_ATTACHMENT | + GPU_TEXTURE_USAGE_HOST_READ, + nullptr); + BLI_assert(offscreen != nullptr); + GPU_offscreen_bind(offscreen, false); + GPUTexture *color_texture = GPU_offscreen_color_texture(offscreen); + GPU_texture_clear(color_texture, GPU_DATA_FLOAT, source_a); + + GPUBatch *batch = DRW_cache_quad_get(); + + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GPU_batch_uniform_4fv(batch, "color", source_b); + GPU_blend(blend_type); + + GPU_batch_draw(batch); + GPU_offscreen_unbind(offscreen, false); + GPU_flush(); + + float4 read_back; + GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); + GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_back); + EXPECT_EQ(read_back, expected_result); + + GPU_offscreen_free(offscreen); + DRW_shape_cache_free(); +} + +static void test_blend_none() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.0f, 1.0f, 0.0f, 0.5f)); +} +GPU_TEST(blend_none) + +static void test_blend_alpha() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.5f, 0.5f, 0.5f, 1.0f)); +} +GPU_TEST(blend_alpha) + +static void test_blend_alpha_premult() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.5f, 1.0f, 0.5f, 1.0f)); +} +GPU_TEST(blend_alpha_premult) + +static void test_blend_additive() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(1.0f, 0.5f, 1.0f, 1.0f)); +} +GPU_TEST(blend_additive) + +static void test_blend_additive_premult() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(1.0f, 1.0f, 1.0f, 1.5f)); +} +GPU_TEST(blend_additive_premult) + +static void test_blend_multiply() +{ + blend_test(float4(1.0f, 0.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.0f, 0.0f, 0.0f, 0.5f)); +} +GPU_TEST(blend_multiply) + +static void test_blend_subtract() +{ + blend_test(float4(1.0f, 1.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(1.0f, 0.0f, 1.0f, 0.5f)); +} +GPU_TEST(blend_subtract) + +static void test_blend_invert() +{ + blend_test(float4(1.0f, 1.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.0f, 0.0f, 0.0f, 1.0f)); +} +GPU_TEST(blend_invert) + +static void test_blend_oit() +{ + blend_test(float4(1.0f, 1.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(1.0f, 2.0f, 1.0f, 0.5f)); +} +GPU_TEST(blend_oit) + +static void test_blend_background() +{ + blend_test(float4(1.0f, 1.0f, 1.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 0.5f), + float4(0.5f, 0.5f, 0.5f, 0.5f)); +} +GPU_TEST(blend_background) + +} // namespace blender::gpu::tests