mirror of
https://github.com/overte-org/overte.git
synced 2025-08-03 22:23:31 +02:00
Adding the ubo slot assignment for the resource texture table
This commit is contained in:
parent
536ada3973
commit
03aeb7adda
8 changed files with 573 additions and 35 deletions
|
@ -98,6 +98,12 @@ public:
|
|||
static const int MAX_NUM_RESOURCE_TEXTURES = 16;
|
||||
size_t getMaxNumResourceTextures() const { return MAX_NUM_RESOURCE_TEXTURES; }
|
||||
|
||||
// Texture Tables offers 2 dedicated slot (taken from the ubo slots)
|
||||
static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2;
|
||||
static const int RESOURCE_TABLE_TEXTURE_SLOT_OFFSET = TRANSFORM_CAMERA_SLOT + 1;
|
||||
size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; }
|
||||
|
||||
|
||||
// Draw Stage
|
||||
virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
|
||||
virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
|
||||
|
|
|
@ -10,6 +10,447 @@
|
|||
|
||||
#include "GLBackend.h"
|
||||
|
||||
namespace gpu {
|
||||
namespace gl {
|
||||
|
||||
class ElementResource {
|
||||
public:
|
||||
gpu::Element _element;
|
||||
uint16 _resource;
|
||||
|
||||
ElementResource(Element&& elem, uint16 resource) : _element(elem), _resource(resource) {}
|
||||
};
|
||||
|
||||
ElementResource getFormatFromGLUniform(GLenum gltype) {
|
||||
switch (gltype) {
|
||||
case GL_FLOAT: return ElementResource(Element(SCALAR, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_FLOAT_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_FLOAT_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_FLOAT_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
/*
|
||||
case GL_DOUBLE: return ElementResource(Element(SCALAR, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_DOUBLE_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_DOUBLE_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_DOUBLE_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
*/
|
||||
case GL_INT: return ElementResource(Element(SCALAR, gpu::INT32, UNIFORM), Resource::BUFFER);
|
||||
case GL_INT_VEC2: return ElementResource(Element(VEC2, gpu::INT32, UNIFORM), Resource::BUFFER);
|
||||
case GL_INT_VEC3: return ElementResource(Element(VEC3, gpu::INT32, UNIFORM), Resource::BUFFER);
|
||||
case GL_INT_VEC4: return ElementResource(Element(VEC4, gpu::INT32, UNIFORM), Resource::BUFFER);
|
||||
|
||||
case GL_UNSIGNED_INT: return ElementResource(Element(SCALAR, gpu::UINT32, UNIFORM), Resource::BUFFER);
|
||||
#if defined(Q_OS_WIN)
|
||||
case GL_UNSIGNED_INT_VEC2: return ElementResource(Element(VEC2, gpu::UINT32, UNIFORM), Resource::BUFFER);
|
||||
case GL_UNSIGNED_INT_VEC3: return ElementResource(Element(VEC3, gpu::UINT32, UNIFORM), Resource::BUFFER);
|
||||
case GL_UNSIGNED_INT_VEC4: return ElementResource(Element(VEC4, gpu::UINT32, UNIFORM), Resource::BUFFER);
|
||||
#endif
|
||||
|
||||
case GL_BOOL: return ElementResource(Element(SCALAR, gpu::BOOL, UNIFORM), Resource::BUFFER);
|
||||
case GL_BOOL_VEC2: return ElementResource(Element(VEC2, gpu::BOOL, UNIFORM), Resource::BUFFER);
|
||||
case GL_BOOL_VEC3: return ElementResource(Element(VEC3, gpu::BOOL, UNIFORM), Resource::BUFFER);
|
||||
case GL_BOOL_VEC4: return ElementResource(Element(VEC4, gpu::BOOL, UNIFORM), Resource::BUFFER);
|
||||
|
||||
|
||||
case GL_FLOAT_MAT2: return ElementResource(Element(gpu::MAT2, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_FLOAT_MAT3: return ElementResource(Element(MAT3, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
case GL_FLOAT_MAT4: return ElementResource(Element(MAT4, gpu::FLOAT, UNIFORM), Resource::BUFFER);
|
||||
|
||||
/* {GL_FLOAT_MAT2x3 mat2x3},
|
||||
{GL_FLOAT_MAT2x4 mat2x4},
|
||||
{GL_FLOAT_MAT3x2 mat3x2},
|
||||
{GL_FLOAT_MAT3x4 mat3x4},
|
||||
{GL_FLOAT_MAT4x2 mat4x2},
|
||||
{GL_FLOAT_MAT4x3 mat4x3},
|
||||
{GL_DOUBLE_MAT2 dmat2},
|
||||
{GL_DOUBLE_MAT3 dmat3},
|
||||
{GL_DOUBLE_MAT4 dmat4},
|
||||
{GL_DOUBLE_MAT2x3 dmat2x3},
|
||||
{GL_DOUBLE_MAT2x4 dmat2x4},
|
||||
{GL_DOUBLE_MAT3x2 dmat3x2},
|
||||
{GL_DOUBLE_MAT3x4 dmat3x4},
|
||||
{GL_DOUBLE_MAT4x2 dmat4x2},
|
||||
{GL_DOUBLE_MAT4x3 dmat4x3},
|
||||
*/
|
||||
|
||||
case GL_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D);
|
||||
case GL_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D);
|
||||
|
||||
case GL_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_3D);
|
||||
case GL_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_CUBE);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
case GL_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D);
|
||||
case GL_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D_ARRAY);
|
||||
case GL_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D_ARRAY);
|
||||
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY);
|
||||
#endif
|
||||
|
||||
case GL_SAMPLER_2D_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D);
|
||||
#if defined(Q_OS_WIN)
|
||||
case GL_SAMPLER_CUBE_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_CUBE);
|
||||
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D_ARRAY);
|
||||
#endif
|
||||
|
||||
// {GL_SAMPLER_1D_SHADOW sampler1DShadow},
|
||||
// {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow},
|
||||
|
||||
// {GL_SAMPLER_BUFFER samplerBuffer},
|
||||
// {GL_SAMPLER_2D_RECT sampler2DRect},
|
||||
// {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow},
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
case GL_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D);
|
||||
case GL_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D);
|
||||
case GL_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D);
|
||||
case GL_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_3D);
|
||||
case GL_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_CUBE);
|
||||
|
||||
case GL_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D_ARRAY);
|
||||
case GL_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D_ARRAY);
|
||||
case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY);
|
||||
|
||||
// {GL_INT_SAMPLER_BUFFER isamplerBuffer},
|
||||
// {GL_INT_SAMPLER_2D_RECT isampler2DRect},
|
||||
|
||||
case GL_UNSIGNED_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D);
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D);
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D);
|
||||
case GL_UNSIGNED_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_3D);
|
||||
case GL_UNSIGNED_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_CUBE);
|
||||
|
||||
case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D_ARRAY);
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D_ARRAY);
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY);
|
||||
#endif
|
||||
// {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer},
|
||||
// {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect},
|
||||
/*
|
||||
{GL_IMAGE_1D image1D},
|
||||
{GL_IMAGE_2D image2D},
|
||||
{GL_IMAGE_3D image3D},
|
||||
{GL_IMAGE_2D_RECT image2DRect},
|
||||
{GL_IMAGE_CUBE imageCube},
|
||||
{GL_IMAGE_BUFFER imageBuffer},
|
||||
{GL_IMAGE_1D_ARRAY image1DArray},
|
||||
{GL_IMAGE_2D_ARRAY image2DArray},
|
||||
{GL_IMAGE_2D_MULTISAMPLE image2DMS},
|
||||
{GL_IMAGE_2D_MULTISAMPLE_ARRAY image2DMSArray},
|
||||
{GL_INT_IMAGE_1D iimage1D},
|
||||
{GL_INT_IMAGE_2D iimage2D},
|
||||
{GL_INT_IMAGE_3D iimage3D},
|
||||
{GL_INT_IMAGE_2D_RECT iimage2DRect},
|
||||
{GL_INT_IMAGE_CUBE iimageCube},
|
||||
{GL_INT_IMAGE_BUFFER iimageBuffer},
|
||||
{GL_INT_IMAGE_1D_ARRAY iimage1DArray},
|
||||
{GL_INT_IMAGE_2D_ARRAY iimage2DArray},
|
||||
{GL_INT_IMAGE_2D_MULTISAMPLE iimage2DMS},
|
||||
{GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY iimage2DMSArray},
|
||||
{GL_UNSIGNED_INT_IMAGE_1D uimage1D},
|
||||
{GL_UNSIGNED_INT_IMAGE_2D uimage2D},
|
||||
{GL_UNSIGNED_INT_IMAGE_3D uimage3D},
|
||||
{GL_UNSIGNED_INT_IMAGE_2D_RECT uimage2DRect},
|
||||
{GL_UNSIGNED_INT_IMAGE_CUBE uimageCube},+ [0] {_name="fInnerRadius" _location=0 _element={_semantic=15 '\xf' _dimension=0 '\0' _type=0 '\0' } } gpu::Shader::Slot
|
||||
|
||||
{GL_UNSIGNED_INT_IMAGE_BUFFER uimageBuffer},
|
||||
{GL_UNSIGNED_INT_IMAGE_1D_ARRAY uimage1DArray},
|
||||
{GL_UNSIGNED_INT_IMAGE_2D_ARRAY uimage2DArray},
|
||||
{GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS},
|
||||
{GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY uimage2DMSArray},
|
||||
{GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint}
|
||||
*/
|
||||
default:
|
||||
return ElementResource(Element(), Resource::BUFFER);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,
|
||||
Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& textureTables, Shader::SlotSet& samplers) {
|
||||
GLint uniformsCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount);
|
||||
|
||||
for (int i = 0; i < uniformsCount; i++) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
GLint size = 0;
|
||||
GLenum type = 0;
|
||||
glGetActiveUniform(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
|
||||
GLint location = glGetUniformLocation(glprogram, name);
|
||||
const GLint INVALID_UNIFORM_LOCATION = -1;
|
||||
|
||||
// Try to make sense of the gltype
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
|
||||
// The uniform as a standard var type
|
||||
if (location != INVALID_UNIFORM_LOCATION) {
|
||||
// Let's make sure the name doesn't contains an array element
|
||||
std::string sname(name);
|
||||
auto foundBracket = sname.find_first_of('[');
|
||||
if (foundBracket != std::string::npos) {
|
||||
// std::string arrayname = sname.substr(0, foundBracket);
|
||||
|
||||
if (sname[foundBracket + 1] == '0') {
|
||||
sname = sname.substr(0, foundBracket);
|
||||
} else {
|
||||
// skip this uniform since it's not the first element of an array
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (elementResource._resource == Resource::BUFFER) {
|
||||
uniforms.insert(Shader::Slot(sname, location, elementResource._element, elementResource._resource));
|
||||
} else {
|
||||
// For texture/Sampler, the location is the actual binding value
|
||||
GLint binding = -1;
|
||||
glGetUniformiv(glprogram, location, &binding);
|
||||
|
||||
auto requestedBinding = slotBindings.find(std::string(sname));
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
if (binding != (*requestedBinding)._location) {
|
||||
binding = (*requestedBinding)._location;
|
||||
glProgramUniform1i(glprogram, location, binding);
|
||||
}
|
||||
}
|
||||
|
||||
textures.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
samplers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uniformsCount;
|
||||
}
|
||||
|
||||
const GLint UNUSED_SLOT = -1;
|
||||
bool isUnusedSlot(GLint binding) {
|
||||
return (binding == UNUSED_SLOT);
|
||||
}
|
||||
|
||||
int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) {
|
||||
GLint buffersCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount);
|
||||
|
||||
// fast exit
|
||||
if (buffersCount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLint maxNumUniformBufferSlots = 0;
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxNumUniformBufferSlots);
|
||||
std::vector<GLint> uniformBufferSlotMap(maxNumUniformBufferSlots, -1);
|
||||
|
||||
struct UniformBlockInfo {
|
||||
using Vector = std::vector<UniformBlockInfo>;
|
||||
const GLuint index { 0 };
|
||||
const std::string name;
|
||||
GLint binding { -1 };
|
||||
GLint size { 0 };
|
||||
|
||||
static std::string getName(GLuint glprogram, GLuint i) {
|
||||
static const GLint NAME_LENGTH = 256;
|
||||
GLint length = 0;
|
||||
GLchar nameBuffer[NAME_LENGTH];
|
||||
glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length);
|
||||
glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, nameBuffer);
|
||||
return std::string(nameBuffer);
|
||||
}
|
||||
|
||||
UniformBlockInfo(GLuint glprogram, GLuint i) : index(i), name(getName(glprogram, i)) {
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_BINDING, &binding);
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
|
||||
}
|
||||
};
|
||||
|
||||
UniformBlockInfo::Vector uniformBlocks;
|
||||
uniformBlocks.reserve(buffersCount);
|
||||
for (int i = 0; i < buffersCount; i++) {
|
||||
uniformBlocks.push_back(UniformBlockInfo(glprogram, i));
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
auto requestedBinding = slotBindings.find(info.name);
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
info.binding = (*requestedBinding)._location;
|
||||
glUniformBlockBinding(glprogram, info.index, info.binding);
|
||||
uniformBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
if (slotBindings.count(info.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the binding is 0, or the binding maps to an already used binding
|
||||
if (info.binding == 0 || uniformBufferSlotMap[info.binding] != UNUSED_SLOT) {
|
||||
// If no binding was assigned then just do it finding a free slot
|
||||
auto slotIt = std::find_if(uniformBufferSlotMap.begin(), uniformBufferSlotMap.end(), isUnusedSlot);
|
||||
if (slotIt != uniformBufferSlotMap.end()) {
|
||||
info.binding = slotIt - uniformBufferSlotMap.begin();
|
||||
glUniformBlockBinding(glprogram, info.index, info.binding);
|
||||
} else {
|
||||
// This should neve happen, an active ubo cannot find an available slot among the max available?!
|
||||
info.binding = -1;
|
||||
}
|
||||
}
|
||||
|
||||
uniformBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
static const Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER);
|
||||
buffers.insert(Shader::Slot(info.name, info.binding, element, Resource::BUFFER, info.size));
|
||||
}
|
||||
return buffersCount;
|
||||
}
|
||||
|
||||
int makeInputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs) {
|
||||
GLint inputsCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &inputsCount);
|
||||
|
||||
for (int i = 0; i < inputsCount; i++) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
GLint size = 0;
|
||||
GLenum type = 0;
|
||||
glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
|
||||
|
||||
GLint binding = glGetAttribLocation(glprogram, name);
|
||||
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
inputs.insert(Shader::Slot(name, binding, elementResource._element, -1));
|
||||
}
|
||||
|
||||
return inputsCount;
|
||||
}
|
||||
|
||||
int makeOutputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs) {
|
||||
/* GLint outputsCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_, &outputsCount);
|
||||
|
||||
for (int i = 0; i < inputsCount; i++) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
GLint size = 0;
|
||||
GLenum type = 0;
|
||||
glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
|
||||
|
||||
auto element = getFormatFromGLUniform(type);
|
||||
outputs.insert(Shader::Slot(name, i, element));
|
||||
}
|
||||
*/
|
||||
return 0; //inputsCount;
|
||||
}
|
||||
|
||||
void makeProgramBindings(ShaderObject& shaderObject) {
|
||||
if (!shaderObject.glprogram) {
|
||||
return;
|
||||
}
|
||||
GLuint glprogram = shaderObject.glprogram;
|
||||
GLint loc = -1;
|
||||
|
||||
//Check for gpu specific attribute slotBindings
|
||||
loc = glGetAttribLocation(glprogram, "inPosition");
|
||||
if (loc >= 0 && loc != gpu::Stream::POSITION) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::POSITION, "inPosition");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inNormal");
|
||||
if (loc >= 0 && loc != gpu::Stream::NORMAL) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "inNormal");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inColor");
|
||||
if (loc >= 0 && loc != gpu::Stream::COLOR) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::COLOR, "inColor");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inTexCoord0");
|
||||
if (loc >= 0 && loc != gpu::Stream::TEXCOORD) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "inTexCoord0");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inTangent");
|
||||
if (loc >= 0 && loc != gpu::Stream::TANGENT) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inTexCoord1");
|
||||
if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inSkinClusterIndex");
|
||||
if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_INDEX) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "inSkinClusterIndex");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inSkinClusterWeight");
|
||||
if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_WEIGHT) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "_drawCallInfo");
|
||||
if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo");
|
||||
}
|
||||
|
||||
// Link again to take into account the assigned attrib location
|
||||
glLinkProgram(glprogram);
|
||||
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
|
||||
if (!linked) {
|
||||
qCWarning(gpugllogging) << "GLShader::makeBindings - failed to link after assigning slotBindings?";
|
||||
}
|
||||
|
||||
// now assign the ubo binding, then DON't relink!
|
||||
|
||||
//Check for gpu specific uniform slotBindings
|
||||
#ifdef GPU_SSBO_DRAW_CALL_INFO
|
||||
loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
#else
|
||||
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
#endif
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
|
||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||
}
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "gpu_resourceTextureTable0");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET);
|
||||
shaderObject.resourceTextureTableSlot0 = GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET;
|
||||
}
|
||||
loc = glGetUniformBlockIndex(glprogram, "gpu_resourceTextureTable1");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET + 1);
|
||||
shaderObject.resourceTextureTableSlot1 = GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET + 1;
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
|
||||
|
@ -73,8 +514,9 @@ bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::Bin
|
|||
|
||||
Shader::SlotSet uniforms;
|
||||
Shader::SlotSet textures;
|
||||
Shader::SlotSet textureTables;
|
||||
Shader::SlotSet samplers;
|
||||
backend.makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, samplers);
|
||||
backend.makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, textureTables, samplers);
|
||||
|
||||
Shader::SlotSet resourceBuffers;
|
||||
backend.makeResourceBufferSlots(shaderObject.glprogram, slotBindings, resourceBuffers);
|
||||
|
|
|
@ -17,8 +17,19 @@ struct ShaderObject {
|
|||
GLuint glprogram { 0 };
|
||||
GLint transformCameraSlot { -1 };
|
||||
GLint transformObjectSlot { -1 };
|
||||
|
||||
GLint resourceTextureTableSlot0 { -1 };
|
||||
GLint resourceTextureTableSlot1 { -1 };
|
||||
};
|
||||
|
||||
int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,
|
||||
Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& textureTables, Shader::SlotSet& samplers);
|
||||
int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers);
|
||||
int makeInputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs);
|
||||
int makeOutputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs);
|
||||
void makeProgramBindings(ShaderObject& shaderObject);
|
||||
|
||||
|
||||
class GLShader : public GPUObject {
|
||||
public:
|
||||
static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr);
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
friend class GL45Backend;
|
||||
using PromoteLambda = std::function<void()>;
|
||||
|
||||
|
||||
const uvec4& getHandle();
|
||||
protected:
|
||||
GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||
~GL45VariableAllocationTexture();
|
||||
|
|
|
@ -212,6 +212,7 @@ void GL45Texture::syncSampler() const {
|
|||
|
||||
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, sampler.getMinMip());
|
||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture;
|
||||
|
@ -275,6 +276,10 @@ GL45StrictResourceTexture::GL45StrictResourceTexture(const std::weak_ptr<GLBacke
|
|||
if (texture.isAutogenerateMips()) {
|
||||
generateMips();
|
||||
}
|
||||
|
||||
// Re-sync the sampler to force access to the new mip level
|
||||
syncSampler();
|
||||
updateSize();
|
||||
}
|
||||
|
||||
GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
||||
|
@ -282,3 +287,80 @@ GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
|||
Backend::textureResidentGPUMemSize.update(size(), 0);
|
||||
}
|
||||
|
||||
const uvec4& GL45Texture::getHandle() {
|
||||
if (uvec4() == _handleAndBias) {
|
||||
auto handle = glGetTextureHandleARB(_id);
|
||||
glMakeTextureHandleResidentARB(handle);
|
||||
memcpy(&_handleAndBias, &handle, sizeof(handle));
|
||||
}
|
||||
_handleAndBias.z = _minMip;
|
||||
return _handleAndBias;
|
||||
}
|
||||
|
||||
using GL45TextureTable = GL45Backend::GL45TextureTable;
|
||||
|
||||
GLuint GL45TextureTable::allocate() {
|
||||
GLuint result;
|
||||
glCreateBuffers(1, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GL45TextureTable::GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& textureTable, const HandlesArray& handles, bool handlesComplete)
|
||||
: Parent(backend, textureTable, allocate()), _stamp(textureTable.getStamp()), _handles(handles), _complete(handlesComplete) {
|
||||
Backend::setGPUObject(textureTable, this);
|
||||
// FIXME include these in overall buffer storage reporting
|
||||
glNamedBufferStorage(_id, sizeof(uvec4) * TextureTable::COUNT, &_handles[0], 0);
|
||||
}
|
||||
|
||||
|
||||
GL45TextureTable::~GL45TextureTable() {
|
||||
if (_id) {
|
||||
auto backend = _backend.lock();
|
||||
if (backend) {
|
||||
// FIXME include these in overall buffer storage reporting
|
||||
backend->releaseBuffer(_id, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GL45TextureTable* GL45Backend::syncGPUObject(const TextureTablePointer& textureTablePointer) {
|
||||
const auto& textureTable = *textureTablePointer;
|
||||
|
||||
// Find the target handles
|
||||
auto textures = textureTable.getTextures();
|
||||
bool handlesComplete = true;
|
||||
GL45TextureTable::HandlesArray handles{};
|
||||
for (size_t i = 0; i < textures.size(); ++i) {
|
||||
auto texture = textures[i];
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
// FIXME what if we have a non-transferrable texture here?
|
||||
auto gltexture = (GL45Texture*)syncGPUObject(texture, true);
|
||||
if (!gltexture) {
|
||||
handlesComplete = false;
|
||||
continue;
|
||||
}
|
||||
auto handle = gltexture->getHandle();
|
||||
memcpy(&handles[i], &handle, sizeof(handle));
|
||||
}
|
||||
|
||||
// If the object hasn't been created, or the object definition is out of date, drop and re-create
|
||||
GL45TextureTable* object = Backend::getGPUObject<GL45TextureTable>(textureTable);
|
||||
|
||||
if (!object || object->_stamp != textureTable.getStamp() || !object->_complete || handles != object->_handles) {
|
||||
object = new GL45TextureTable(shared_from_this(), textureTable, handles, handlesComplete);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void GL45Backend::do_setResourceTextureTable(const Batch& batch, size_t paramOffset) {
|
||||
auto textureTable = batch._textureTables.get(batch._params[paramOffset]._uint);
|
||||
auto slot = batch._params[paramOffset + 1]._uint;
|
||||
GL45TextureTable* glTextureTable = syncGPUObject(textureTable);
|
||||
if (glTextureTable) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, slot + GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET, glTextureTable->_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,11 @@ class QDebug;
|
|||
namespace gpu {
|
||||
|
||||
enum ReservedSlot {
|
||||
#ifdef GPU_SSBO_DRAW_CALL_INFO
|
||||
TRANSFORM_OBJECT_SLOT = 14,
|
||||
#else
|
||||
TRANSFORM_OBJECT_SLOT = 31,
|
||||
#endif
|
||||
TRANSFORM_CAMERA_SLOT = 15,
|
||||
};
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8
|
||||
|
||||
struct GPUTextureTable {
|
||||
uvec2 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];
|
||||
uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];
|
||||
};
|
||||
|
||||
#define TextureTable(index, name) layout (std140) uniform gpu_textureTableBuffer { GPUTextureTable name; }
|
||||
#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }
|
||||
|
||||
#define tableTex(name, slot) sampler2D(name._textures[slot])
|
||||
#define tableTex(name, slot) sampler2D(name._textures[slot].xy)
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -145,6 +145,17 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
}
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
if (!_drawMaterialTextures) {
|
||||
_drawMaterialTextures = std::make_shared<gpu::TextureTable>();
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::ALBEDO_MAP, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::ROUGHNESS_MAP, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::NORMAL_MAP, textureCache->getBlueTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, textureCache->getBlackTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::OCCLUSION_MAP, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::SCATTERING_MAP, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture());
|
||||
}
|
||||
|
||||
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, _drawMaterial->getSchemaBuffer());
|
||||
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, _drawMaterial->getTexMapArrayBuffer());
|
||||
|
@ -172,9 +183,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isAlbedoMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView());
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::ALBEDO_MAP, itr->second->getTextureView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,11 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isRoughnessMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, itr->second->getTextureView());
|
||||
|
||||
// texcoord are assumed to be the same has albedo
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::ROUGHNESS_MAP, itr->second->getTextureView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,11 +199,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isNormalMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, itr->second->getTextureView());
|
||||
|
||||
// texcoord are assumed to be the same has albedo
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::NORMAL_MAP, itr->second->getTextureView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,11 +207,11 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isMetallicMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, itr->second->getTextureView());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, itr->second->getTextureView());
|
||||
|
||||
// texcoord are assumed to be the same has albedo
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, textureCache->getBlackTexture());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,11 +219,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isOcclusionMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, itr->second->getTextureView());
|
||||
|
||||
// texcoord are assumed to be the same has albedo
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::OCCLUSION_MAP, itr->second->getTextureView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,11 +227,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
if (materialKey.isScatteringMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP);
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, itr->second->getTextureView());
|
||||
|
||||
// texcoord are assumed to be the same has albedo
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::SCATTERING_MAP, itr->second->getTextureView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,17 +236,16 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP);
|
||||
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, itr->second->getTextureView());
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture());
|
||||
}
|
||||
} else if (materialKey.isEmissiveMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP);
|
||||
|
||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, itr->second->getTextureView());
|
||||
} else {
|
||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture());
|
||||
_drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue