Compare commits
16 Commits
arcpatch-D
...
temp-gpu-u
Author | SHA1 | Date | |
---|---|---|---|
cb9e251440 | |||
34e3468d89 | |||
9bc3a313fc | |||
ebb8c9c025 | |||
92c9a36c32 | |||
79ec0eec53 | |||
1259271a78 | |||
b60e61396b | |||
5437af2e6f | |||
dbcdc536b6 | |||
9309287687 | |||
8ff67b51d1 | |||
9f7bca255e | |||
8f2bb1b1f0 | |||
0271c736a9 | |||
dd31aebf11 |
Submodule release/datafiles/locale updated: 4833954c0a...1ab25ca4f2
Submodule release/scripts/addons updated: f86f25e622...7884a7bbf9
Submodule release/scripts/addons_contrib updated: 5a82baad9f...fd1bed98c9
@@ -401,6 +401,7 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
|
||||
prim_type,
|
||||
varying_names,
|
||||
varying_count,
|
||||
GPU_SHADER_BLOCK_CUSTOM,
|
||||
__func__);
|
||||
}
|
||||
|
||||
|
@@ -81,6 +81,7 @@ set(SRC
|
||||
intern/gpu_select_pick.c
|
||||
intern/gpu_select_sample_query.cc
|
||||
intern/gpu_shader.cc
|
||||
intern/gpu_shader_block.cc
|
||||
intern/gpu_shader_builtin.c
|
||||
intern/gpu_shader_log.cc
|
||||
intern/gpu_shader_interface.cc
|
||||
@@ -400,6 +401,7 @@ if(WITH_GTESTS)
|
||||
tests/gpu_index_buffer_test.cc
|
||||
tests/gpu_shader_builtin_test.cc
|
||||
tests/gpu_shader_test.cc
|
||||
tests/gpu_shader_block_test.cc
|
||||
|
||||
tests/gpu_testing.hh
|
||||
)
|
||||
|
@@ -23,6 +23,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GPU_shader_block_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -64,10 +66,12 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
const eGPUShaderTFBType tf_type,
|
||||
const char **tf_names,
|
||||
const int tf_count,
|
||||
const GPUShaderBlockType uniform_struct_type,
|
||||
const char *shname);
|
||||
|
||||
struct GPU_ShaderCreateFromArray_Params {
|
||||
const char **vert, **geom, **frag, **defs;
|
||||
const GPUShaderBlockType shader_block;
|
||||
};
|
||||
struct GPUShader *GPU_shader_create_from_arrays_impl(
|
||||
const struct GPU_ShaderCreateFromArray_Params *params, const char *func, int line);
|
||||
@@ -122,6 +126,7 @@ typedef enum {
|
||||
GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */
|
||||
GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */
|
||||
GPU_UNIFORM_BLOCK_INFO, /* infoBlock */
|
||||
GPU_UNIFORM_BLOCK_SHADER, /* shaderBlock */
|
||||
|
||||
GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */
|
||||
} GPUUniformBlockBuiltin;
|
||||
|
51
source/blender/gpu/GPU_shader_block_types.h
Normal file
51
source/blender/gpu/GPU_shader_block_types.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2021 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum GPUShaderBlockType {
|
||||
GPU_SHADER_BLOCK_CUSTOM = 0,
|
||||
GPU_SHADER_BLOCK_3D_COLOR,
|
||||
GPU_NUM_SHADER_BLOCK_TYPES, /* Special value, denotes number of structs. */
|
||||
} GPUShaderBlockType;
|
||||
|
||||
typedef struct GPUShaderBlock3dColor {
|
||||
float ModelMatrix[4][4];
|
||||
float ModelViewProjectionMatrix[4][4];
|
||||
float color[4];
|
||||
float WorldClipPlanes[6][4];
|
||||
int SrgbTransform;
|
||||
int _pad[3];
|
||||
} GPUShaderBlock3dColor;
|
||||
|
||||
BLI_STATIC_ASSERT_ALIGN(GPUShaderBlock3dColor, 16)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
@@ -32,6 +34,11 @@
|
||||
#include "gpu_backend.hh"
|
||||
#include "gpu_context_private.hh"
|
||||
#include "gpu_shader_private.hh"
|
||||
#include "gpu_uniform_buffer_private.hh"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
static CLG_LogRef LOG = {"gpu.shader"};
|
||||
|
||||
extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
|
||||
|
||||
@@ -52,6 +59,31 @@ Shader::Shader(const char *sh_name)
|
||||
Shader::~Shader()
|
||||
{
|
||||
delete interface;
|
||||
delete m_shader_struct;
|
||||
}
|
||||
|
||||
const bool Shader::has_shader_block() const
|
||||
{
|
||||
return m_shader_struct;
|
||||
}
|
||||
|
||||
const bool Shader::shader_block_dirty_get() const
|
||||
{
|
||||
BLI_assert(m_shader_struct);
|
||||
return m_shader_struct->flags().is_dirty;
|
||||
}
|
||||
|
||||
void Shader::shader_block_update() const
|
||||
{
|
||||
BLI_assert(m_shader_struct);
|
||||
m_shader_struct->update();
|
||||
}
|
||||
|
||||
void Shader::shader_block_bind() const
|
||||
{
|
||||
BLI_assert(m_shader_struct);
|
||||
const int binding = interface->ubo_builtin(GPU_UNIFORM_BLOCK_SHADER);
|
||||
m_shader_struct->bind(binding);
|
||||
}
|
||||
|
||||
static void standard_defines(Vector<const char *> &sources)
|
||||
@@ -94,6 +126,7 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
const eGPUShaderTFBType tf_type,
|
||||
const char **tf_names,
|
||||
const int tf_count,
|
||||
const GPUShaderBlockType shader_block,
|
||||
const char *shname)
|
||||
{
|
||||
/* At least a vertex shader and a fragment shader are required, or only a compute shader. */
|
||||
@@ -102,6 +135,9 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
(computecode != nullptr)));
|
||||
|
||||
Shader *shader = GPUBackend::get()->shader_alloc(shname);
|
||||
if (shader_block != GPU_SHADER_BLOCK_CUSTOM) {
|
||||
shader->set_shader_struct(shader_block);
|
||||
}
|
||||
|
||||
if (vertcode) {
|
||||
Vector<const char *> sources;
|
||||
@@ -114,6 +150,10 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
if (defines) {
|
||||
sources.append(defines);
|
||||
}
|
||||
if (shader->m_shader_struct) {
|
||||
sources.append("#define GPU_SHADER_BLOCK\n");
|
||||
sources.append(shader->m_shader_struct->type_info().defines());
|
||||
}
|
||||
sources.append(vertcode);
|
||||
|
||||
shader->vertex_shader_from_glsl(sources);
|
||||
@@ -130,6 +170,10 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
if (defines) {
|
||||
sources.append(defines);
|
||||
}
|
||||
if (shader->m_shader_struct) {
|
||||
sources.append("#define GPU_SHADER_BLOCK\n");
|
||||
sources.append(shader->m_shader_struct->type_info().defines());
|
||||
}
|
||||
if (libcode) {
|
||||
sources.append(libcode);
|
||||
}
|
||||
@@ -145,6 +189,10 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
if (defines) {
|
||||
sources.append(defines);
|
||||
}
|
||||
if (shader->m_shader_struct) {
|
||||
sources.append("#define GPU_SHADER_BLOCK\n");
|
||||
sources.append(shader->m_shader_struct->type_info().defines());
|
||||
}
|
||||
sources.append(geomcode);
|
||||
|
||||
shader->geometry_shader_from_glsl(sources);
|
||||
@@ -160,6 +208,10 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
if (libcode) {
|
||||
sources.append(libcode);
|
||||
}
|
||||
if (shader->m_shader_struct) {
|
||||
sources.append("#define GPU_SHADER_BLOCK\n");
|
||||
sources.append(shader->m_shader_struct->type_info().defines());
|
||||
}
|
||||
sources.append(computecode);
|
||||
|
||||
shader->compute_shader_from_glsl(sources);
|
||||
@@ -175,6 +227,21 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (G.debug & G_DEBUG_GPU) {
|
||||
std::optional<GPUShaderBlockType> best_struct_type = find_smallest_shader_block(
|
||||
*shader->interface);
|
||||
if (best_struct_type) {
|
||||
if (/*uniform_struct_type != GPU_SHADER_BLOCK_CUSTOM &&*/
|
||||
shader_block != *best_struct_type) {
|
||||
CLOG_WARN(&LOG,
|
||||
"Found better matching uniform struct for '%s'; current %d, suggested %d",
|
||||
shname,
|
||||
static_cast<int>(shader_block),
|
||||
static_cast<int>(*best_struct_type));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return wrap(shader);
|
||||
}
|
||||
|
||||
@@ -205,6 +272,7 @@ GPUShader *GPU_shader_create(const char *vertcode,
|
||||
GPU_SHADER_TFB_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
GPU_SHADER_BLOCK_CUSTOM,
|
||||
shname);
|
||||
}
|
||||
|
||||
@@ -222,6 +290,7 @@ GPUShader *GPU_shader_create_compute(const char *computecode,
|
||||
GPU_SHADER_TFB_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
GPU_SHADER_BLOCK_CUSTOM,
|
||||
shname);
|
||||
}
|
||||
|
||||
@@ -249,6 +318,7 @@ GPUShader *GPU_shader_create_from_python(const char *vertcode,
|
||||
GPU_SHADER_TFB_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
GPU_SHADER_BLOCK_CUSTOM,
|
||||
"pyGPUShader");
|
||||
|
||||
MEM_SAFE_FREE(libcodecat);
|
||||
@@ -316,8 +386,17 @@ struct GPUShader *GPU_shader_create_from_arrays_impl(
|
||||
char name[64];
|
||||
BLI_snprintf(name, sizeof(name), "%s_%d", func, line);
|
||||
|
||||
GPUShader *sh = GPU_shader_create(
|
||||
str_dst[0].str, str_dst[1].str, str_dst[2].str, nullptr, str_dst[3].str, name);
|
||||
GPUShader *sh = GPU_shader_create_ex(str_dst[0].str,
|
||||
str_dst[1].str,
|
||||
str_dst[2].str,
|
||||
nullptr,
|
||||
nullptr,
|
||||
str_dst[3].str,
|
||||
GPU_SHADER_TFB_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
params->shader_block,
|
||||
name);
|
||||
|
||||
for (auto &i : str_dst) {
|
||||
if (i.is_alloc) {
|
||||
@@ -353,6 +432,13 @@ void GPU_shader_bind(GPUShader *gpu_shader)
|
||||
GPU_matrix_bind(gpu_shader);
|
||||
}
|
||||
}
|
||||
|
||||
if (shader->has_shader_block()) {
|
||||
if (shader->shader_block_dirty_get()) {
|
||||
shader->shader_block_update();
|
||||
}
|
||||
shader->shader_block_bind();
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_shader_unbind(void)
|
||||
|
313
source/blender/gpu/intern/gpu_shader_block.cc
Normal file
313
source/blender/gpu/intern/gpu_shader_block.cc
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2021 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "gpu_uniform_buffer_private.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "gpu_shader_block.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Attribute bindings
|
||||
* \{ */
|
||||
const int BUILTIN_BINDING_LOCATION_OFFSET = 1000;
|
||||
|
||||
static constexpr int to_binding_location(const GPUUniformBuiltin builtin_uniform)
|
||||
{
|
||||
return BUILTIN_BINDING_LOCATION_OFFSET + builtin_uniform;
|
||||
}
|
||||
|
||||
static GPUUniformBuiltin to_builtin_uniform(int location)
|
||||
{
|
||||
return static_cast<GPUUniformBuiltin>(location - BUILTIN_BINDING_LOCATION_OFFSET);
|
||||
}
|
||||
|
||||
static bool is_valid_location(int location)
|
||||
{
|
||||
int builtin_uniform = location - BUILTIN_BINDING_LOCATION_OFFSET;
|
||||
if (builtin_uniform < 0 || builtin_uniform >= GPU_NUM_UNIFORMS) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr ShaderBlockType::AttributeBinding determine_location_3d_color(
|
||||
const GPUUniformBuiltin builtin_uniform)
|
||||
{
|
||||
ShaderBlockType::AttributeBinding result = {-1, 0};
|
||||
|
||||
switch (builtin_uniform) {
|
||||
case GPU_UNIFORM_MODEL:
|
||||
result.location = to_binding_location(builtin_uniform);
|
||||
result.offset = offsetof(GPUShaderBlock3dColor, ModelMatrix);
|
||||
break;
|
||||
case GPU_UNIFORM_MVP:
|
||||
result.location = to_binding_location(builtin_uniform);
|
||||
result.offset = offsetof(GPUShaderBlock3dColor, ModelViewProjectionMatrix);
|
||||
break;
|
||||
case GPU_UNIFORM_COLOR:
|
||||
result.location = to_binding_location(builtin_uniform);
|
||||
result.offset = offsetof(GPUShaderBlock3dColor, color);
|
||||
break;
|
||||
case GPU_UNIFORM_CLIPPLANES:
|
||||
result.location = to_binding_location(builtin_uniform);
|
||||
result.offset = offsetof(GPUShaderBlock3dColor, WorldClipPlanes);
|
||||
break;
|
||||
case GPU_UNIFORM_SRGB_TRANSFORM:
|
||||
result.location = to_binding_location(builtin_uniform);
|
||||
result.offset = offsetof(GPUShaderBlock3dColor, SrgbTransform);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static constexpr ShaderBlockType::AttributeBinding determine_binding(
|
||||
const GPUShaderBlockType block_type, const GPUUniformBuiltin builtin_uniform)
|
||||
{
|
||||
|
||||
switch (block_type) {
|
||||
case GPU_SHADER_BLOCK_CUSTOM:
|
||||
case GPU_NUM_SHADER_BLOCK_TYPES:
|
||||
return {};
|
||||
|
||||
case GPU_SHADER_BLOCK_3D_COLOR:
|
||||
return determine_location_3d_color(builtin_uniform);
|
||||
};
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr std::array<const ShaderBlockType::AttributeBinding, GPU_NUM_UNIFORMS>
|
||||
builtin_uniforms_for_struct_type(const GPUShaderBlockType block_type)
|
||||
{
|
||||
return {
|
||||
determine_binding(block_type, GPU_UNIFORM_MODEL),
|
||||
determine_binding(block_type, GPU_UNIFORM_VIEW),
|
||||
determine_binding(block_type, GPU_UNIFORM_MODELVIEW),
|
||||
determine_binding(block_type, GPU_UNIFORM_PROJECTION),
|
||||
determine_binding(block_type, GPU_UNIFORM_VIEWPROJECTION),
|
||||
determine_binding(block_type, GPU_UNIFORM_MVP),
|
||||
determine_binding(block_type, GPU_UNIFORM_MODEL_INV),
|
||||
determine_binding(block_type, GPU_UNIFORM_VIEW_INV),
|
||||
determine_binding(block_type, GPU_UNIFORM_MODELVIEW_INV),
|
||||
determine_binding(block_type, GPU_UNIFORM_PROJECTION_INV),
|
||||
determine_binding(block_type, GPU_UNIFORM_VIEWPROJECTION_INV),
|
||||
determine_binding(block_type, GPU_UNIFORM_NORMAL),
|
||||
determine_binding(block_type, GPU_UNIFORM_ORCO),
|
||||
determine_binding(block_type, GPU_UNIFORM_CLIPPLANES),
|
||||
determine_binding(block_type, GPU_UNIFORM_COLOR),
|
||||
determine_binding(block_type, GPU_UNIFORM_BASE_INSTANCE),
|
||||
determine_binding(block_type, GPU_UNIFORM_RESOURCE_CHUNK),
|
||||
determine_binding(block_type, GPU_UNIFORM_RESOURCE_ID),
|
||||
determine_binding(block_type, GPU_UNIFORM_SRGB_TRANSFORM),
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr std::array<
|
||||
const std::array<const ShaderBlockType::AttributeBinding, GPU_NUM_UNIFORMS>,
|
||||
GPU_NUM_SHADER_BLOCK_TYPES>
|
||||
ATTRIBUTE_BINDINGS = {
|
||||
builtin_uniforms_for_struct_type(GPU_SHADER_BLOCK_CUSTOM),
|
||||
builtin_uniforms_for_struct_type(GPU_SHADER_BLOCK_3D_COLOR),
|
||||
};
|
||||
|
||||
static constexpr size_t data_size_for(const GPUShaderBlockType block_type)
|
||||
{
|
||||
switch (block_type) {
|
||||
case GPU_SHADER_BLOCK_CUSTOM:
|
||||
case GPU_NUM_SHADER_BLOCK_TYPES:
|
||||
return 0;
|
||||
|
||||
case GPU_SHADER_BLOCK_3D_COLOR:
|
||||
return sizeof(GPUShaderBlock3dColor);
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr StringRef DEFINES_3D_COLOR = R"(
|
||||
layout(std140) uniform shaderBlock {
|
||||
mat4 ModelMatrix;
|
||||
mat4 ModelViewProjectionMatrix;
|
||||
vec4 color;
|
||||
vec4 WorldClipPlanes[6];
|
||||
bool srgbTarget;
|
||||
};
|
||||
)";
|
||||
|
||||
static constexpr const char *defines_for(const GPUShaderBlockType type)
|
||||
{
|
||||
switch (type) {
|
||||
case GPU_SHADER_BLOCK_CUSTOM:
|
||||
case GPU_NUM_SHADER_BLOCK_TYPES:
|
||||
return nullptr;
|
||||
|
||||
case GPU_SHADER_BLOCK_3D_COLOR:
|
||||
return DEFINES_3D_COLOR.data();
|
||||
};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Struct type
|
||||
* \{ */
|
||||
|
||||
constexpr ShaderBlockType::ShaderBlockType(const GPUShaderBlockType type)
|
||||
: type(type),
|
||||
m_attribute_bindings(ATTRIBUTE_BINDINGS[type]),
|
||||
m_data_size(data_size_for(type)),
|
||||
m_defines(defines_for(type))
|
||||
{
|
||||
}
|
||||
|
||||
bool ShaderBlockType::AttributeBinding::has_binding() const
|
||||
{
|
||||
return location != -1;
|
||||
}
|
||||
|
||||
bool ShaderBlockType::has_all_builtin_uniforms(const ShaderInterface &interface) const
|
||||
{
|
||||
for (int i = 0; i < GPU_NUM_UNIFORMS; i++) {
|
||||
const GPUUniformBuiltin builtin_uniform = static_cast<const GPUUniformBuiltin>(i);
|
||||
const AttributeBinding &binding = attribute_binding(builtin_uniform);
|
||||
const bool builtin_is_used = interface.builtins_[i] != -1;
|
||||
const bool has_attribute = binding.has_binding();
|
||||
if (builtin_is_used && !has_attribute) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr std::array<ShaderBlockType, GPU_NUM_SHADER_BLOCK_TYPES> STRUCT_TYPE_INFOS = {
|
||||
ShaderBlockType(GPU_SHADER_BLOCK_CUSTOM),
|
||||
ShaderBlockType(GPU_SHADER_BLOCK_3D_COLOR),
|
||||
};
|
||||
|
||||
const ShaderBlockType &ShaderBlockType::get(const GPUShaderBlockType type)
|
||||
{
|
||||
return STRUCT_TYPE_INFOS[type];
|
||||
}
|
||||
|
||||
std::optional<const GPUShaderBlockType> find_smallest_shader_block(
|
||||
const ShaderInterface &interface)
|
||||
{
|
||||
if (!interface.has_builtin_uniforms()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (ShaderBlockType::get(GPU_SHADER_BLOCK_3D_COLOR).has_all_builtin_uniforms(interface)) {
|
||||
return std::make_optional(GPU_SHADER_BLOCK_3D_COLOR);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Struct type
|
||||
* \{ */
|
||||
|
||||
ShaderBlockBuffer::ShaderBlockBuffer(const GPUShaderBlockType type)
|
||||
: m_type_info(ShaderBlockType::get(type))
|
||||
{
|
||||
m_data = MEM_mallocN(m_type_info.data_size(), __func__);
|
||||
m_ubo = GPUBackend::get()->uniformbuf_alloc(m_type_info.data_size(), __func__);
|
||||
}
|
||||
|
||||
ShaderBlockBuffer::~ShaderBlockBuffer()
|
||||
{
|
||||
delete m_ubo;
|
||||
m_ubo = nullptr;
|
||||
MEM_freeN(m_data);
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
bool ShaderBlockBuffer::uniform_int(int location, int comp_len, int array_size, const int *data)
|
||||
{
|
||||
if (!is_valid_location(location)) {
|
||||
return false;
|
||||
}
|
||||
const GPUUniformBuiltin builtin_uniform = to_builtin_uniform(location);
|
||||
const ShaderBlockType::AttributeBinding &attribute = m_type_info.attribute_binding(
|
||||
builtin_uniform);
|
||||
|
||||
if (!attribute.has_binding()) {
|
||||
return false;
|
||||
}
|
||||
const size_t attribute_len = comp_len * array_size * sizeof(int);
|
||||
memcpy(((uint8_t *)m_data) + attribute.offset, data, attribute_len);
|
||||
m_flags.is_dirty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderBlockBuffer::uniform_float(int location,
|
||||
int comp_len,
|
||||
int array_size,
|
||||
const float *data)
|
||||
{
|
||||
if (!is_valid_location(location)) {
|
||||
return false;
|
||||
}
|
||||
const GPUUniformBuiltin builtin_uniform = to_builtin_uniform(location);
|
||||
const ShaderBlockType::AttributeBinding &attribute = m_type_info.attribute_binding(
|
||||
builtin_uniform);
|
||||
|
||||
if (!attribute.has_binding()) {
|
||||
return false;
|
||||
}
|
||||
const size_t attribute_len = comp_len * array_size * sizeof(float);
|
||||
memcpy(((uint8_t *)m_data) + attribute.offset, data, attribute_len);
|
||||
m_flags.is_dirty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderBlockBuffer::update()
|
||||
{
|
||||
if (m_flags.is_dirty) {
|
||||
m_ubo->update(m_data);
|
||||
m_flags.is_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderBlockBuffer::bind(int binding)
|
||||
{
|
||||
m_ubo->bind(binding);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::gpu
|
116
source/blender/gpu/intern/gpu_shader_block.hh
Normal file
116
source/blender/gpu/intern/gpu_shader_block.hh
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2021, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "GPU_shader_block_types.h"
|
||||
#include "gpu_backend.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
#include "gpu_uniform_buffer_private.hh"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
class ShaderBlockType {
|
||||
public:
|
||||
constexpr ShaderBlockType(const GPUShaderBlockType type);
|
||||
static const ShaderBlockType &get(const GPUShaderBlockType type);
|
||||
|
||||
bool has_all_builtin_uniforms(const ShaderInterface &interface) const;
|
||||
|
||||
GPUShaderBlockType type;
|
||||
struct AttributeBinding {
|
||||
int location = -1;
|
||||
size_t offset = 0;
|
||||
|
||||
bool has_binding() const;
|
||||
};
|
||||
|
||||
const AttributeBinding &attribute_binding(const GPUUniformBuiltin builtin_uniform) const
|
||||
{
|
||||
return m_attribute_bindings[builtin_uniform];
|
||||
}
|
||||
|
||||
size_t data_size() const
|
||||
{
|
||||
return m_data_size;
|
||||
}
|
||||
|
||||
const char *defines() const
|
||||
{
|
||||
return m_defines;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::array<const AttributeBinding, GPU_NUM_UNIFORMS> &m_attribute_bindings;
|
||||
const size_t m_data_size;
|
||||
const char *m_defines;
|
||||
};
|
||||
|
||||
class ShaderBlockBuffer {
|
||||
public:
|
||||
struct Flags {
|
||||
bool is_dirty : 1;
|
||||
};
|
||||
|
||||
ShaderBlockBuffer(const GPUShaderBlockType type);
|
||||
ShaderBlockBuffer(const ShaderBlockBuffer &other) = default;
|
||||
ShaderBlockBuffer(ShaderBlockBuffer &&other) = default;
|
||||
|
||||
~ShaderBlockBuffer();
|
||||
|
||||
const Flags &flags() const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
void *data() const
|
||||
{
|
||||
return m_data;
|
||||
};
|
||||
|
||||
const ShaderBlockType &type_info() const
|
||||
{
|
||||
return m_type_info;
|
||||
}
|
||||
|
||||
bool uniform_int(int location, int comp_len, int array_size, const int *data);
|
||||
bool uniform_float(int location, int comp_len, int array_size, const float *data);
|
||||
void update();
|
||||
void bind(int binding);
|
||||
|
||||
private:
|
||||
Flags m_flags;
|
||||
const ShaderBlockType &m_type_info;
|
||||
void *m_data;
|
||||
UniformBuf *m_ubo;
|
||||
};
|
||||
|
||||
std::optional<const GPUShaderBlockType> find_smallest_shader_block(
|
||||
const ShaderInterface &interface);
|
||||
|
||||
} // namespace blender::gpu
|
@@ -157,6 +157,7 @@ typedef struct {
|
||||
const char *frag;
|
||||
/** Optional. */
|
||||
const char *defs;
|
||||
const GPUShaderBlockType shader_block;
|
||||
} GPUShaderStages;
|
||||
|
||||
static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
|
||||
@@ -165,6 +166,7 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
|
||||
.name = "GPU_SHADER_TEXT",
|
||||
.vert = datatoc_gpu_shader_text_vert_glsl,
|
||||
.frag = datatoc_gpu_shader_text_frag_glsl,
|
||||
.shader_block = GPU_SHADER_BLOCK_3D_COLOR,
|
||||
},
|
||||
[GPU_SHADER_KEYFRAME_DIAMOND] =
|
||||
{
|
||||
@@ -532,6 +534,7 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
|
||||
.geom = (const char *[]){stages->geom, NULL},
|
||||
.frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
|
||||
.defs = (const char *[]){stages->defs, NULL},
|
||||
.shader_block = stages->shader_block,
|
||||
});
|
||||
}
|
||||
else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
||||
|
@@ -129,4 +129,14 @@ void ShaderInterface::debug_print()
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bool ShaderInterface::has_builtin_uniforms() const
|
||||
{
|
||||
for (int i = 0; i < GPU_NUM_UNIFORMS; i++) {
|
||||
if (builtins_[i] != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
@@ -35,6 +35,8 @@
|
||||
|
||||
#include "GPU_shader.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
typedef struct ShaderInput {
|
||||
@@ -75,6 +77,7 @@ class ShaderInterface {
|
||||
virtual ~ShaderInterface();
|
||||
|
||||
void debug_print(void);
|
||||
bool has_builtin_uniforms() const;
|
||||
|
||||
inline const ShaderInput *attr_get(const char *name) const
|
||||
{
|
||||
@@ -202,6 +205,8 @@ inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBu
|
||||
return "modelBlock";
|
||||
case GPU_UNIFORM_BLOCK_INFO:
|
||||
return "infoBlock";
|
||||
case GPU_UNIFORM_BLOCK_SHADER:
|
||||
return "shaderBlock";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -24,9 +24,14 @@
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_shader_block_types.h"
|
||||
#include "gpu_shader_block.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
#include "gpu_uniform_buffer_private.hh"
|
||||
#include "gpu_vertex_buffer_private.hh"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace blender {
|
||||
namespace gpu {
|
||||
|
||||
@@ -45,6 +50,8 @@ class Shader {
|
||||
/** For debugging purpose. */
|
||||
char name[64];
|
||||
|
||||
std::optional<ShaderBlockBuffer> shader_struct;
|
||||
|
||||
public:
|
||||
Shader(const char *name);
|
||||
virtual ~Shader();
|
||||
@@ -76,6 +83,17 @@ class Shader {
|
||||
return name;
|
||||
};
|
||||
|
||||
ShaderBlockBuffer *m_shader_struct = nullptr;
|
||||
void set_shader_struct(GPUShaderBlockType struct_type)
|
||||
{
|
||||
m_shader_struct = new ShaderBlockBuffer(struct_type);
|
||||
}
|
||||
|
||||
const bool has_shader_block() const;
|
||||
const bool shader_block_dirty_get() const;
|
||||
void shader_block_update() const;
|
||||
void shader_block_bind() const;
|
||||
|
||||
protected:
|
||||
void print_log(Span<const char *> sources,
|
||||
char *log,
|
||||
|
@@ -24,11 +24,20 @@
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_shader_block_types.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
struct GPUUniformBuf;
|
||||
|
||||
namespace blender {
|
||||
namespace gpu {
|
||||
|
||||
class ShaderInterface;
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DEBUG_NAME_LEN 64
|
||||
#else
|
||||
|
@@ -225,8 +225,9 @@ bool GLShader::finalize()
|
||||
this->print_log(sources, log, "Linking", true, &parser);
|
||||
return false;
|
||||
}
|
||||
|
||||
interface = new GLShaderInterface(shader_program_);
|
||||
const ShaderBlockType *type_info = m_shader_struct != nullptr ? &m_shader_struct->type_info() :
|
||||
nullptr;
|
||||
interface = new GLShaderInterface(type_info, shader_program_);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -308,6 +309,12 @@ void GLShader::transform_feedback_disable()
|
||||
|
||||
void GLShader::uniform_float(int location, int comp_len, int array_size, const float *data)
|
||||
{
|
||||
if (m_shader_struct) {
|
||||
if (m_shader_struct->uniform_float(location, comp_len, array_size, data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (comp_len) {
|
||||
case 1:
|
||||
glUniform1fv(location, array_size, data);
|
||||
@@ -335,6 +342,12 @@ void GLShader::uniform_float(int location, int comp_len, int array_size, const f
|
||||
|
||||
void GLShader::uniform_int(int location, int comp_len, int array_size, const int *data)
|
||||
{
|
||||
if (m_shader_struct) {
|
||||
if (m_shader_struct->uniform_int(location, comp_len, array_size, data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (comp_len) {
|
||||
case 1:
|
||||
glUniform1iv(location, array_size, data);
|
||||
|
@@ -145,7 +145,7 @@ static inline int ssbo_binding(int32_t program, uint32_t ssbo_index)
|
||||
/** \name Creation / Destruction
|
||||
* \{ */
|
||||
|
||||
GLShaderInterface::GLShaderInterface(GLuint program)
|
||||
GLShaderInterface::GLShaderInterface(const ShaderBlockType *type_info, GLuint program)
|
||||
{
|
||||
/* Necessary to make #glUniform works. */
|
||||
glUseProgram(program);
|
||||
@@ -187,6 +187,20 @@ GLShaderInterface::GLShaderInterface(GLuint program)
|
||||
max_ssbo_name_len = 256;
|
||||
}
|
||||
|
||||
/* Perform uniform builtin structs after work around to make sure the work around is passed. */
|
||||
if (type_info) {
|
||||
for (int i = 0; i < GPU_NUM_UNIFORMS; i++) {
|
||||
const GPUUniformBuiltin builtin_uniform = static_cast<const GPUUniformBuiltin>(i);
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info->attribute_binding(
|
||||
builtin_uniform);
|
||||
if (binding.has_binding()) {
|
||||
uniform_len++;
|
||||
max_uniform_name_len = max_ii(max_uniform_name_len,
|
||||
strlen(builtin_uniform_name(builtin_uniform)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before
|
||||
* allocating the uniform array. */
|
||||
GLint max_ubo_uni_len = 0;
|
||||
@@ -281,6 +295,24 @@ GLShaderInterface::GLShaderInterface(GLuint program)
|
||||
enabled_ima_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
|
||||
}
|
||||
}
|
||||
if (type_info) {
|
||||
for (int i = 0; i < GPU_NUM_UNIFORMS; i++) {
|
||||
const GPUUniformBuiltin builtin_uniform = static_cast<const GPUUniformBuiltin>(i);
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info->attribute_binding(
|
||||
builtin_uniform);
|
||||
if (binding.has_binding()) {
|
||||
ShaderInput *input = &inputs_[attr_len_ + ubo_len_ + uniform_len_++];
|
||||
input->location = binding.location;
|
||||
input->binding = -1;
|
||||
|
||||
char *name = name_buffer_ + name_buffer_offset;
|
||||
const char *uniform_name = builtin_uniform_name(builtin_uniform);
|
||||
size_t name_len = strlen(uniform_name);
|
||||
strcpy(name, uniform_name);
|
||||
name_buffer_offset += this->set_input_name(input, name, name_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SSBOs */
|
||||
for (int i = 0; i < ssbo_len; i++) {
|
||||
@@ -301,7 +333,8 @@ GLShaderInterface::GLShaderInterface(GLuint program)
|
||||
/* Builtin Uniforms */
|
||||
for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) {
|
||||
GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int);
|
||||
builtins_[u] = glGetUniformLocation(program, builtin_uniform_name(u));
|
||||
const ShaderInput *block = this->uniform_get(builtin_uniform_name(u));
|
||||
builtins_[u] = (block != nullptr) ? block->location : -1;
|
||||
}
|
||||
|
||||
/* Builtin Uniforms Blocks */
|
||||
|
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "glew-mx.h"
|
||||
|
||||
#include "gpu_shader_block.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
@@ -49,7 +50,7 @@ class GLShaderInterface : public ShaderInterface {
|
||||
Vector<GLVaoCache *> refs_;
|
||||
|
||||
public:
|
||||
GLShaderInterface(GLuint program);
|
||||
GLShaderInterface(const ShaderBlockType *type_info, GLuint program);
|
||||
~GLShaderInterface();
|
||||
|
||||
void ref_add(GLVaoCache *ref);
|
||||
|
@@ -2,7 +2,9 @@
|
||||
/* Undefine the macro that avoids compilation errors. */
|
||||
#undef blender_srgb_to_framebuffer_space
|
||||
|
||||
#ifndef GPU_SHADER_BLOCK
|
||||
uniform bool srgbTarget = false;
|
||||
#endif
|
||||
|
||||
vec4 blender_srgb_to_framebuffer_space(vec4 color)
|
||||
{
|
||||
|
@@ -1,6 +1,4 @@
|
||||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
in vec4 pos; /* rect */
|
||||
in vec4 col;
|
||||
in int offset;
|
||||
|
164
source/blender/gpu/tests/gpu_shader_block_test.cc
Normal file
164
source/blender/gpu/tests/gpu_shader_block_test.cc
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "gpu_testing.hh"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
#include "GPU_compute.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_shader_block_types.h"
|
||||
#include "gpu_shader_block.hh"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
namespace blender::gpu::tests {
|
||||
|
||||
TEST(GPUUniformStruct, struct1)
|
||||
{
|
||||
ShaderBlockBuffer uniform_struct(GPU_SHADER_BLOCK_3D_COLOR);
|
||||
const ShaderBlockType &type_info = uniform_struct.type_info();
|
||||
const GPUShaderBlock3dColor *struct_data = static_cast<const GPUShaderBlock3dColor *>(
|
||||
uniform_struct.data());
|
||||
EXPECT_EQ(type_info.data_size(), sizeof(*struct_data));
|
||||
|
||||
/* ModelMatrix attribute. */
|
||||
{
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info.attribute_binding(
|
||||
GPU_UNIFORM_MODEL);
|
||||
float m4[4][4];
|
||||
unit_m4(m4);
|
||||
|
||||
const bool result = uniform_struct.uniform_float(binding.location, 4, 4, (const float *)m4);
|
||||
EXPECT_TRUE(result);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
EXPECT_EQ(struct_data->ModelMatrix[i][j], m4[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ModelViewProjectionMatrix attribute. */
|
||||
{
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info.attribute_binding(
|
||||
GPU_UNIFORM_MVP);
|
||||
float m4[4][4];
|
||||
unit_m4(m4);
|
||||
|
||||
const bool result = uniform_struct.uniform_float(binding.location, 4, 4, (const float *)m4);
|
||||
EXPECT_TRUE(result);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
EXPECT_EQ(struct_data->ModelViewProjectionMatrix[i][j], m4[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Color attribute. */
|
||||
{
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info.attribute_binding(
|
||||
GPU_UNIFORM_COLOR);
|
||||
float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
|
||||
const bool result = uniform_struct.uniform_float(binding.location, 4, 1, color);
|
||||
EXPECT_TRUE(result);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(struct_data->color[i], color[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* WorldClipPlanes attribute. */
|
||||
{
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info.attribute_binding(
|
||||
GPU_UNIFORM_CLIPPLANES);
|
||||
|
||||
float clip_planes[6][4] = {
|
||||
{01.0f, 02.0f, 03.0f, 04.0f},
|
||||
{11.0f, 12.0f, 13.0f, 14.0f},
|
||||
{21.0f, 22.0f, 23.0f, 24.0f},
|
||||
{31.0f, 32.0f, 33.0f, 34.0f},
|
||||
{41.0f, 42.0f, 43.0f, 44.0f},
|
||||
{51.0f, 52.0f, 53.0f, 54.0f},
|
||||
};
|
||||
|
||||
const bool result = uniform_struct.uniform_float(
|
||||
binding.location, 4, 6, (const float *)clip_planes);
|
||||
EXPECT_TRUE(result);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
EXPECT_EQ(struct_data->WorldClipPlanes[i][j], clip_planes[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SrgbTransform attribute. */
|
||||
{
|
||||
const ShaderBlockType::AttributeBinding &binding = type_info.attribute_binding(
|
||||
GPU_UNIFORM_SRGB_TRANSFORM);
|
||||
int srgb_transform = true;
|
||||
const bool result = uniform_struct.uniform_int(binding.location, 1, 1, &srgb_transform);
|
||||
EXPECT_TRUE(result);
|
||||
EXPECT_EQ(struct_data->SrgbTransform, srgb_transform);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_shader_block_struct()
|
||||
{
|
||||
if (!GPU_compute_shader_support()) {
|
||||
/* We can't test as a the platform does not support compute shaders. */
|
||||
std::cout << "Skipping compute shader test: platform not supported";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build compute shader. */
|
||||
const char *compute_glsl = R"(
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1) in;
|
||||
layout(rgba32f, binding = 0) uniform image2D img_output;
|
||||
|
||||
void main() {
|
||||
}
|
||||
|
||||
)";
|
||||
|
||||
GPUShader *shader = GPU_shader_create_ex(nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
compute_glsl,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GPU_SHADER_TFB_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
GPU_SHADER_BLOCK_3D_COLOR,
|
||||
__func__);
|
||||
EXPECT_NE(shader, nullptr);
|
||||
|
||||
int location;
|
||||
|
||||
location = GPU_shader_get_uniform(shader, "ModelMatrix");
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_uniform(shader, "color");
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_uniform(shader, "WorldClipPlanes");
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_uniform(shader, "srgbTarget");
|
||||
EXPECT_NE(location, -1);
|
||||
|
||||
location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR);
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES);
|
||||
EXPECT_NE(location, -1);
|
||||
location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM);
|
||||
EXPECT_NE(location, -1);
|
||||
|
||||
float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
|
||||
GPU_shader_uniform_4fv(shader, "color", color);
|
||||
|
||||
GPU_shader_free(shader);
|
||||
}
|
||||
|
||||
GPU_TEST(shader_block_struct)
|
||||
|
||||
} // namespace blender::gpu::tests
|
Submodule source/tools updated: 01f51a0e55...c8579c5cf4
Reference in New Issue
Block a user