From b7d0260a17654dd79854e5b65058b2cd74c6115f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 8 Feb 2018 14:05:21 -0800 Subject: [PATCH] Fix the uniform target for bindless --- libraries/gpu-gl/src/gpu/gl/GLShader.cpp | 444 +----------------- libraries/gpu-gl/src/gpu/gl/GLShader.h | 9 - .../src/gpu/gl41/GL41BackendTexture.cpp | 4 - libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 84 +++- .../gpu-gl/src/gpu/gl45/GL45BackendShader.cpp | 5 + .../src/gpu/gl45/GL45BackendTexture.cpp | 183 ++++++-- .../gpu/gl45/GL45BackendVariableTexture.cpp | 19 +- libraries/gpu/src/gpu/Texture.h | 34 +- libraries/gpu/src/gpu/TextureTable.h | 1 - libraries/gpu/src/gpu/TextureTable.slh | 3 - 10 files changed, 259 insertions(+), 527 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index 9c3de94957..7a26642024 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -10,447 +10,6 @@ #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 uniformBufferSlotMap(maxNumUniformBufferSlots, -1); - - struct UniformBlockInfo { - using Vector = std::vector; - 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; @@ -516,7 +75,8 @@ bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::Bin Shader::SlotSet textures; Shader::SlotSet textureTables; 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; backend.makeResourceBufferSlots(shaderObject.glprogram, slotBindings, resourceBuffers); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index a5a6a6e72c..b2a1f189a2 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -17,19 +17,10 @@ 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); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index b70730fd98..495f11e4a8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -167,7 +167,6 @@ void GL41Texture::syncSampler() const { glTexParameteri(_target, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]); 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_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip())); @@ -206,9 +205,6 @@ void GL41FixedAllocationTexture::allocateStorage() const { void GL41FixedAllocationTexture::syncSampler() const { Parent::syncSampler(); const Sampler& sampler = _gpuObject.getSampler(); - auto baseMip = std::max(sampler.getMipOffset(), sampler.getMinMip()); - - glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, baseMip); 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())); } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index 4fb12fbdb1..d733b38a2f 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -19,6 +19,7 @@ #define INCREMENTAL_TRANSFER 0 #define GPU_SSBO_TRANSFORM_OBJECT 1 +#define GPU_BINDLESS_TEXTURES 1 namespace gpu { namespace gl45 { @@ -49,21 +50,6 @@ public: static const std::string GL45_VERSION; const std::string& getVersion() const override { return GL45_VERSION; } - class GL45TextureTable : public GLObject { - static GLuint allocate(); - using Parent = GLObject; - public: - using HandlesArray = std::array; - GL45TextureTable(const std::weak_ptr& 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 { using Parent = GLTexture; friend class GL45Backend; @@ -73,8 +59,72 @@ public: 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; 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 { + static GLuint allocate(); + using Parent = GLObject; + public: + using BindlessArray = std::array; + + GL45TextureTable(const std::weak_ptr& 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 // @@ -89,6 +139,8 @@ public: protected: Size size() const override { return _size; } + uint16 getMinMip() const override { return 0; } + void allocateStorage() const; void syncSampler() const override; const Size _size { 0 }; @@ -125,6 +177,8 @@ public: ~GL45VariableAllocationTexture(); 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; void copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) override; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp index c2490524ae..9c973c9a6a 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp @@ -165,6 +165,11 @@ void GL45Backend::makeProgramBindings(ShaderObject& shaderObject) { 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(); } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index e3c10928b4..d33afc0e67 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include "../gl/GLTexelFormat.h" @@ -29,6 +30,10 @@ using namespace gpu::gl45; #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) { if (!texturePointer) { @@ -52,14 +57,18 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) { object = new GL45AttachmentTexture(shared_from_this(), texture); break; +#if FORCE_STRICT_TEXTURE + case TextureUsageType::RESOURCE: +#endif case TextureUsageType::STRICT_RESOURCE: qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str(); object = new GL45StrictResourceTexture(shared_from_this(), texture); break; +#if !FORCE_STRICT_TEXTURE case TextureUsageType::RESOURCE: { if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) { -#if 0 +#if ENABLE_SPARSE_TEXTURE if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) { object = new GL45SparseResourceTexture(shared_from_this(), texture); } else { @@ -77,7 +86,7 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) { } break; } - +#endif default: Q_UNREACHABLE(); } @@ -115,6 +124,50 @@ void GL45Backend::initTextureManagementStage() { 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 _samplerCache; +}; + +static GLSamplerCache SAMPLER_CACHE; +const Sampler GL45Texture::INVALID_SAMPLER = GL45Texture::InvalidSampler(); + GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& texture) : GLTexture(backend, texture, allocate(texture)) { } @@ -122,10 +175,10 @@ GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& GLuint GL45Texture::allocate(const Texture& texture) { GLuint result; glCreateTextures(getGLTextureType(texture), 1, &result); -#ifdef DEBUG - auto source = texture.source(); - glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data()); -#endif + if (::gl::Context::enableDebugLogger()) { + auto source = texture.source(); + glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data()); + } return result; } @@ -190,32 +243,69 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const return amountCopied; } -void GL45Texture::syncSampler() const { - const Sampler& sampler = _gpuObject.getSampler(); - - 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); +void GL45Texture::releaseBindless() const { + // Release the old handler + SAMPLER_CACHE.releaseGLSampler(_bindless.sampler); + glMakeTextureHandleNonResidentARB(_bindless.handle); + _bindless = Bindless(); +} + +void GL45Texture::recreateBindless() const { + if (isBindless()) { + releaseBindless(); } - 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()]); + _bindless.sampler = SAMPLER_CACHE.getGLSampler(_cachedSampler); + _bindless.handle = glGetTextureSamplerHandleARB(_id, _bindless.sampler); + glMakeTextureHandleResidentARB(_bindless.handle); +} - glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy()); - glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor()); +const GL45Texture::Bindless& GL45Texture::getBindless() const { + if (!_bindless) { + recreateBindless(); + } + _bindless.minMip = getMinMip(); + return _bindless; +} - 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 GL45Texture::syncSampler() const { + 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(); } +// Fixed allocation textures, used for strict resources & framebuffer attachments + using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture; GL45FixedAllocationTexture::GL45FixedAllocationTexture(const std::weak_ptr& backend, const Texture& texture) : GL45Texture(backend, texture), _size(texture.evalTotalSize()) { @@ -240,8 +330,6 @@ void GL45FixedAllocationTexture::allocateStorage() const { void GL45FixedAllocationTexture::syncSampler() const { Parent::syncSampler(); const Sampler& sampler = _gpuObject.getSampler(); - auto baseMip = std::max(sampler.getMipOffset(), sampler.getMinMip()); - glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip); 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())); } @@ -280,7 +368,6 @@ GL45StrictResourceTexture::GL45StrictResourceTexture(const std::weak_ptr& backend, const TextureTable& textureTable, const HandlesArray& handles, bool handlesComplete) - : Parent(backend, textureTable, allocate()), _stamp(textureTable.getStamp()), _handles(handles), _complete(handlesComplete) { +GL45TextureTable::GL45TextureTable(const std::weak_ptr& backend, const TextureTable& textureTable) + : Parent(backend, textureTable, allocate()){ Backend::setGPUObject(textureTable, this); // 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() { if (_id) { @@ -324,36 +410,33 @@ GL45TextureTable::~GL45TextureTable() { } } - GL45TextureTable* GL45Backend::syncGPUObject(const TextureTablePointer& textureTablePointer) { const auto& textureTable = *textureTablePointer; // Find the target handles auto textures = textureTable.getTextures(); - bool handlesComplete = true; - GL45TextureTable::HandlesArray handles{}; + GL45TextureTable::BindlessArray 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); + auto gltexture = (GL45Texture*)syncGPUObject(texture); if (!gltexture) { - handlesComplete = false; continue; } - auto handle = gltexture->getHandle(); - memcpy(&handles[i], &handle, sizeof(handle)); + handles[i] = gltexture->getBindless(); } // If the object hasn't been created, or the object definition is out of date, drop and re-create GL45TextureTable* object = Backend::getGPUObject(textureTable); - if (!object || object->_stamp != textureTable.getStamp() || !object->_complete || handles != object->_handles) { - object = new GL45TextureTable(shared_from_this(), textureTable, handles, handlesComplete); + if (!object) { + object = new GL45TextureTable(shared_from_this(), textureTable); } + object->update(handles); return object; } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp index 0f1de0f868..ab5577940c 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp @@ -27,6 +27,7 @@ using namespace gpu; using namespace gpu::gl; using namespace gpu::gl45; +using GL45Texture = GL45Backend::GL45Texture; using GL45VariableAllocationTexture = GL45Backend::GL45VariableAllocationTexture; GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr& backend, const Texture& texture) : GL45Texture(backend, texture) { @@ -40,6 +41,12 @@ GL45VariableAllocationTexture::~GL45VariableAllocationTexture() { 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 amountCopied = 0; amountCopied = Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer); @@ -127,7 +134,9 @@ Size GL45ResourceTexture::copyMipsFromTexture() { void GL45ResourceTexture::syncSampler() const { Parent::syncSampler(); - glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip); + if (!isBindless()) { + glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip); + } } void GL45ResourceTexture::promote() { @@ -137,6 +146,10 @@ void GL45ResourceTexture::promote() { uint16_t targetAllocatedMip = _allocatedMip - std::min(_allocatedMip, 2); targetAllocatedMip = std::max(_minAllocatedMip, targetAllocatedMip); + if (isBindless()) { + releaseBindless(); + } + GLuint oldId = _id; auto oldSize = _size; uint16_t oldAllocatedMip = _allocatedMip; @@ -170,6 +183,10 @@ void GL45ResourceTexture::demote() { auto oldSize = _size; auto oldPopulatedMip = _populatedMip; + if (isBindless()) { + releaseBindless(); + } + // allocate new texture const_cast(_id) = allocate(_gpuObject); uint16_t oldAllocatedMip = _allocatedMip; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index ad3dc5fada..096d6368f8 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #include "Forward.h" #include "Resource.h" #include "Metric.h" @@ -126,12 +128,23 @@ public: uint8 _wrapModeV = WRAP_REPEAT; uint8 _wrapModeW = WRAP_REPEAT; - uint8 _mipOffset = 0; uint8 _minMip = 0; uint8 _maxMip = MAX_MIP_LEVEL; Desc() {} 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() {} @@ -151,11 +164,17 @@ public: ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); } bool doComparison() const { return getComparisonFunction() != ALWAYS; } - uint8 getMipOffset() const { return _desc._mipOffset; } uint8 getMinMip() const { return _desc._minMip; } uint8 getMaxMip() const { return _desc._maxMip; } 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: Desc _desc; }; @@ -667,6 +686,17 @@ typedef std::shared_ptr< TextureSource > TextureSourcePointer; }; +namespace std { + template<> struct hash { + 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) #endif diff --git a/libraries/gpu/src/gpu/TextureTable.h b/libraries/gpu/src/gpu/TextureTable.h index 7b278bf304..4307e60adb 100644 --- a/libraries/gpu/src/gpu/TextureTable.h +++ b/libraries/gpu/src/gpu/TextureTable.h @@ -18,7 +18,6 @@ class TextureTable { public: static const size_t COUNT = 8; using Array = std::array; - using Array = std::array; TextureTable(); TextureTable(const std::initializer_list& textures); TextureTable(const std::array& textures); diff --git a/libraries/gpu/src/gpu/TextureTable.slh b/libraries/gpu/src/gpu/TextureTable.slh index d45c8f819b..1b83f4d622 100644 --- a/libraries/gpu/src/gpu/TextureTable.slh +++ b/libraries/gpu/src/gpu/TextureTable.slh @@ -25,7 +25,4 @@ struct GPUTextureTable { #endif - - - <@endif@>