This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/gpu/intern/gpu_shader_interface.hh
Clément Foucault 136bdb561b GPU: Add Image Load Store extension support
This wraps the functionality used to speedup EEVEE volumetrics.

This touches the rendering code of EEVEE as it should fix a mis-usage of
the GL barrier. The barrier changed type and location, removing an
unused barrier.
2020-09-12 15:29:54 +02:00

262 lines
8.0 KiB
C++

/*
* 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) 2016 by Mike Erwin.
* All rights reserved.
*/
/** \file
* \ingroup gpu
*
* GPU shader interface (C --> GLSL)
*
* Structure detailing needed vertex inputs and resources for a specific shader.
* A shader interface can be shared between two similar shaders.
*/
#pragma once
#include <cstring> /* required for STREQ later on. */
#include "BLI_hash.h"
#include "BLI_utildefines.h"
#include "GPU_shader.h"
namespace blender::gpu {
typedef struct ShaderInput {
uint32_t name_offset;
uint32_t name_hash;
int32_t location;
/** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */
int32_t binding;
} ShaderInput;
/**
* Implementation of Shader interface.
* Base class which is then specialized for each implementation (GL, VK, ...).
**/
class ShaderInterface {
/* TODO(fclem) should be protected. */
public:
/** Flat array. In this order: Attributes, Ubos, Uniforms. */
ShaderInput *inputs_ = NULL;
/** Buffer containing all inputs names separated by '\0'. */
char *name_buffer_ = NULL;
/** Input counts inside input array. */
uint attr_len_ = 0;
uint ubo_len_ = 0;
uint uniform_len_ = 0;
/** Enabled bindpoints that needs to be fed with data. */
uint16_t enabled_attr_mask_ = 0;
uint16_t enabled_ubo_mask_ = 0;
uint8_t enabled_ima_mask_ = 0;
uint64_t enabled_tex_mask_ = 0;
/** Location of builtin uniforms. Fast access, no lookup needed. */
int32_t builtins_[GPU_NUM_UNIFORMS];
int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS];
public:
ShaderInterface();
virtual ~ShaderInterface();
void debug_print(void);
inline const ShaderInput *attr_get(const char *name) const
{
return input_lookup(inputs_, attr_len_, name);
}
inline const ShaderInput *ubo_get(const char *name) const
{
return input_lookup(inputs_ + attr_len_, ubo_len_, name);
}
inline const ShaderInput *ubo_get(const int binding) const
{
return input_lookup(inputs_ + attr_len_, ubo_len_, binding);
}
inline const ShaderInput *uniform_get(const char *name) const
{
return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, name);
}
inline const ShaderInput *texture_get(const int binding) const
{
return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, binding);
}
inline const char *input_name_get(const ShaderInput *input) const
{
return name_buffer_ + input->name_offset;
}
/* Returns uniform location. */
inline int32_t uniform_builtin(const GPUUniformBuiltin builtin) const
{
BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS);
return builtins_[builtin];
}
/* Returns binding position. */
inline int32_t ubo_builtin(const GPUUniformBlockBuiltin builtin) const
{
BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS);
return builtin_blocks_[builtin];
}
protected:
static inline const char *builtin_uniform_name(GPUUniformBuiltin u);
static inline const char *builtin_uniform_block_name(GPUUniformBlockBuiltin u);
inline uint32_t set_input_name(ShaderInput *input, char *name, uint32_t name_len) const;
/* Finalize interface construction by sorting the ShaderInputs for faster lookups. */
void sort_inputs(void);
private:
inline const ShaderInput *input_lookup(const ShaderInput *const inputs,
const uint inputs_len,
const char *name) const;
inline const ShaderInput *input_lookup(const ShaderInput *const inputs,
const uint inputs_len,
const int binding) const;
};
inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u)
{
switch (u) {
case GPU_UNIFORM_MODEL:
return "ModelMatrix";
case GPU_UNIFORM_VIEW:
return "ViewMatrix";
case GPU_UNIFORM_MODELVIEW:
return "ModelViewMatrix";
case GPU_UNIFORM_PROJECTION:
return "ProjectionMatrix";
case GPU_UNIFORM_VIEWPROJECTION:
return "ViewProjectionMatrix";
case GPU_UNIFORM_MVP:
return "ModelViewProjectionMatrix";
case GPU_UNIFORM_MODEL_INV:
return "ModelMatrixInverse";
case GPU_UNIFORM_VIEW_INV:
return "ViewMatrixInverse";
case GPU_UNIFORM_MODELVIEW_INV:
return "ModelViewMatrixInverse";
case GPU_UNIFORM_PROJECTION_INV:
return "ProjectionMatrixInverse";
case GPU_UNIFORM_VIEWPROJECTION_INV:
return "ViewProjectionMatrixInverse";
case GPU_UNIFORM_NORMAL:
return "NormalMatrix";
case GPU_UNIFORM_ORCO:
return "OrcoTexCoFactors";
case GPU_UNIFORM_CLIPPLANES:
return "WorldClipPlanes";
case GPU_UNIFORM_COLOR:
return "color";
case GPU_UNIFORM_BASE_INSTANCE:
return "baseInstance";
case GPU_UNIFORM_RESOURCE_CHUNK:
return "resourceChunk";
case GPU_UNIFORM_RESOURCE_ID:
return "resourceId";
case GPU_UNIFORM_SRGB_TRANSFORM:
return "srgbTarget";
default:
return NULL;
}
}
inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBuiltin u)
{
switch (u) {
case GPU_UNIFORM_BLOCK_VIEW:
return "viewBlock";
case GPU_UNIFORM_BLOCK_MODEL:
return "modelBlock";
case GPU_UNIFORM_BLOCK_INFO:
return "infoBlock";
default:
return NULL;
}
}
/* Returns string length including '\0' terminator. */
inline uint32_t ShaderInterface::set_input_name(ShaderInput *input,
char *name,
uint32_t name_len) const
{
/* remove "[0]" from array name */
if (name[name_len - 1] == ']') {
name[name_len - 3] = '\0';
name_len -= 3;
}
input->name_offset = (uint32_t)(name - name_buffer_);
input->name_hash = BLI_hash_string(name);
return name_len + 1; /* include NULL terminator */
}
inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const inputs,
const uint inputs_len,
const char *name) const
{
const uint name_hash = BLI_hash_string(name);
/* Simple linear search for now. */
for (int i = inputs_len - 1; i >= 0; i--) {
if (inputs[i].name_hash == name_hash) {
if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) {
/* Hash colision resolve. */
for (; i >= 0 && inputs[i].name_hash == name_hash; i--) {
if (STREQ(name, name_buffer_ + inputs[i].name_offset)) {
return inputs + i; /* not found */
}
}
return NULL; /* not found */
}
/* This is a bit dangerous since we could have a hash collision.
* where the asked uniform that does not exist has the same hash
* as a real uniform. */
BLI_assert(STREQ(name, name_buffer_ + inputs[i].name_offset));
return inputs + i;
}
}
return NULL; /* not found */
}
inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const inputs,
const uint inputs_len,
const int binding) const
{
/* Simple linear search for now. */
for (int i = inputs_len - 1; i >= 0; i--) {
if (inputs[i].binding == binding) {
return inputs + i;
}
}
return NULL; /* not found */
}
} // namespace blender::gpu