From ab5355dbdd91ad8e8e0c5e2c8a803fb79819e610 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 25 Jan 2017 17:47:33 -0800 Subject: [PATCH] First pass at bindless textures --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 1 + libraries/gpu-gl/src/gpu/gl/GLBackend.h | 1 + libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 3 ++ .../src/gpu/gl41/GL41BackendTexture.cpp | 3 ++ libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 21 ++++++++ .../src/gpu/gl45/GL45BackendTexture.cpp | 3 +- libraries/gpu/src/gpu/Batch.cpp | 8 +++ libraries/gpu/src/gpu/Batch.h | 4 ++ libraries/gpu/src/gpu/Forward.h | 2 + libraries/gpu/src/gpu/TextureTable.cpp | 48 ++++++++++++++++++ libraries/gpu/src/gpu/TextureTable.h | 42 ++++++++++++++++ .../render-utils/src/MeshPartPayload.cpp | 49 +++++++++---------- libraries/render-utils/src/MeshPartPayload.h | 1 + 13 files changed, 160 insertions(+), 26 deletions(-) create mode 100644 libraries/gpu/src/gpu/TextureTable.cpp create mode 100644 libraries/gpu/src/gpu/TextureTable.h diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 08bd20be66..3a4c7b4f47 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -99,6 +99,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_setUniformBuffer), (&::gpu::gl::GLBackend::do_setResourceBuffer), (&::gpu::gl::GLBackend::do_setResourceTexture), + (&::gpu::gl::GLBackend::do_setResourceTextureTable), (&::gpu::gl::GLBackend::do_setFramebuffer), (&::gpu::gl::GLBackend::do_clearFramebuffer), diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index e13bfe8166..35aabef48f 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -132,6 +132,7 @@ public: // Resource Stage virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final; virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final; + virtual void do_setResourceTextureTable(const Batch& batch, size_t paramOffset) = 0; // Pipeline Stage virtual void do_setPipeline(const Batch& batch, size_t paramOffset) final; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 42926fdb1c..1b7882518d 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -157,6 +157,9 @@ protected: void resetInputStage() override; void updateInput() override; + // Resource stage + void do_setResourceTextureTable(const Batch& batch, size_t paramOffset) override; + // Synchronize the state cache of this Backend with the actual real state of the GL Context void transferTransformState(const Batch& batch) const override; void initTransform() override; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 925e83bb77..b70730fd98 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -611,3 +611,6 @@ GL41ResourceTexture::GL41ResourceTexture(const std::weak_ptr& backend GL41ResourceTexture::~GL41ResourceTexture() { } +void GL41Backend::do_setResourceTextureTable(const Batch& batch, size_t paramOffset) { + +} diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index 098ac11763..4fb12fbdb1 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -15,6 +15,7 @@ #include "../gl/GLBackend.h" #include "../gl/GLTexture.h" #include +#include #define INCREMENTAL_TRANSFER 0 #define GPU_SSBO_TRANSFORM_OBJECT 1 @@ -48,6 +49,21 @@ 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; @@ -181,6 +197,8 @@ protected: GLuint getQueryID(const QueryPointer& query) override; GLQuery* syncGPUObject(const Query& query) override; + GL45TextureTable* syncGPUObject(const TextureTablePointer& textureTable); + // Draw Stage void do_draw(const Batch& batch, size_t paramOffset) override; void do_drawIndexed(const Batch& batch, size_t paramOffset) override; @@ -193,6 +211,9 @@ protected: void resetInputStage() override; void updateInput() override; + // Resource stage + void do_setResourceTextureTable(const Batch& batch, size_t paramOffset) override; + // Synchronize the state cache of this Backend with the actual real state of the GL Context void transferTransformState(const Batch& batch) const override; void initTransform() override; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 45900a62b6..e3c10928b4 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -20,15 +20,16 @@ #include #include +#include #include "../gl/GLTexelFormat.h" using namespace gpu; using namespace gpu::gl; using namespace gpu::gl45; -#define SPARSE_PAGE_SIZE_OVERHEAD_ESTIMATE 1.3f #define MAX_RESOURCE_TEXTURES_PER_FRAME 2 + GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) { if (!texturePointer) { return nullptr; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index c432e19368..3764a94494 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -59,6 +59,7 @@ Batch::Batch(const Batch& batch_) { _buffers._items.swap(batch._buffers._items); _textures._items.swap(batch._textures._items); + _textureTables._items.swap(batch._textureTables._items); _streamFormats._items.swap(batch._streamFormats._items); _transforms._items.swap(batch._transforms._items); _pipelines._items.swap(batch._pipelines._items); @@ -96,6 +97,7 @@ void Batch::clear() { _data.clear(); _buffers.clear(); _textures.clear(); + _textureTables.clear(); _streamFormats.clear(); _transforms.clear(); _pipelines.clear(); @@ -306,6 +308,12 @@ void Batch::setResourceTexture(uint32 slot, const TexturePointer& texture) { _params.emplace_back(slot); } +void Batch::setResourceTextureTable(const TextureTablePointer& textureTable, uint32 slot) { + ADD_COMMAND(setResourceTextureTable); + _params.emplace_back(_textureTables.cache(textureTable)); + _params.emplace_back(slot); +} + void Batch::setResourceTexture(uint32 slot, const TextureView& view) { setResourceTexture(slot, view._texture); } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index a57ee94747..8eb769a6fe 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -193,6 +193,7 @@ public: void setResourceTexture(uint32 slot, const TexturePointer& texture); void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView + void setResourceTextureTable(const TextureTablePointer& table, uint32 slot = 0); // Ouput Stage void setFramebuffer(const FramebufferPointer& framebuffer); @@ -304,6 +305,7 @@ public: COMMAND_setUniformBuffer, COMMAND_setResourceBuffer, COMMAND_setResourceTexture, + COMMAND_setResourceTextureTable, COMMAND_setFramebuffer, COMMAND_clearFramebuffer, @@ -422,6 +424,7 @@ public: typedef Cache::Vector BufferCaches; typedef Cache::Vector TextureCaches; + typedef Cache::Vector TextureTableCaches; typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; typedef Cache::Vector PipelineCaches; @@ -476,6 +479,7 @@ public: BufferCaches _buffers; TextureCaches _textures; + TextureTableCaches _textureTables; StreamFormatCaches _streamFormats; TransformCaches _transforms; PipelineCaches _pipelines; diff --git a/libraries/gpu/src/gpu/Forward.h b/libraries/gpu/src/gpu/Forward.h index 8100efafaf..987788c29b 100644 --- a/libraries/gpu/src/gpu/Forward.h +++ b/libraries/gpu/src/gpu/Forward.h @@ -91,6 +91,8 @@ namespace gpu { using Textures = std::vector; class TextureView; using TextureViews = std::vector; + class TextureTable; + using TextureTablePointer = std::shared_ptr; struct StereoState { bool isStereo() const { diff --git a/libraries/gpu/src/gpu/TextureTable.cpp b/libraries/gpu/src/gpu/TextureTable.cpp new file mode 100644 index 0000000000..17a9e87f3e --- /dev/null +++ b/libraries/gpu/src/gpu/TextureTable.cpp @@ -0,0 +1,48 @@ +// +// Created by Bradley Austin Davis on 2017/01/25 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "TextureTable.h" +#include "Texture.h" + +using namespace gpu; + +TextureTable::TextureTable() { } + +TextureTable::TextureTable(const std::initializer_list& textures) { + auto max = std::min(COUNT, textures.size()); + auto itr = textures.begin(); + size_t index = 0; + while (itr != textures.end() && index < max) { + setTexture(index, *itr); + ++index; + } +} + +TextureTable::TextureTable(const std::array& textures) : _stamp(1), _textures(textures) { +} + +void TextureTable::setTexture(size_t index, const TexturePointer& texturePointer) { + if (index >= COUNT || _textures[index] == texturePointer) { + return; + } + { + Lock lock(_mutex); + ++_stamp; + _textures[index] = texturePointer; + } +} + +void TextureTable::setTexture(size_t index, const TextureView& textureView) { + setTexture(index, textureView._texture); +} + +TextureTable::Array TextureTable::getTextures() const { + Array result; + Lock lock(_mutex); + result = _textures; + return result; +} diff --git a/libraries/gpu/src/gpu/TextureTable.h b/libraries/gpu/src/gpu/TextureTable.h new file mode 100644 index 0000000000..7b278bf304 --- /dev/null +++ b/libraries/gpu/src/gpu/TextureTable.h @@ -0,0 +1,42 @@ +// +// Created by Bradley Austin Davis on 2017/01/25 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_gpu_TextureTable_h +#define hifi_gpu_TextureTable_h + +#include "Forward.h" + +#include + +namespace gpu { + +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); + + // Only for gpu::Context + const GPUObjectPointer gpuObject{}; + + void setTexture(size_t index, const TexturePointer& texturePointer); + void setTexture(size_t index, const TextureView& texturePointer); + + Array getTextures() const; + Stamp getStamp() const { return _stamp; } +private: + mutable Mutex _mutex; + Array _textures; + Stamp _stamp{ 0 }; +}; + +} + +#endif diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2428ec95aa..181eb19c8a 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include "DeferredLightingEffect.h" using namespace render; @@ -144,24 +146,25 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat return; } + + const auto& textureMaps = _drawMaterial->getTextureMaps(); + const auto& materialKey = _drawMaterial->getKey(); auto textureCache = DependencyManager::get(); if (!_drawMaterialTextures) { _drawMaterialTextures = std::make_shared(); - _drawMaterialTextures->setTexture(model::MaterialKey::ALBEDO_MAP, textureCache->getWhiteTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::ROUGHNESS_MAP, textureCache->getWhiteTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::NORMAL_MAP, textureCache->getBlueTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, textureCache->getBlackTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::OCCLUSION_MAP, textureCache->getWhiteTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::SCATTERING_MAP, textureCache->getWhiteTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture()); - _drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::ALBEDO_MAP, textureCache->getWhiteTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::ROUGHNESS_MAP, textureCache->getWhiteTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::NORMAL_MAP, textureCache->getBlueTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::METALLIC_MAP, textureCache->getBlackTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::OCCLUSION_MAP, textureCache->getWhiteTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::SCATTERING_MAP, textureCache->getWhiteTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture()); } batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, _drawMaterial->getSchemaBuffer()); batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, _drawMaterial->getTexMapArrayBuffer()); - - const auto& materialKey = _drawMaterial->getKey(); - const auto& textureMaps = _drawMaterial->getTextureMaps(); + batch.setResourceTextureTable(_drawMaterialTextures); int numUnlit = 0; if (materialKey.isUnlit()) { @@ -183,7 +186,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isAlbedoMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::ALBEDO_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::ALBEDO_MAP, itr->second->getTextureView()); } } @@ -191,7 +194,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isRoughnessMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::ROUGHNESS_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::ROUGHNESS_MAP, itr->second->getTextureView()); } } @@ -199,7 +202,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isNormalMap()) { auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::NORMAL_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::NORMAL_MAP, itr->second->getTextureView()); } } @@ -207,11 +210,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isMetallicMap()) { auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - _drawMaterialTextures->setTexture(model::MaterialKey::METALLIC_MAP, textureCache->getBlackTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::METALLIC_MAP, itr->second->getTextureView()); } } @@ -219,7 +218,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isOcclusionMap()) { auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::OCCLUSION_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::OCCLUSION_MAP, itr->second->getTextureView()); } } @@ -227,7 +226,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isScatteringMap()) { auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::SCATTERING_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::SCATTERING_MAP, itr->second->getTextureView()); } } @@ -236,16 +235,16 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::LIGHTMAP_MAP, itr->second->getTextureView()); } else { - _drawMaterialTextures->setTexture(model::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else if (materialKey.isEmissiveMap()) { auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); if (itr != textureMaps.end() && itr->second->isDefined()) { - _drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, itr->second->getTextureView()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::EMISSIVE_MAP, itr->second->getTextureView()); } else { - _drawMaterialTextures->setTexture(model::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture()); + _drawMaterialTextures->setTexture(graphics::MaterialKey::EMISSIVE_MAP, textureCache->getBlackTexture()); } } } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 21f9dc2e68..51bc7f39e0 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -67,6 +67,7 @@ public: std::shared_ptr _drawMaterial; graphics::Mesh::Part _drawPart; + mutable gpu::TextureTablePointer _drawMaterialTextures; size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; }