mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 16:53:16 +02:00
Fix the uniform target for bindless
This commit is contained in:
parent
ab5355dbdd
commit
b7d0260a17
10 changed files with 259 additions and 527 deletions
|
@ -10,447 +10,6 @@
|
||||||
|
|
||||||
#include "GLBackend.h"
|
#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;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
|
|
||||||
|
@ -516,7 +75,8 @@ bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::Bin
|
||||||
Shader::SlotSet textures;
|
Shader::SlotSet textures;
|
||||||
Shader::SlotSet textureTables;
|
Shader::SlotSet textureTables;
|
||||||
Shader::SlotSet samplers;
|
Shader::SlotSet samplers;
|
||||||
backend.makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, textureTables, samplers);
|
//backend.makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, textureTables, samplers);
|
||||||
|
backend.makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, samplers);
|
||||||
|
|
||||||
Shader::SlotSet resourceBuffers;
|
Shader::SlotSet resourceBuffers;
|
||||||
backend.makeResourceBufferSlots(shaderObject.glprogram, slotBindings, resourceBuffers);
|
backend.makeResourceBufferSlots(shaderObject.glprogram, slotBindings, resourceBuffers);
|
||||||
|
|
|
@ -17,19 +17,10 @@ struct ShaderObject {
|
||||||
GLuint glprogram { 0 };
|
GLuint glprogram { 0 };
|
||||||
GLint transformCameraSlot { -1 };
|
GLint transformCameraSlot { -1 };
|
||||||
GLint transformObjectSlot { -1 };
|
GLint transformObjectSlot { -1 };
|
||||||
|
|
||||||
GLint resourceTextureTableSlot0 { -1 };
|
GLint resourceTextureTableSlot0 { -1 };
|
||||||
GLint resourceTextureTableSlot1 { -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 {
|
class GLShader : public GPUObject {
|
||||||
public:
|
public:
|
||||||
static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr);
|
static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr);
|
||||||
|
|
|
@ -167,7 +167,6 @@ void GL41Texture::syncSampler() const {
|
||||||
glTexParameteri(_target, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
glTexParameteri(_target, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, (uint16)sampler.getMipOffset());
|
|
||||||
|
|
||||||
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
@ -206,9 +205,6 @@ void GL41FixedAllocationTexture::allocateStorage() const {
|
||||||
void GL41FixedAllocationTexture::syncSampler() const {
|
void GL41FixedAllocationTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), sampler.getMinMip());
|
|
||||||
|
|
||||||
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, baseMip);
|
|
||||||
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.0f : sampler.getMaxMip()));
|
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.0f : sampler.getMaxMip()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#define INCREMENTAL_TRANSFER 0
|
#define INCREMENTAL_TRANSFER 0
|
||||||
#define GPU_SSBO_TRANSFORM_OBJECT 1
|
#define GPU_SSBO_TRANSFORM_OBJECT 1
|
||||||
|
#define GPU_BINDLESS_TEXTURES 1
|
||||||
|
|
||||||
namespace gpu { namespace gl45 {
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
@ -49,21 +50,6 @@ public:
|
||||||
static const std::string GL45_VERSION;
|
static const std::string GL45_VERSION;
|
||||||
const std::string& getVersion() const override { return GL45_VERSION; }
|
const std::string& getVersion() const override { return GL45_VERSION; }
|
||||||
|
|
||||||
class GL45TextureTable : public GLObject<TextureTable> {
|
|
||||||
static GLuint allocate();
|
|
||||||
using Parent = GLObject<TextureTable>;
|
|
||||||
public:
|
|
||||||
using HandlesArray = std::array<uvec4, TextureTable::COUNT>;
|
|
||||||
GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& texture, const HandlesArray& newHandles, bool complete);
|
|
||||||
~GL45TextureTable();
|
|
||||||
|
|
||||||
// FIXME instead of making a buffer for each table, there should be a global buffer of all materials
|
|
||||||
// and we should store an offset into that buffer
|
|
||||||
const uint32_t _stamp { 0 };
|
|
||||||
const HandlesArray _handles;
|
|
||||||
const bool _complete { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
class GL45Texture : public GLTexture {
|
class GL45Texture : public GLTexture {
|
||||||
using Parent = GLTexture;
|
using Parent = GLTexture;
|
||||||
friend class GL45Backend;
|
friend class GL45Backend;
|
||||||
|
@ -73,8 +59,72 @@ public:
|
||||||
void generateMips() const override;
|
void generateMips() const override;
|
||||||
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
||||||
void syncSampler() const override;
|
void syncSampler() const override;
|
||||||
|
|
||||||
|
bool isBindless() const {
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
return _bindless.operator bool();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
struct Bindless {
|
||||||
|
uint64_t handle{ 0 };
|
||||||
|
uint32_t minMip{ 0 };
|
||||||
|
uint32_t sampler{ 0 };
|
||||||
|
|
||||||
|
operator bool() const {
|
||||||
|
return handle != 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual const Bindless& getBindless() const;
|
||||||
|
void releaseBindless() const;
|
||||||
|
void recreateBindless() const;
|
||||||
|
virtual uint16 getMinMip() const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
class InvalidSampler : public Sampler {
|
||||||
|
public:
|
||||||
|
InvalidSampler() {
|
||||||
|
_desc._borderColor = vec4(-1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const Sampler&() const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Sampler INVALID_SAMPLER;
|
||||||
|
// This stores the texture handle (64 bits) in xy, the min mip available in z, and the sampler ID in w
|
||||||
|
mutable Sampler _cachedSampler{ INVALID_SAMPLER };
|
||||||
|
|
||||||
|
mutable Bindless _bindless;
|
||||||
|
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
class GL45TextureTable : public GLObject<TextureTable> {
|
||||||
|
static GLuint allocate();
|
||||||
|
using Parent = GLObject<TextureTable>;
|
||||||
|
public:
|
||||||
|
using BindlessArray = std::array<GL45Texture::Bindless, TextureTable::COUNT>;
|
||||||
|
|
||||||
|
GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& texture);
|
||||||
|
~GL45TextureTable();
|
||||||
|
|
||||||
|
void update(const BindlessArray& newHandles);
|
||||||
|
|
||||||
|
// FIXME instead of making a buffer for each table, there should be a global buffer of all materials
|
||||||
|
// and we should store an offset into that buffer
|
||||||
|
BindlessArray _handles;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Textures that have fixed allocation sizes and cannot be managed at runtime
|
// Textures that have fixed allocation sizes and cannot be managed at runtime
|
||||||
//
|
//
|
||||||
|
@ -89,6 +139,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Size size() const override { return _size; }
|
Size size() const override { return _size; }
|
||||||
|
uint16 getMinMip() const override { return 0; }
|
||||||
|
|
||||||
void allocateStorage() const;
|
void allocateStorage() const;
|
||||||
void syncSampler() const override;
|
void syncSampler() const override;
|
||||||
const Size _size { 0 };
|
const Size _size { 0 };
|
||||||
|
@ -125,6 +177,8 @@ public:
|
||||||
~GL45VariableAllocationTexture();
|
~GL45VariableAllocationTexture();
|
||||||
|
|
||||||
Size size() const override { return _size; }
|
Size size() const override { return _size; }
|
||||||
|
uint16 getMinMip() const override { return _populatedMip; }
|
||||||
|
virtual const Bindless& getBindless() const override;
|
||||||
|
|
||||||
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
||||||
void copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) override;
|
void copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) override;
|
||||||
|
|
|
@ -165,6 +165,11 @@ void GL45Backend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loc = glGetUniformBlockIndex(glprogram, "gpu_resourceTextureTable0");
|
||||||
|
if (loc >= 0) {
|
||||||
|
glUniformBlockBinding(glprogram, loc, RESOURCE_TABLE_TEXTURE_SLOT_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
#include <gl/Context.h>
|
||||||
#include <gpu/TextureTable.h>
|
#include <gpu/TextureTable.h>
|
||||||
#include "../gl/GLTexelFormat.h"
|
#include "../gl/GLTexelFormat.h"
|
||||||
|
|
||||||
|
@ -29,6 +30,10 @@ using namespace gpu::gl45;
|
||||||
|
|
||||||
#define MAX_RESOURCE_TEXTURES_PER_FRAME 2
|
#define MAX_RESOURCE_TEXTURES_PER_FRAME 2
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
|
#define FORCE_STRICT_TEXTURE 0
|
||||||
|
#define ENABLE_SPARSE_TEXTURE 0
|
||||||
|
|
||||||
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
if (!texturePointer) {
|
if (!texturePointer) {
|
||||||
|
@ -52,14 +57,18 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
object = new GL45AttachmentTexture(shared_from_this(), texture);
|
object = new GL45AttachmentTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if FORCE_STRICT_TEXTURE
|
||||||
|
case TextureUsageType::RESOURCE:
|
||||||
|
#endif
|
||||||
case TextureUsageType::STRICT_RESOURCE:
|
case TextureUsageType::STRICT_RESOURCE:
|
||||||
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
||||||
object = new GL45StrictResourceTexture(shared_from_this(), texture);
|
object = new GL45StrictResourceTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if !FORCE_STRICT_TEXTURE
|
||||||
case TextureUsageType::RESOURCE: {
|
case TextureUsageType::RESOURCE: {
|
||||||
if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) {
|
if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) {
|
||||||
#if 0
|
#if ENABLE_SPARSE_TEXTURE
|
||||||
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
||||||
object = new GL45SparseResourceTexture(shared_from_this(), texture);
|
object = new GL45SparseResourceTexture(shared_from_this(), texture);
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,7 +86,7 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -115,6 +124,50 @@ void GL45Backend::initTextureManagementStage() {
|
||||||
|
|
||||||
using GL45Texture = GL45Backend::GL45Texture;
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
|
|
||||||
|
|
||||||
|
class GLSamplerCache {
|
||||||
|
public:
|
||||||
|
GLuint getGLSampler(const Sampler& sampler) {
|
||||||
|
if (0 == _samplerCache.count(sampler)) {
|
||||||
|
GLuint result = 0;
|
||||||
|
glGenSamplers(1, &result);
|
||||||
|
const auto& fm = GLTexture::FILTER_MODES[sampler.getFilter()];
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
||||||
|
if (sampler.doComparison()) {
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE_ARB);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||||
|
} else {
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_S, GLTexture::WRAP_MODES[sampler.getWrapModeU()]);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_T, GLTexture::WRAP_MODES[sampler.getWrapModeV()]);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_R, GLTexture::WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
|
glSamplerParameterfv(result, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
|
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MIN_LOD, sampler.getMinMip());
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
_samplerCache[sampler] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _samplerCache[sampler];
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseGLSampler(GLuint sampler) {
|
||||||
|
// NO OP
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Sampler, GLuint> _samplerCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLSamplerCache SAMPLER_CACHE;
|
||||||
|
const Sampler GL45Texture::INVALID_SAMPLER = GL45Texture::InvalidSampler();
|
||||||
|
|
||||||
GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture)
|
GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture)
|
||||||
: GLTexture(backend, texture, allocate(texture)) {
|
: GLTexture(backend, texture, allocate(texture)) {
|
||||||
}
|
}
|
||||||
|
@ -122,10 +175,10 @@ GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
|
||||||
GLuint GL45Texture::allocate(const Texture& texture) {
|
GLuint GL45Texture::allocate(const Texture& texture) {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
glCreateTextures(getGLTextureType(texture), 1, &result);
|
glCreateTextures(getGLTextureType(texture), 1, &result);
|
||||||
#ifdef DEBUG
|
if (::gl::Context::enableDebugLogger()) {
|
||||||
auto source = texture.source();
|
auto source = texture.source();
|
||||||
glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data());
|
glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data());
|
||||||
#endif
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,32 +243,69 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
||||||
return amountCopied;
|
return amountCopied;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Texture::syncSampler() const {
|
void GL45Texture::releaseBindless() const {
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
// Release the old handler
|
||||||
|
SAMPLER_CACHE.releaseGLSampler(_bindless.sampler);
|
||||||
|
glMakeTextureHandleNonResidentARB(_bindless.handle);
|
||||||
|
_bindless = Bindless();
|
||||||
|
}
|
||||||
|
|
||||||
const auto& fm = FILTER_MODES[sampler.getFilter()];
|
void GL45Texture::recreateBindless() const {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
if (isBindless()) {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
releaseBindless();
|
||||||
|
|
||||||
if (sampler.doComparison()) {
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE_ARB);
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
|
||||||
} else {
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_WRAP_S, WRAP_MODES[sampler.getWrapModeU()]);
|
_bindless.sampler = SAMPLER_CACHE.getGLSampler(_cachedSampler);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]);
|
_bindless.handle = glGetTextureSamplerHandleARB(_id, _bindless.sampler);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
glMakeTextureHandleResidentARB(_bindless.handle);
|
||||||
|
}
|
||||||
|
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
const GL45Texture::Bindless& GL45Texture::getBindless() const {
|
||||||
glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
if (!_bindless) {
|
||||||
|
recreateBindless();
|
||||||
|
}
|
||||||
|
_bindless.minMip = getMinMip();
|
||||||
|
return _bindless;
|
||||||
|
}
|
||||||
|
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, sampler.getMinMip());
|
void GL45Texture::syncSampler() const {
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
|
bool samplerChanged = _cachedSampler != sampler;
|
||||||
|
if (samplerChanged) {
|
||||||
|
_cachedSampler = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBindless()) {
|
||||||
|
if (samplerChanged) {
|
||||||
|
recreateBindless();
|
||||||
|
}
|
||||||
|
} else if (samplerChanged) {
|
||||||
|
const auto& fm = FILTER_MODES[sampler.getFilter()];
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
||||||
|
|
||||||
|
if (sampler.doComparison()) {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE_ARB);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||||
|
} else {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_S, WRAP_MODES[sampler.getWrapModeU()]);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
|
glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
|
glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
|
|
||||||
|
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();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fixed allocation textures, used for strict resources & framebuffer attachments
|
||||||
|
|
||||||
using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture;
|
using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture;
|
||||||
|
|
||||||
GL45FixedAllocationTexture::GL45FixedAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture), _size(texture.evalTotalSize()) {
|
GL45FixedAllocationTexture::GL45FixedAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture), _size(texture.evalTotalSize()) {
|
||||||
|
@ -240,8 +330,6 @@ void GL45FixedAllocationTexture::allocateStorage() const {
|
||||||
void GL45FixedAllocationTexture::syncSampler() const {
|
void GL45FixedAllocationTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), sampler.getMinMip());
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip);
|
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
}
|
}
|
||||||
|
@ -280,7 +368,6 @@ GL45StrictResourceTexture::GL45StrictResourceTexture(const std::weak_ptr<GLBacke
|
||||||
|
|
||||||
// Re-sync the sampler to force access to the new mip level
|
// Re-sync the sampler to force access to the new mip level
|
||||||
syncSampler();
|
syncSampler();
|
||||||
updateSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
||||||
|
@ -288,16 +375,7 @@ GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
||||||
Backend::textureResidentGPUMemSize.update(size(), 0);
|
Backend::textureResidentGPUMemSize.update(size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uvec4& GL45Texture::getHandle() {
|
// Encapsulate bindless textures
|
||||||
if (uvec4() == _handleAndBias) {
|
|
||||||
auto handle = glGetTextureHandleARB(_id);
|
|
||||||
glMakeTextureHandleResidentARB(handle);
|
|
||||||
memcpy(&_handleAndBias, &handle, sizeof(handle));
|
|
||||||
}
|
|
||||||
_handleAndBias.z = _minMip;
|
|
||||||
return _handleAndBias;
|
|
||||||
}
|
|
||||||
|
|
||||||
using GL45TextureTable = GL45Backend::GL45TextureTable;
|
using GL45TextureTable = GL45Backend::GL45TextureTable;
|
||||||
|
|
||||||
GLuint GL45TextureTable::allocate() {
|
GLuint GL45TextureTable::allocate() {
|
||||||
|
@ -306,13 +384,21 @@ GLuint GL45TextureTable::allocate() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
GL45TextureTable::GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& textureTable, const HandlesArray& handles, bool handlesComplete)
|
GL45TextureTable::GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& textureTable)
|
||||||
: Parent(backend, textureTable, allocate()), _stamp(textureTable.getStamp()), _handles(handles), _complete(handlesComplete) {
|
: Parent(backend, textureTable, allocate()){
|
||||||
Backend::setGPUObject(textureTable, this);
|
Backend::setGPUObject(textureTable, this);
|
||||||
// FIXME include these in overall buffer storage reporting
|
// FIXME include these in overall buffer storage reporting
|
||||||
glNamedBufferStorage(_id, sizeof(uvec4) * TextureTable::COUNT, &_handles[0], 0);
|
glNamedBufferStorage(_id, sizeof(uvec4) * TextureTable::COUNT, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GL45TextureTable::update(const BindlessArray& handles) {
|
||||||
|
if (_handles != handles) {
|
||||||
|
_handles = handles;
|
||||||
|
// FIXME include these in overall buffer storage reporting
|
||||||
|
// FIXME use a single shared buffer for bindless data
|
||||||
|
glNamedBufferSubData(_id, 0, sizeof(GL45Texture::Bindless) * TextureTable::COUNT, &_handles[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GL45TextureTable::~GL45TextureTable() {
|
GL45TextureTable::~GL45TextureTable() {
|
||||||
if (_id) {
|
if (_id) {
|
||||||
|
@ -324,36 +410,33 @@ GL45TextureTable::~GL45TextureTable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GL45TextureTable* GL45Backend::syncGPUObject(const TextureTablePointer& textureTablePointer) {
|
GL45TextureTable* GL45Backend::syncGPUObject(const TextureTablePointer& textureTablePointer) {
|
||||||
const auto& textureTable = *textureTablePointer;
|
const auto& textureTable = *textureTablePointer;
|
||||||
|
|
||||||
// Find the target handles
|
// Find the target handles
|
||||||
auto textures = textureTable.getTextures();
|
auto textures = textureTable.getTextures();
|
||||||
bool handlesComplete = true;
|
GL45TextureTable::BindlessArray handles{};
|
||||||
GL45TextureTable::HandlesArray handles{};
|
|
||||||
for (size_t i = 0; i < textures.size(); ++i) {
|
for (size_t i = 0; i < textures.size(); ++i) {
|
||||||
auto texture = textures[i];
|
auto texture = textures[i];
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// FIXME what if we have a non-transferrable texture here?
|
// FIXME what if we have a non-transferrable texture here?
|
||||||
auto gltexture = (GL45Texture*)syncGPUObject(texture, true);
|
auto gltexture = (GL45Texture*)syncGPUObject(texture);
|
||||||
if (!gltexture) {
|
if (!gltexture) {
|
||||||
handlesComplete = false;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto handle = gltexture->getHandle();
|
handles[i] = gltexture->getBindless();
|
||||||
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
|
// 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);
|
GL45TextureTable* object = Backend::getGPUObject<GL45TextureTable>(textureTable);
|
||||||
|
|
||||||
if (!object || object->_stamp != textureTable.getStamp() || !object->_complete || handles != object->_handles) {
|
if (!object) {
|
||||||
object = new GL45TextureTable(shared_from_this(), textureTable, handles, handlesComplete);
|
object = new GL45TextureTable(shared_from_this(), textureTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object->update(handles);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ using namespace gpu;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
using GL45VariableAllocationTexture = GL45Backend::GL45VariableAllocationTexture;
|
using GL45VariableAllocationTexture = GL45Backend::GL45VariableAllocationTexture;
|
||||||
|
|
||||||
GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture) {
|
GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture) {
|
||||||
|
@ -40,6 +41,12 @@ GL45VariableAllocationTexture::~GL45VariableAllocationTexture() {
|
||||||
Backend::textureResourcePopulatedGPUMemSize.update(_populatedSize, 0);
|
Backend::textureResourcePopulatedGPUMemSize.update(_populatedSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GL45Texture::Bindless& GL45VariableAllocationTexture::getBindless() const {
|
||||||
|
auto& result = Parent::getBindless();
|
||||||
|
_bindless.minMip = _populatedMip - _allocatedMip;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Size GL45VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
Size GL45VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
||||||
Size amountCopied = 0;
|
Size amountCopied = 0;
|
||||||
amountCopied = Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer);
|
amountCopied = Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer);
|
||||||
|
@ -127,7 +134,9 @@ Size GL45ResourceTexture::copyMipsFromTexture() {
|
||||||
|
|
||||||
void GL45ResourceTexture::syncSampler() const {
|
void GL45ResourceTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
|
if (!isBindless()) {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45ResourceTexture::promote() {
|
void GL45ResourceTexture::promote() {
|
||||||
|
@ -137,6 +146,10 @@ void GL45ResourceTexture::promote() {
|
||||||
uint16_t targetAllocatedMip = _allocatedMip - std::min<uint16_t>(_allocatedMip, 2);
|
uint16_t targetAllocatedMip = _allocatedMip - std::min<uint16_t>(_allocatedMip, 2);
|
||||||
targetAllocatedMip = std::max<uint16_t>(_minAllocatedMip, targetAllocatedMip);
|
targetAllocatedMip = std::max<uint16_t>(_minAllocatedMip, targetAllocatedMip);
|
||||||
|
|
||||||
|
if (isBindless()) {
|
||||||
|
releaseBindless();
|
||||||
|
}
|
||||||
|
|
||||||
GLuint oldId = _id;
|
GLuint oldId = _id;
|
||||||
auto oldSize = _size;
|
auto oldSize = _size;
|
||||||
uint16_t oldAllocatedMip = _allocatedMip;
|
uint16_t oldAllocatedMip = _allocatedMip;
|
||||||
|
@ -170,6 +183,10 @@ void GL45ResourceTexture::demote() {
|
||||||
auto oldSize = _size;
|
auto oldSize = _size;
|
||||||
auto oldPopulatedMip = _populatedMip;
|
auto oldPopulatedMip = _populatedMip;
|
||||||
|
|
||||||
|
if (isBindless()) {
|
||||||
|
releaseBindless();
|
||||||
|
}
|
||||||
|
|
||||||
// allocate new texture
|
// allocate new texture
|
||||||
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
||||||
uint16_t oldAllocatedMip = _allocatedMip;
|
uint16_t oldAllocatedMip = _allocatedMip;
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <shared/Storage.h>
|
#include <shared/Storage.h>
|
||||||
#include <shared/FileCache.h>
|
#include <shared/FileCache.h>
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "Metric.h"
|
#include "Metric.h"
|
||||||
|
@ -126,12 +128,23 @@ public:
|
||||||
uint8 _wrapModeV = WRAP_REPEAT;
|
uint8 _wrapModeV = WRAP_REPEAT;
|
||||||
uint8 _wrapModeW = WRAP_REPEAT;
|
uint8 _wrapModeW = WRAP_REPEAT;
|
||||||
|
|
||||||
uint8 _mipOffset = 0;
|
|
||||||
uint8 _minMip = 0;
|
uint8 _minMip = 0;
|
||||||
uint8 _maxMip = MAX_MIP_LEVEL;
|
uint8 _maxMip = MAX_MIP_LEVEL;
|
||||||
|
|
||||||
Desc() {}
|
Desc() {}
|
||||||
Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {}
|
Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {}
|
||||||
|
|
||||||
|
bool operator==(const Desc& other) const {
|
||||||
|
return _borderColor == other._borderColor &&
|
||||||
|
_maxAnisotropy == other._maxAnisotropy &&
|
||||||
|
_filter == other._filter &&
|
||||||
|
_comparisonFunc == other._comparisonFunc &&
|
||||||
|
_wrapModeU == other._wrapModeU &&
|
||||||
|
_wrapModeV == other._wrapModeV &&
|
||||||
|
_wrapModeW == other._wrapModeW &&
|
||||||
|
_minMip == other._minMip &&
|
||||||
|
_maxMip == other._maxMip;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Sampler() {}
|
Sampler() {}
|
||||||
|
@ -151,11 +164,17 @@ public:
|
||||||
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
|
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
|
||||||
bool doComparison() const { return getComparisonFunction() != ALWAYS; }
|
bool doComparison() const { return getComparisonFunction() != ALWAYS; }
|
||||||
|
|
||||||
uint8 getMipOffset() const { return _desc._mipOffset; }
|
|
||||||
uint8 getMinMip() const { return _desc._minMip; }
|
uint8 getMinMip() const { return _desc._minMip; }
|
||||||
uint8 getMaxMip() const { return _desc._maxMip; }
|
uint8 getMaxMip() const { return _desc._maxMip; }
|
||||||
|
|
||||||
const Desc& getDesc() const { return _desc; }
|
const Desc& getDesc() const { return _desc; }
|
||||||
|
|
||||||
|
bool operator==(const Sampler& other) const {
|
||||||
|
return _desc == other._desc;
|
||||||
|
}
|
||||||
|
bool operator!=(const Sampler& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Desc _desc;
|
Desc _desc;
|
||||||
};
|
};
|
||||||
|
@ -667,6 +686,17 @@ typedef std::shared_ptr< TextureSource > TextureSourcePointer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<> struct hash<gpu::Sampler> {
|
||||||
|
size_t operator()(const gpu::Sampler& sampler) const noexcept {
|
||||||
|
size_t result = 0;
|
||||||
|
const auto& desc = sampler.getDesc();
|
||||||
|
hash_combine(result, desc._comparisonFunc, desc._filter, desc._maxAnisotropy, desc._maxMip, desc._minMip, desc._wrapModeU, desc._wrapModeV, desc._wrapModeW);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(gpu::TexturePointer)
|
Q_DECLARE_METATYPE(gpu::TexturePointer)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,7 +18,6 @@ class TextureTable {
|
||||||
public:
|
public:
|
||||||
static const size_t COUNT = 8;
|
static const size_t COUNT = 8;
|
||||||
using Array = std::array<TexturePointer, COUNT>;
|
using Array = std::array<TexturePointer, COUNT>;
|
||||||
using Array = std::array<TexturePointer, COUNT>;
|
|
||||||
TextureTable();
|
TextureTable();
|
||||||
TextureTable(const std::initializer_list<TexturePointer>& textures);
|
TextureTable(const std::initializer_list<TexturePointer>& textures);
|
||||||
TextureTable(const std::array<TexturePointer, COUNT>& textures);
|
TextureTable(const std::array<TexturePointer, COUNT>& textures);
|
||||||
|
|
|
@ -25,7 +25,4 @@ struct GPUTextureTable {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
Loading…
Reference in a new issue