Vulkan: Push constants #104880
|
@ -61,7 +61,7 @@ GPU_SHADER_CREATE_INFO(gpu_push_constants_base_test)
|
|||
.storage_buf(0, Qualifier::WRITE, "float", "data_out[]")
|
||||
.compute_source("gpu_push_constants_test.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_push_constants_packed_test)
|
||||
GPU_SHADER_CREATE_INFO(gpu_push_constants_test)
|
||||
.additional_info("gpu_push_constants_base_test")
|
||||
.push_constant(Type::FLOAT, "float_in")
|
||||
.push_constant(Type::VEC2, "vec2_in")
|
||||
|
@ -71,7 +71,7 @@ GPU_SHADER_CREATE_INFO(gpu_push_constants_packed_test)
|
|||
|
||||
/* Push constants size test. */
|
||||
GPU_SHADER_CREATE_INFO(gpu_push_constants_128bytes_test)
|
||||
.additional_info("gpu_push_constants_packed_test")
|
||||
.additional_info("gpu_push_constants_test")
|
||||
.push_constant(Type::FLOAT, "filler", 20)
|
||||
.do_static_compilation(true);
|
||||
|
||||
|
|
|
@ -8,13 +8,122 @@
|
|||
#include "GPU_storage_buffer.h"
|
||||
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "gpu_testing.hh"
|
||||
|
||||
namespace blender::gpu::tests {
|
||||
struct CallData {
|
||||
GPUStorageBuf *ssbo = nullptr;
|
||||
Vector<float> data;
|
||||
|
||||
static void push_constants(const char *info_name)
|
||||
float float_in;
|
||||
float2 vec2_in;
|
||||
float3 vec3_in;
|
||||
float4 vec4_in;
|
||||
|
||||
void init_ssbo(size_t num_floats)
|
||||
{
|
||||
if (ssbo == nullptr) {
|
||||
ssbo = GPU_storagebuf_create_ex(
|
||||
num_floats * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
|
||||
data.resize(num_floats);
|
||||
}
|
||||
}
|
||||
|
||||
~CallData()
|
||||
{
|
||||
if (ssbo != nullptr) {
|
||||
GPU_storagebuf_free(ssbo);
|
||||
ssbo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void generate_test_data(const float components_mul, const float component_mul)
|
||||
Jeroen-Bakker marked this conversation as resolved
|
||||
{
|
||||
float_in = components_mul;
|
||||
vec2_in = float2(components_mul * 2.0, components_mul * 2.0 + component_mul);
|
||||
vec3_in = float3(components_mul * 3.0,
|
||||
components_mul * 3.0 + component_mul,
|
||||
components_mul * 3.0 + component_mul * 2.0);
|
||||
vec4_in = float4(components_mul * 4.0,
|
||||
components_mul * 4.0 + component_mul,
|
||||
components_mul * 4.0 + component_mul * 2.0,
|
||||
components_mul * 4.0 + component_mul * 3.0);
|
||||
}
|
||||
|
||||
void read_back()
|
||||
{
|
||||
GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
|
||||
GPU_storagebuf_read(ssbo, data.data());
|
||||
}
|
||||
|
||||
void validate()
|
||||
{
|
||||
/* Check the results. */
|
||||
EXPECT_EQ(data[0], float_in);
|
||||
EXPECT_EQ(data[1], vec2_in.x);
|
||||
EXPECT_EQ(data[2], vec2_in.y);
|
||||
EXPECT_EQ(data[3], vec3_in.x);
|
||||
EXPECT_EQ(data[4], vec3_in.y);
|
||||
EXPECT_EQ(data[5], vec3_in.z);
|
||||
EXPECT_EQ(data[6], vec4_in.x);
|
||||
EXPECT_EQ(data[7], vec4_in.y);
|
||||
EXPECT_EQ(data[8], vec4_in.z);
|
||||
EXPECT_EQ(data[9], vec4_in.w);
|
||||
}
|
||||
};
|
||||
|
||||
struct Shader {
|
||||
GPUShader *shader = nullptr;
|
||||
Vector<CallData> call_datas;
|
||||
|
||||
~Shader()
|
||||
{
|
||||
if (shader != nullptr) {
|
||||
GPU_shader_unbind();
|
||||
GPU_shader_free(shader);
|
||||
}
|
||||
}
|
||||
|
||||
void init_shader(const char *info_name)
|
||||
{
|
||||
if (shader == nullptr) {
|
||||
shader = GPU_shader_create_from_info_name(info_name);
|
||||
EXPECT_NE(shader, nullptr);
|
||||
GPU_shader_bind(shader);
|
||||
}
|
||||
}
|
||||
|
||||
CallData &new_call()
|
||||
{
|
||||
CallData call_data;
|
||||
call_datas.append(call_data);
|
||||
return call_datas.last();
|
||||
}
|
||||
|
||||
void bind(CallData &call_data)
|
||||
{
|
||||
GPU_storagebuf_bind(call_data.ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));
|
||||
}
|
||||
|
||||
void update_push_constants(const CallData &call_data)
|
||||
{
|
||||
GPU_shader_uniform_1f(shader, "float_in", call_data.float_in);
|
||||
GPU_shader_uniform_2fv(shader, "vec2_in", call_data.vec2_in);
|
||||
GPU_shader_uniform_3fv(shader, "vec3_in", call_data.vec3_in);
|
||||
GPU_shader_uniform_4fv(shader, "vec4_in", call_data.vec4_in);
|
||||
}
|
||||
|
||||
void dispatch()
|
||||
{
|
||||
GPU_compute_dispatch(shader, 1, 1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/** Test the given info when doing a single call. */
|
||||
static void do_push_constants_test(const char *info_name, const int num_calls_simultaneously = 1)
|
||||
{
|
||||
if (!GPU_compute_shader_support() && !GPU_shader_storage_buffer_objects_support()) {
|
||||
/* We can't test as a the platform does not support compute shaders. */
|
||||
|
@ -24,75 +133,79 @@ static void push_constants(const char *info_name)
|
|||
|
||||
static constexpr uint SIZE = 16;
|
||||
|
||||
/* Build compute shader. */
|
||||
GPUShader *shader = GPU_shader_create_from_info_name(info_name);
|
||||
EXPECT_NE(shader, nullptr);
|
||||
GPU_shader_bind(shader);
|
||||
Shader shader;
|
||||
shader.init_shader(info_name);
|
||||
|
||||
/* Construct SSBO. */
|
||||
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
|
||||
SIZE * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
|
||||
GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));
|
||||
|
||||
const float float_in = 10.0f;
|
||||
const float2 vec2_in(20.0f, 21.0f);
|
||||
const float3 vec3_in(30.0f, 31.0f, 32.0f);
|
||||
const float4 vec4_in(40.0f, 41.0f, 42.0f, 43.0f);
|
||||
GPU_shader_uniform_1f(shader, "float_in", float_in);
|
||||
GPU_shader_uniform_2fv(shader, "vec2_in", vec2_in);
|
||||
GPU_shader_uniform_3fv(shader, "vec3_in", vec3_in);
|
||||
GPU_shader_uniform_4fv(shader, "vec4_in", vec4_in);
|
||||
|
||||
/* Dispatch compute task. */
|
||||
GPU_compute_dispatch(shader, 1, 1, 1);
|
||||
|
||||
/* Check if compute has been done. */
|
||||
GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
|
||||
|
||||
/* Download the index buffer. */
|
||||
float data[SIZE];
|
||||
GPU_storagebuf_read(ssbo, data);
|
||||
|
||||
/* Check the results. */
|
||||
EXPECT_EQ(data[0], float_in);
|
||||
EXPECT_EQ(data[1], vec2_in.x);
|
||||
EXPECT_EQ(data[2], vec2_in.y);
|
||||
EXPECT_EQ(data[3], vec3_in.x);
|
||||
EXPECT_EQ(data[4], vec3_in.y);
|
||||
EXPECT_EQ(data[5], vec3_in.z);
|
||||
EXPECT_EQ(data[6], vec4_in.x);
|
||||
EXPECT_EQ(data[7], vec4_in.y);
|
||||
EXPECT_EQ(data[8], vec4_in.z);
|
||||
EXPECT_EQ(data[9], vec4_in.w);
|
||||
|
||||
/* Cleanup. */
|
||||
GPU_shader_unbind();
|
||||
GPU_storagebuf_free(ssbo);
|
||||
GPU_shader_free(shader);
|
||||
for (const int call_index : IndexRange(num_calls_simultaneously)) {
|
||||
CallData &call_data = shader.new_call();
|
||||
call_data.generate_test_data(call_index * 10.0, call_index * 1.0);
|
||||
call_data.init_ssbo(SIZE);
|
||||
shader.bind(call_data);
|
||||
shader.update_push_constants(call_data);
|
||||
shader.dispatch();
|
||||
}
|
||||
/* All calls will be "simultaneously" in flight. First readback will wait until the dispatches
|
||||
* have finished execution.*/
|
||||
for (const int call_index : IndexRange(num_calls_simultaneously)) {
|
||||
CallData &call_data = shader.call_datas[call_index];
|
||||
call_data.read_back();
|
||||
call_data.validate();
|
||||
}
|
||||
}
|
||||
|
||||
static void test_push_constants_packed()
|
||||
/* Test case with single call as sanity check, before we make it more interesting.*/
|
||||
static void test_push_constants()
|
||||
{
|
||||
push_constants("gpu_push_constants_packed_test");
|
||||
do_push_constants_test("gpu_push_constants_test");
|
||||
}
|
||||
GPU_TEST(push_constants_packed)
|
||||
GPU_TEST(push_constants)
|
||||
|
||||
static void test_push_constants_128bytes()
|
||||
{
|
||||
push_constants("gpu_push_constants_128bytes_test");
|
||||
do_push_constants_test("gpu_push_constants_128bytes_test");
|
||||
}
|
||||
GPU_TEST(push_constants_128bytes)
|
||||
|
||||
static void test_push_constants_256bytes()
|
||||
{
|
||||
push_constants("gpu_push_constants_256bytes_test");
|
||||
do_push_constants_test("gpu_push_constants_256bytes_test");
|
||||
}
|
||||
GPU_TEST(push_constants_256bytes)
|
||||
|
||||
static void test_push_constants_512bytes()
|
||||
{
|
||||
push_constants("gpu_push_constants_512bytes_test");
|
||||
do_push_constants_test("gpu_push_constants_512bytes_test");
|
||||
}
|
||||
GPU_TEST(push_constants_512bytes)
|
||||
|
||||
#if 0
|
||||
/* Schedule multiple simultaneously. */
|
||||
/* These test have been disabled for now as this will to be solved in a separate PR.
|
||||
* - DescriptorSets may not be altered, when they are in the command queue or being executed.
|
||||
*/
|
||||
static void test_push_constants_multiple()
|
||||
{
|
||||
do_push_constants_test("gpu_push_constants_test", 10);
|
||||
}
|
||||
GPU_TEST(push_constants_multiple)
|
||||
|
||||
static void test_push_constants_multiple_128bytes()
|
||||
{
|
||||
do_push_constants_test("gpu_push_constants_128bytes_test", 10);
|
||||
}
|
||||
GPU_TEST(push_constants_multiple_128bytes)
|
||||
|
||||
static void test_push_constants_multiple_256bytes()
|
||||
{
|
||||
do_push_constants_test("gpu_push_constants_256bytes_test", 10);
|
||||
}
|
||||
GPU_TEST(push_constants_multiple_256bytes)
|
||||
|
||||
static void test_push_constants_multiple_512bytes()
|
||||
{
|
||||
do_push_constants_test("gpu_push_constants_512bytes_test", 10);
|
||||
}
|
||||
GPU_TEST(push_constants_multiple_512bytes)
|
||||
#endif
|
||||
|
||||
} // namespace blender::gpu::tests
|
Loading…
Reference in New Issue
components_mul > vector_mul
component_mul > scalar_mul