Merge pull request #13954 from jherico/fix/reduce_pointer_duplication

Reduce needless smart pointer duplication
This commit is contained in:
Bradley Austin Davis 2018-09-13 08:56:50 -07:00 committed by GitHub
commit d90551ac3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 353 additions and 207 deletions

View file

@ -201,9 +201,10 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
{ {
Vec2u outputSize{ 1,1 }; Vec2u outputSize{ 1,1 };
if (_output._framebuffer) { auto framebuffer = acquire(_output._framebuffer);
outputSize.x = _output._framebuffer->getWidth(); if (framebuffer) {
outputSize.y = _output._framebuffer->getHeight(); outputSize.x = framebuffer->getWidth();
outputSize.y = framebuffer->getHeight();
} else if (glm::dot(_transform._projectionJitter, _transform._projectionJitter)>0.0f) { } else if (glm::dot(_transform._projectionJitter, _transform._projectionJitter)>0.0f) {
qCWarning(gpugllogging) << "Jittering needs to have a frame buffer to be set"; qCWarning(gpugllogging) << "Jittering needs to have a frame buffer to be set";
} }
@ -220,6 +221,7 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
_stereo._contextDisable = false; _stereo._contextDisable = false;
break; break;
case Batch::COMMAND_setFramebuffer:
case Batch::COMMAND_setViewportTransform: case Batch::COMMAND_setViewportTransform:
case Batch::COMMAND_setViewTransform: case Batch::COMMAND_setViewTransform:
case Batch::COMMAND_setProjectionTransform: case Batch::COMMAND_setProjectionTransform:

View file

@ -30,7 +30,6 @@
#include "GLShared.h" #include "GLShared.h"
// Different versions for the stereo drawcall // Different versions for the stereo drawcall
// Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only // Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only
#if defined(USE_GLES) #if defined(USE_GLES)
@ -40,7 +39,6 @@
#define GPU_STEREO_TECHNIQUE_INSTANCED #define GPU_STEREO_TECHNIQUE_INSTANCED
#endif #endif
// Let these be configured by the one define picked above // Let these be configured by the one define picked above
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
#define GPU_STEREO_DRAWCALL_DOUBLED #define GPU_STEREO_DRAWCALL_DOUBLED
@ -56,8 +54,153 @@
#define GPU_STEREO_CAMERA_BUFFER #define GPU_STEREO_CAMERA_BUFFER
#endif #endif
//
// GL Backend pointer storage mechanism
// One of the following three defines must be defined.
// GPU_POINTER_STORAGE_SHARED
// The platonic ideal, use references to smart pointers.
// However, this produces artifacts because there are too many places in the code right now that
// create temporary values (undesirable smart pointer duplications) and then those temp variables
// get passed on and have their reference taken, and then invalidated
// GPU_POINTER_STORAGE_REF
// Raw pointer manipulation. Seems more dangerous than the reference wrappers,
// but in practice, the danger of grabbing a reference to a temporary variable
// is causing issues
// GPU_POINTER_STORAGE_RAW
#if defined(USE_GLES)
#define GPU_POINTER_STORAGE_SHARED
#else
#define GPU_POINTER_STORAGE_RAW
#endif
namespace gpu { namespace gl { namespace gpu { namespace gl {
#if defined(GPU_POINTER_STORAGE_SHARED)
template <typename T>
static inline bool compare(const std::shared_ptr<T>& a, const std::shared_ptr<T>& b) {
return a == b;
}
template <typename T>
static inline T* acquire(const std::shared_ptr<T>& pointer) {
return pointer.get();
}
template <typename T>
static inline void reset(std::shared_ptr<T>& pointer) {
return pointer.reset();
}
template <typename T>
static inline bool valid(const std::shared_ptr<T>& pointer) {
return pointer.operator bool();
}
template <typename T>
static inline void assign(std::shared_ptr<T>& pointer, const std::shared_ptr<T>& source) {
pointer = source;
}
using BufferReference = BufferPointer;
using TextureReference = TexturePointer;
using FramebufferReference = FramebufferPointer;
using FormatReference = Stream::FormatPointer;
using PipelineReference = PipelinePointer;
#define GPU_REFERENCE_INIT_VALUE nullptr
#elif defined(GPU_POINTER_STORAGE_REF)
template <typename T>
class PointerReferenceWrapper : public std::reference_wrapper<const std::shared_ptr<T>> {
using Parent = std::reference_wrapper<const std::shared_ptr<T>>;
public:
using Pointer = std::shared_ptr<T>;
PointerReferenceWrapper() : Parent(EMPTY()) {}
PointerReferenceWrapper(const Pointer& pointer) : Parent(pointer) {}
void clear() { *this = EMPTY(); }
private:
static const Pointer& EMPTY() {
static const Pointer EMPTY_VALUE;
return EMPTY_VALUE;
};
};
template <typename T>
static bool compare(const PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) {
return reference.get() == pointer;
}
template <typename T>
static inline T* acquire(const PointerReferenceWrapper<T>& reference) {
return reference.get().get();
}
template <typename T>
static void assign(PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) {
reference = pointer;
}
template <typename T>
static bool valid(const PointerReferenceWrapper<T>& reference) {
return reference.get().operator bool();
}
template <typename T>
static inline void reset(PointerReferenceWrapper<T>& reference) {
return reference.clear();
}
using BufferReference = PointerReferenceWrapper<Buffer>;
using TextureReference = PointerReferenceWrapper<Texture>;
using FramebufferReference = PointerReferenceWrapper<Framebuffer>;
using FormatReference = PointerReferenceWrapper<Stream::Format>;
using PipelineReference = PointerReferenceWrapper<Pipeline>;
#define GPU_REFERENCE_INIT_VALUE
#elif defined(GPU_POINTER_STORAGE_RAW)
template <typename T>
static bool compare(const T* const& rawPointer, const std::shared_ptr<T>& pointer) {
return rawPointer == pointer.get();
}
template <typename T>
static inline T* acquire(T*& rawPointer) {
return rawPointer;
}
template <typename T>
static inline bool valid(const T* const& rawPointer) {
return rawPointer;
}
template <typename T>
static inline void reset(T*& rawPointer) {
rawPointer = nullptr;
}
template <typename T>
static inline void assign(T*& rawPointer, const std::shared_ptr<T>& pointer) {
rawPointer = pointer.get();
}
using BufferReference = Buffer*;
using TextureReference = Texture*;
using FramebufferReference = Framebuffer*;
using FormatReference = Stream::Format*;
using PipelineReference = Pipeline*;
#define GPU_REFERENCE_INIT_VALUE nullptr
#endif
class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> { class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> {
// Context Backend static interface required // Context Backend static interface required
friend class gpu::Context; friend class gpu::Context;
@ -67,8 +210,8 @@ class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend>
protected: protected:
explicit GLBackend(bool syncCache); explicit GLBackend(bool syncCache);
GLBackend(); GLBackend();
public:
public:
#if defined(USE_GLES) #if defined(USE_GLES)
// https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGet.xhtml // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGet.xhtml
static const GLint MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16; static const GLint MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16;
@ -109,8 +252,8 @@ public:
// This is the ugly "download the pixels to sysmem for taking a snapshot" // This is the ugly "download the pixels to sysmem for taking a snapshot"
// Just avoid using it, it's ugly and will break performances // Just avoid using it, it's ugly and will break performances
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer,
const Vec4i& region, QImage& destImage) final override; const Vec4i& region,
QImage& destImage) final override;
// this is the maximum numeber of available input buffers // this is the maximum numeber of available input buffers
size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); } size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); }
@ -131,7 +274,6 @@ public:
static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2; static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2;
size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; } size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; }
// Draw Stage // Draw Stage
virtual void do_draw(const Batch& batch, size_t paramOffset) = 0; virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0; virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
@ -183,7 +325,6 @@ public:
// Reset stages // Reset stages
virtual void do_resetStages(const Batch& batch, size_t paramOffset) final; virtual void do_resetStages(const Batch& batch, size_t paramOffset) final;
virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final; virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final;
virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final; virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final;
@ -203,7 +344,7 @@ public:
virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final; virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final;
// TODO: As long as we have gl calls explicitely issued from interface // TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long // code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API // term strategy is to get rid of any GL calls in favor of the HIFI GPU API
virtual void do_glUniform1i(const Batch& batch, size_t paramOffset) final; virtual void do_glUniform1i(const Batch& batch, size_t paramOffset) final;
virtual void do_glUniform1f(const Batch& batch, size_t paramOffset) final; virtual void do_glUniform1f(const Batch& batch, size_t paramOffset) final;
@ -228,7 +369,9 @@ public:
virtual void do_setStateAntialiasedLineEnable(bool enable) final; virtual void do_setStateAntialiasedLineEnable(bool enable) final;
virtual void do_setStateDepthBias(Vec2 bias) final; virtual void do_setStateDepthBias(Vec2 bias) final;
virtual void do_setStateDepthTest(State::DepthTest test) final; virtual void do_setStateDepthTest(State::DepthTest test) final;
virtual void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) final; virtual void do_setStateStencil(State::StencilActivation activation,
State::StencilTest frontTest,
State::StencilTest backTest) final;
virtual void do_setStateAlphaToCoverageEnable(bool enable) final; virtual void do_setStateAlphaToCoverageEnable(bool enable) final;
virtual void do_setStateSampleMask(uint32 mask) final; virtual void do_setStateSampleMask(uint32 mask) final;
virtual void do_setStateBlend(State::BlendFunction blendFunction) final; virtual void do_setStateBlend(State::BlendFunction blendFunction) final;
@ -257,7 +400,9 @@ public:
virtual void releaseQuery(GLuint id) const; virtual void releaseQuery(GLuint id) const;
virtual void queueLambda(const std::function<void()> lambda) const; virtual void queueLambda(const std::function<void()> lambda) const;
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); } bool isTextureManagementSparseEnabled() const override {
return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures());
}
protected: protected:
virtual GLint getRealUniformLocation(GLint location) const; virtual GLint getRealUniformLocation(GLint location) const;
@ -266,11 +411,11 @@ protected:
// FIXME instead of a single flag, create a features struct similar to // FIXME instead of a single flag, create a features struct similar to
// https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPhysicalDeviceFeatures.html // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPhysicalDeviceFeatures.html
virtual bool supportsBindless() const { return false; } virtual bool supportsBindless() const { return false; }
static const size_t INVALID_OFFSET = (size_t)-1; static const size_t INVALID_OFFSET = (size_t)-1;
bool _inRenderTransferPass { false }; bool _inRenderTransferPass{ false };
int _currentDraw { -1 }; int _currentDraw{ -1 };
std::list<std::string> profileRanges; std::list<std::string> profileRanges;
mutable Mutex _trashMutex; mutable Mutex _trashMutex;
@ -299,46 +444,36 @@ protected:
virtual void updateInput() = 0; virtual void updateInput() = 0;
struct InputStageState { struct InputStageState {
bool _invalidFormat { true }; bool _invalidFormat{ true };
bool _lastUpdateStereoState{ false }; bool _lastUpdateStereoState{ false };
bool _hadColorAttribute{ true }; bool _hadColorAttribute{ true };
Stream::FormatPointer _format; FormatReference _format{ GPU_REFERENCE_INIT_VALUE };
std::string _formatKey; std::string _formatKey;
typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache; typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
ActivationCache _attributeActivation { 0 }; ActivationCache _attributeActivation{ 0 };
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState; typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
BuffersState _invalidBuffers{ 0 }; BuffersState _invalidBuffers{ 0 };
BuffersState _attribBindingBuffers{ 0 }; BuffersState _attribBindingBuffers{ 0 };
Buffers _buffers; std::array<BufferReference, MAX_NUM_INPUT_BUFFERS> _buffers{};
Offsets _bufferOffsets; std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferOffsets{};
Offsets _bufferStrides; std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides{};
std::vector<GLuint> _bufferVBOs; std::array<GLuint, MAX_NUM_INPUT_BUFFERS> _bufferVBOs{};
glm::vec4 _colorAttribute{ 0.0f }; glm::vec4 _colorAttribute{ 0.0f };
BufferPointer _indexBuffer; BufferReference _indexBuffer{};
Offset _indexBufferOffset { 0 }; Offset _indexBufferOffset{ 0 };
Type _indexBufferType { UINT32 }; Type _indexBufferType{ UINT32 };
BufferPointer _indirectBuffer; BufferReference _indirectBuffer{};
Offset _indirectBufferOffset{ 0 }; Offset _indirectBufferOffset{ 0 };
Offset _indirectBufferStride{ 0 }; Offset _indirectBufferStride{ 0 };
GLuint _defaultVAO { 0 }; GLuint _defaultVAO{ 0 };
InputStageState() :
_invalidFormat(true),
_format(0),
_formatKey(),
_attributeActivation(0),
_buffers(_invalidBuffers.size(), BufferPointer(0)),
_bufferOffsets(_invalidBuffers.size(), 0),
_bufferStrides(_invalidBuffers.size(), 0),
_bufferVBOs(_invalidBuffers.size(), 0) {}
} _input; } _input;
virtual void initTransform() = 0; virtual void initTransform() = 0;
@ -349,7 +484,7 @@ protected:
virtual void resetTransformStage(); virtual void resetTransformStage();
// Allows for correction of the camera pose to account for changes // Allows for correction of the camera pose to account for changes
// between the time when a was recorded and the time(s) when it is // between the time when a was recorded and the time(s) when it is
// executed // executed
// Prev is the previous correction used at previous frame // Prev is the previous correction used at previous frame
struct CameraCorrection { struct CameraCorrection {
@ -364,9 +499,12 @@ protected:
struct Cameras { struct Cameras {
TransformCamera _cams[2]; TransformCamera _cams[2];
Cameras() {}; Cameras(){};
Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); }; Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); };
Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); }; Cameras(const TransformCamera& camL, const TransformCamera& camR) {
memcpy(_cams, &camL, sizeof(TransformCamera));
memcpy(_cams + 1, &camR, sizeof(TransformCamera));
};
}; };
using CameraBufferElement = Cameras; using CameraBufferElement = Cameras;
@ -380,25 +518,24 @@ protected:
mutable std::map<std::string, GLvoid*> _drawCallInfoOffsets; mutable std::map<std::string, GLvoid*> _drawCallInfoOffsets;
GLuint _objectBuffer { 0 }; GLuint _objectBuffer{ 0 };
GLuint _cameraBuffer { 0 }; GLuint _cameraBuffer{ 0 };
GLuint _drawCallInfoBuffer { 0 }; GLuint _drawCallInfoBuffer{ 0 };
GLuint _objectBufferTexture { 0 }; GLuint _objectBufferTexture{ 0 };
size_t _cameraUboSize { 0 }; size_t _cameraUboSize{ 0 };
bool _viewIsCamera{ false }; bool _viewIsCamera{ false };
bool _skybox { false }; bool _skybox{ false };
Transform _view; Transform _view;
CameraCorrection _correction; CameraCorrection _correction;
bool _viewCorrectionEnabled{ true }; bool _viewCorrectionEnabled{ true };
Mat4 _projection; Mat4 _projection;
Vec4i _viewport { 0, 0, 1, 1 }; Vec4i _viewport{ 0, 0, 1, 1 };
Vec2 _depthRange { 0.0f, 1.0f }; Vec2 _depthRange{ 0.0f, 1.0f };
Vec2 _projectionJitter{ 0.0f, 0.0f }; Vec2 _projectionJitter{ 0.0f, 0.0f };
bool _invalidView { false }; bool _invalidView{ false };
bool _invalidProj { false }; bool _invalidProj{ false };
bool _invalidViewport { false }; bool _invalidViewport{ false };
bool _enabledDrawcallInfoBuffer{ false }; bool _enabledDrawcallInfoBuffer{ false };
@ -417,45 +554,54 @@ protected:
struct UniformStageState { struct UniformStageState {
struct BufferState { struct BufferState {
BufferPointer buffer; BufferReference buffer{};
GLintptr offset{ 0 }; GLintptr offset{ 0 };
GLsizeiptr size{ 0 }; GLsizeiptr size{ 0 };
BufferState(const BufferPointer& buffer = nullptr, GLintptr offset = 0, GLsizeiptr size = 0);
bool operator ==(BufferState& other) const { BufferState& operator=(const BufferState& other) = delete;
return offset == other.offset && size == other.size && buffer == other.buffer; void reset() {
gpu::gl::reset(buffer);
offset = 0;
size = 0;
}
bool compare(const BufferPointer& buffer, GLintptr offset, GLsizeiptr size) {
const auto& self = *this;
return (self.offset == offset && self.size == size && gpu::gl::compare(self.buffer, buffer));
} }
}; };
// MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but // MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but
// MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some // MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some
// internal UBOs for things like camera correction // internal UBOs for things like camera correction
std::array<BufferState, MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS> _buffers; std::array<BufferState, MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS> _buffers;
} _uniform; } _uniform;
// Helper function that provides common code // Helper function that provides common code
void bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset = 0, GLsizeiptr size = 0); void bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset = 0, GLsizeiptr size = 0);
void releaseUniformBuffer(uint32_t slot); void releaseUniformBuffer(uint32_t slot);
void resetUniformStage(); void resetUniformStage();
// update resource cache and do the gl bind/unbind call with the current gpu::Buffer cached at slot s // update resource cache and do the gl bind/unbind call with the current gpu::Buffer cached at slot s
// This is using different gl object depending on the gl version // This is using different gl object depending on the gl version
virtual bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) = 0; virtual bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) = 0;
virtual void releaseResourceBuffer(uint32_t slot) = 0; virtual void releaseResourceBuffer(uint32_t slot) = 0;
// Helper function that provides common code used by do_setResourceTexture and // Helper function that provides common code used by do_setResourceTexture and
// do_setResourceTextureTable (in non-bindless mode) // do_setResourceTextureTable (in non-bindless mode)
void bindResourceTexture(uint32_t slot, const TexturePointer& texture); void bindResourceTexture(uint32_t slot, const TexturePointer& texture);
// update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s // update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s
void releaseResourceTexture(uint32_t slot); void releaseResourceTexture(uint32_t slot);
void resetResourceStage(); void resetResourceStage();
struct ResourceStageState { struct ResourceStageState {
std::array<BufferPointer, MAX_NUM_RESOURCE_BUFFERS> _buffers; struct TextureState {
std::array<TexturePointer, MAX_NUM_RESOURCE_TEXTURES> _textures; TextureReference _texture{};
//Textures _textures { { MAX_NUM_RESOURCE_TEXTURES } }; GLenum _target;
};
std::array<BufferReference, MAX_NUM_RESOURCE_BUFFERS> _buffers{};
std::array<TextureState, MAX_NUM_RESOURCE_TEXTURES> _textures{};
int findEmptyTextureSlot() const; int findEmptyTextureSlot() const;
} _resource; } _resource;
@ -470,21 +616,22 @@ protected:
void resetPipelineStage(); void resetPipelineStage();
struct PipelineStageState { struct PipelineStageState {
PipelinePointer _pipeline; PipelineReference _pipeline{};
GLuint _program { 0 }; GLuint _program{ 0 };
bool _cameraCorrection { false }; bool _cameraCorrection{ false };
GLShader* _programShader { nullptr }; GLShader* _programShader{ nullptr };
bool _invalidProgram { false }; bool _invalidProgram{ false };
BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr )) }; BufferView _cameraCorrectionBuffer{ gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr)) };
BufferView _cameraCorrectionBufferIdentity { gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr )) }; BufferView _cameraCorrectionBufferIdentity{ gpu::BufferView(
std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr)) };
State::Data _stateCache{ State::DEFAULT }; State::Data _stateCache{ State::DEFAULT };
State::Signature _stateSignatureCache { 0 }; State::Signature _stateSignatureCache{ 0 };
GLState* _state { nullptr }; GLState* _state{ nullptr };
bool _invalidState { false }; bool _invalidState{ false };
PipelineStageState() { PipelineStageState() {
_cameraCorrectionBuffer.edit<CameraCorrection>() = CameraCorrection(); _cameraCorrectionBuffer.edit<CameraCorrection>() = CameraCorrection();
@ -498,9 +645,9 @@ protected:
virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler); virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler); virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
virtual std::string getBackendShaderHeader() const = 0; virtual std::string getBackendShaderHeader() const = 0;
// For a program, this will return a string containing all the source files (without any // For a program, this will return a string containing all the source files (without any
// backend headers or defines). For a vertex, fragment or geometry shader, this will // backend headers or defines). For a vertex, fragment or geometry shader, this will
// return the fully customized shader with all the version and backend specific // return the fully customized shader with all the version and backend specific
// preprocessor directives // preprocessor directives
// The program string returned can be used as a key for a cache of shader binaries // The program string returned can be used as a key for a cache of shader binaries
// The shader strings can be reliably sent to the low level `compileShader` functions // The shader strings can be reliably sent to the low level `compileShader` functions
@ -516,22 +663,22 @@ protected:
// Synchronize the state cache of this Backend with the actual real state of the GL Context // Synchronize the state cache of this Backend with the actual real state of the GL Context
void syncOutputStateCache(); void syncOutputStateCache();
void resetOutputStage(); void resetOutputStage();
struct OutputStageState { struct OutputStageState {
FramebufferPointer _framebuffer { nullptr }; FramebufferReference _framebuffer{};
GLuint _drawFBO { 0 }; GLuint _drawFBO{ 0 };
} _output; } _output;
void resetQueryStage(); void resetQueryStage();
struct QueryStageState { struct QueryStageState {
uint32_t _rangeQueryDepth { 0 }; uint32_t _rangeQueryDepth{ 0 };
} _queryStage; } _queryStage;
void resetStages(); void resetStages();
// Stores cached binary versions of the shaders for quicker startup on subsequent runs // Stores cached binary versions of the shaders for quicker startup on subsequent runs
// Note that shaders in the cache can still fail to load due to hardware or driver // Note that shaders in the cache can still fail to load due to hardware or driver
// changes that invalidate the cached binary, in which case we fall back on compiling // changes that invalidate the cached binary, in which case we fall back on compiling
// the source again // the source again
struct ShaderBinaryCache { struct ShaderBinaryCache {
std::mutex _mutex; std::mutex _mutex;
@ -543,7 +690,7 @@ protected:
virtual void killShaderBinaryCache(); virtual void killShaderBinaryCache();
struct TextureManagementStageState { struct TextureManagementStageState {
bool _sparseCapable { false }; bool _sparseCapable{ false };
GLTextureTransferEnginePointer _transferEngine; GLTextureTransferEnginePointer _transferEngine;
} _textureManagement; } _textureManagement;
virtual void initTextureManagementStage(); virtual void initTextureManagementStage();
@ -556,6 +703,6 @@ protected:
friend class GLShader; friend class GLShader;
}; };
} } }} // namespace gpu::gl
#endif #endif

View file

@ -17,10 +17,10 @@ using namespace gpu;
using namespace gpu::gl; using namespace gpu::gl;
void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) { void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) {
Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint); const auto& format = batch._streamFormats.get(batch._params[paramOffset]._uint);
if (format != _input._format) { if (!compare(_input._format, format)) {
_input._format = format;
if (format) { if (format) {
assign(_input._format, format);
auto inputFormat = GLInputFormat::sync((*format)); auto inputFormat = GLInputFormat::sync((*format));
assert(inputFormat); assert(inputFormat);
if (_input._formatKey != inputFormat->key) { if (_input._formatKey != inputFormat->key) {
@ -28,6 +28,7 @@ void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) {
_input._invalidFormat = true; _input._invalidFormat = true;
} }
} else { } else {
reset(_input._format);
_input._formatKey.clear(); _input._formatKey.clear();
_input._invalidFormat = true; _input._invalidFormat = true;
} }
@ -37,13 +38,13 @@ void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) {
void GLBackend::do_setInputBuffer(const Batch& batch, size_t paramOffset) { void GLBackend::do_setInputBuffer(const Batch& batch, size_t paramOffset) {
Offset stride = batch._params[paramOffset + 0]._uint; Offset stride = batch._params[paramOffset + 0]._uint;
Offset offset = batch._params[paramOffset + 1]._uint; Offset offset = batch._params[paramOffset + 1]._uint;
BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); const auto& buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
uint32 channel = batch._params[paramOffset + 3]._uint; uint32 channel = batch._params[paramOffset + 3]._uint;
if (channel < getNumInputBuffers()) { if (channel < getNumInputBuffers()) {
bool isModified = false; bool isModified = false;
if (_input._buffers[channel] != buffer) { if (!compare(_input._buffers[channel], buffer)) {
_input._buffers[channel] = buffer; assign(_input._buffers[channel], buffer);
_input._bufferVBOs[channel] = getBufferIDUnsynced((*buffer)); _input._bufferVBOs[channel] = getBufferIDUnsynced((*buffer));
isModified = true; isModified = true;
} }
@ -94,18 +95,18 @@ void GLBackend::resetInputStage() {
// Reset index buffer // Reset index buffer
_input._indexBufferType = UINT32; _input._indexBufferType = UINT32;
_input._indexBufferOffset = 0; _input._indexBufferOffset = 0;
_input._indexBuffer.reset(); reset(_input._indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
// Reset vertex buffer and format // Reset vertex buffer and format
_input._format.reset(); reset(_input._format);
_input._formatKey.clear(); _input._formatKey.clear();
_input._invalidFormat = false; _input._invalidFormat = false;
_input._attributeActivation.reset(); _input._attributeActivation.reset();
for (uint32_t i = 0; i < _input._buffers.size(); i++) { for (uint32_t i = 0; i < _input._buffers.size(); i++) {
_input._buffers[i].reset(); reset(_input._buffers[i]);
_input._bufferOffsets[i] = 0; _input._bufferOffsets[i] = 0;
_input._bufferStrides[i] = 0; _input._bufferStrides[i] = 0;
_input._bufferVBOs[i] = 0; _input._bufferVBOs[i] = 0;
@ -119,9 +120,9 @@ void GLBackend::do_setIndexBuffer(const Batch& batch, size_t paramOffset) {
_input._indexBufferType = (Type)batch._params[paramOffset + 2]._uint; _input._indexBufferType = (Type)batch._params[paramOffset + 2]._uint;
_input._indexBufferOffset = batch._params[paramOffset + 0]._uint; _input._indexBufferOffset = batch._params[paramOffset + 0]._uint;
BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); const auto& indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint);
if (indexBuffer != _input._indexBuffer) { if (!compare(_input._indexBuffer, indexBuffer)) {
_input._indexBuffer = indexBuffer; assign(_input._indexBuffer, indexBuffer);
if (indexBuffer) { if (indexBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferIDUnsynced(*indexBuffer)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferIDUnsynced(*indexBuffer));
} else { } else {
@ -136,9 +137,9 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) {
_input._indirectBufferOffset = batch._params[paramOffset + 1]._uint; _input._indirectBufferOffset = batch._params[paramOffset + 1]._uint;
_input._indirectBufferStride = batch._params[paramOffset + 2]._uint; _input._indirectBufferStride = batch._params[paramOffset + 2]._uint;
BufferPointer buffer = batch._buffers.get(batch._params[paramOffset]._uint); const auto& buffer = batch._buffers.get(batch._params[paramOffset]._uint);
if (buffer != _input._indirectBuffer) { if (!compare(_input._indirectBuffer, buffer)) {
_input._indirectBuffer = buffer; assign(_input._indirectBuffer, buffer);
if (buffer) { if (buffer) {
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, getBufferIDUnsynced(*buffer)); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, getBufferIDUnsynced(*buffer));
} else { } else {
@ -152,7 +153,7 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) {
void GLBackend::updateInput() { void GLBackend::updateInput() {
bool isStereoNow = isStereo(); bool isStereoNow = isStereo();
// track stereo state change potentially happening wihtout changing the input format // track stereo state change potentially happening without changing the input format
// this is a rare case requesting to invalid the format // this is a rare case requesting to invalid the format
#ifdef GPU_STEREO_DRAWCALL_INSTANCED #ifdef GPU_STEREO_DRAWCALL_INSTANCED
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState); _input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
@ -163,13 +164,14 @@ void GLBackend::updateInput() {
InputStageState::ActivationCache newActivation; InputStageState::ActivationCache newActivation;
// Assign the vertex format required // Assign the vertex format required
if (_input._format) { auto format = acquire(_input._format);
if (format) {
bool hasColorAttribute{ false }; bool hasColorAttribute{ false };
_input._attribBindingBuffers.reset(); _input._attribBindingBuffers.reset();
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); const auto& attributes = format->getAttributes();
auto& inputChannels = _input._format->getChannels(); const auto& inputChannels = format->getChannels();
for (auto& channelIt : inputChannels) { for (auto& channelIt : inputChannels) {
auto bufferChannelNum = (channelIt).first; auto bufferChannelNum = (channelIt).first;
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second; const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;

View file

@ -27,12 +27,12 @@ void GLBackend::syncOutputStateCache() {
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFBO); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFBO);
_output._drawFBO = currentFBO; _output._drawFBO = currentFBO;
_output._framebuffer.reset(); reset(_output._framebuffer);
} }
void GLBackend::resetOutputStage() { void GLBackend::resetOutputStage() {
if (_output._framebuffer) { if (valid(_output._framebuffer)) {
_output._framebuffer.reset(); reset(_output._framebuffer);
_output._drawFBO = 0; _output._drawFBO = 0;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
@ -41,7 +41,7 @@ void GLBackend::resetOutputStage() {
} }
void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) {
auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); const auto& framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
setFramebuffer(framebuffer); setFramebuffer(framebuffer);
} }
@ -55,13 +55,13 @@ void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffse
} }
void GLBackend::setFramebuffer(const FramebufferPointer& framebuffer) { void GLBackend::setFramebuffer(const FramebufferPointer& framebuffer) {
if (_output._framebuffer != framebuffer) { if (!compare(_output._framebuffer, framebuffer)) {
auto newFBO = getFramebufferID(framebuffer); auto newFBO = getFramebufferID(framebuffer);
if (_output._drawFBO != newFBO) { if (_output._drawFBO != newFBO) {
_output._drawFBO = newFBO; _output._drawFBO = newFBO;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newFBO);
} }
_output._framebuffer = framebuffer; assign(_output._framebuffer, framebuffer);
} }
} }
@ -114,8 +114,9 @@ void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) {
} }
std::vector<GLenum> drawBuffers; std::vector<GLenum> drawBuffers;
auto framebuffer = acquire(_output._framebuffer);
if (masks & Framebuffer::BUFFER_COLORS) { if (masks & Framebuffer::BUFFER_COLORS) {
if (_output._framebuffer) { if (framebuffer) {
for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) {
if (masks & (1 << i)) { if (masks & (1 << i)) {
drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i);
@ -163,8 +164,8 @@ void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) {
} }
// Restore the color draw buffers only if a frmaebuffer is bound // Restore the color draw buffers only if a frmaebuffer is bound
if (_output._framebuffer && !drawBuffers.empty()) { if (framebuffer && !drawBuffers.empty()) {
auto glFramebuffer = syncGPUObject(*_output._framebuffer); auto glFramebuffer = syncGPUObject(*framebuffer);
if (glFramebuffer) { if (glFramebuffer) {
glDrawBuffers((GLsizei)glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data()); glDrawBuffers((GLsizei)glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data());
} }

View file

@ -23,9 +23,9 @@ using namespace gpu;
using namespace gpu::gl; using namespace gpu::gl;
void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) { void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint); const auto& pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint);
if (_pipeline._pipeline == pipeline) { if (compare(_pipeline._pipeline, pipeline)) {
return; return;
} }
@ -34,7 +34,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
// null pipeline == reset // null pipeline == reset
if (!pipeline) { if (!pipeline) {
_pipeline._pipeline.reset(); reset(_pipeline._pipeline);
_pipeline._program = 0; _pipeline._program = 0;
_pipeline._cameraCorrection = false; _pipeline._cameraCorrection = false;
@ -73,7 +73,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
} }
// Remember the new pipeline // Remember the new pipeline
_pipeline._pipeline = pipeline; assign(_pipeline._pipeline, pipeline);
} }
// THis should be done on Pipeline::update... // THis should be done on Pipeline::update...
@ -81,7 +81,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
glUseProgram(_pipeline._program); glUseProgram(_pipeline._program);
if (_pipeline._cameraCorrection) { if (_pipeline._cameraCorrection) {
// Invalidate uniform buffer cache slot // Invalidate uniform buffer cache slot
_uniform._buffers[gpu::slot::buffer::CameraCorrection] = {}; _uniform._buffers[gpu::slot::buffer::CameraCorrection].reset();
auto& cameraCorrectionBuffer = _transform._viewCorrectionEnabled ? auto& cameraCorrectionBuffer = _transform._viewCorrectionEnabled ?
_pipeline._cameraCorrectionBuffer._buffer : _pipeline._cameraCorrectionBuffer._buffer :
_pipeline._cameraCorrectionBufferIdentity._buffer; _pipeline._cameraCorrectionBufferIdentity._buffer;
@ -112,7 +112,7 @@ void GLBackend::updatePipeline() {
_pipeline._stateSignatureCache |= _pipeline._state->_signature; _pipeline._stateSignatureCache |= _pipeline._state->_signature;
// And perform // And perform
for (auto command : _pipeline._state->_commands) { for (const auto& command : _pipeline._state->_commands) {
command->run(this); command->run(this);
} }
} else { } else {
@ -134,23 +134,17 @@ void GLBackend::resetPipelineStage() {
_pipeline._invalidProgram = false; _pipeline._invalidProgram = false;
_pipeline._program = 0; _pipeline._program = 0;
_pipeline._programShader = nullptr; _pipeline._programShader = nullptr;
_pipeline._pipeline.reset(); reset(_pipeline._pipeline);
glUseProgram(0); glUseProgram(0);
} }
GLBackend::UniformStageState::BufferState::BufferState(const BufferPointer& buffer, GLintptr offset, GLsizeiptr size)
: buffer(buffer), offset(offset), size(size) {}
void GLBackend::releaseUniformBuffer(uint32_t slot) { void GLBackend::releaseUniformBuffer(uint32_t slot) {
auto& buf = _uniform._buffers[slot]; auto& bufferState = _uniform._buffers[slot];
if (buf.buffer) { if (valid(bufferState.buffer)) {
auto* object = Backend::getGPUObject<GLBuffer>(*buf.buffer); glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE
if (object) { (void)CHECK_GL_ERROR();
glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE
(void)CHECK_GL_ERROR();
}
buf = UniformStageState::BufferState();
} }
bufferState.reset();
} }
void GLBackend::resetUniformStage() { void GLBackend::resetUniformStage() {
@ -165,18 +159,20 @@ void GLBackend::bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GL
return; return;
} }
UniformStageState::BufferState bufferState{ buffer, offset, size };
auto& currentBufferState = _uniform._buffers[slot];
// check cache before thinking // check cache before thinking
if (_uniform._buffers[slot] == bufferState) { if (currentBufferState.compare(buffer, offset, size)) {
return; return;
} }
// Grab the true gl Buffer object // Grab the true gl Buffer object
auto glBO = getBufferIDUnsynced(*buffer); auto glBO = getBufferIDUnsynced(*buffer);
if (glBO) { if (glBO) {
glBindBufferRange(GL_UNIFORM_BUFFER, slot, glBO, bufferState.offset, bufferState.size); glBindBufferRange(GL_UNIFORM_BUFFER, slot, glBO, offset, size);
_uniform._buffers[slot] = bufferState; assign(currentBufferState.buffer, buffer);
currentBufferState.offset = offset;
currentBufferState.size = size;
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} else { } else {
releaseUniformBuffer(slot); releaseUniformBuffer(slot);
@ -193,7 +189,7 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
return; return;
} }
BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); const auto& uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
GLintptr rangeStart = batch._params[paramOffset + 1]._uint; GLintptr rangeStart = batch._params[paramOffset + 1]._uint;
GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint; GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint;
@ -201,16 +197,12 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
} }
void GLBackend::releaseResourceTexture(uint32_t slot) { void GLBackend::releaseResourceTexture(uint32_t slot) {
auto& tex = _resource._textures[slot]; auto& textureState = _resource._textures[slot];
if (tex) { if (valid(textureState._texture)) {
auto* object = Backend::getGPUObject<GLTexture>(*tex); glActiveTexture(GL_TEXTURE0 + slot);
if (object) { glBindTexture(textureState._target, 0); // RELEASE
GLuint target = object->_target; (void)CHECK_GL_ERROR();
glActiveTexture(GL_TEXTURE0 + slot); reset(textureState._texture);
glBindTexture(target, 0); // RELEASE
(void)CHECK_GL_ERROR();
}
tex.reset();
} }
} }
@ -232,14 +224,14 @@ void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) {
return; return;
} }
auto resourceBuffer = batch._buffers.get(batch._params[paramOffset + 0]._uint); const auto& resourceBuffer = batch._buffers.get(batch._params[paramOffset + 0]._uint);
if (!resourceBuffer) { if (!resourceBuffer) {
releaseResourceBuffer(slot); releaseResourceBuffer(slot);
return; return;
} }
// check cache before thinking // check cache before thinking
if (_resource._buffers[slot] == resourceBuffer) { if (compare(_resource._buffers[slot], resourceBuffer)) {
return; return;
} }
@ -248,7 +240,7 @@ void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) {
// If successful bind then cache it // If successful bind then cache it
if (bindResourceBuffer(slot, resourceBuffer)) { if (bindResourceBuffer(slot, resourceBuffer)) {
_resource._buffers[slot] = resourceBuffer; assign(_resource._buffers[slot], resourceBuffer);
} else { // else clear slot and cache } else { // else clear slot and cache
releaseResourceBuffer(slot); releaseResourceBuffer(slot);
return; return;
@ -293,14 +285,15 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si
} }
auto index = batch._params[paramOffset + 2]._uint; auto index = batch._params[paramOffset + 2]._uint;
auto renderBufferSlot = batch._params[paramOffset + 3]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint;
auto resourceFramebuffer = swapChain->get(index); const auto& resourceFramebuffer = swapChain->get(index);
auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); const auto& resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot);
setResourceTexture(slot, resourceTexture); setResourceTexture(slot, resourceTexture);
} }
void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture) { void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture) {
auto& textureState = _resource._textures[slot];
// check cache before thinking // check cache before thinking
if (_resource._textures[slot] == resourceTexture) { if (compare(textureState._texture, resourceTexture)) {
return; return;
} }
@ -310,15 +303,12 @@ void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& reso
// Always make sure the GLObject is in sync // Always make sure the GLObject is in sync
GLTexture* object = syncGPUObject(resourceTexture); GLTexture* object = syncGPUObject(resourceTexture);
if (object) { if (object) {
assign(textureState._texture, resourceTexture);
GLuint to = object->_texture; GLuint to = object->_texture;
GLuint target = object->_target; textureState._target = object->_target;
glActiveTexture(GL_TEXTURE0 + slot); glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(target, to); glBindTexture(textureState._target, to);
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_resource._textures[slot] = resourceTexture;
_stats._RSAmountTextureMemoryBounded += (int)object->size(); _stats._RSAmountTextureMemoryBounded += (int)object->size();
} else { } else {
@ -343,7 +333,7 @@ void GLBackend::do_setResourceTextureTable(const Batch& batch, size_t paramOffse
int GLBackend::ResourceStageState::findEmptyTextureSlot() const { int GLBackend::ResourceStageState::findEmptyTextureSlot() const {
// start from the end of the slots, try to find an empty one that can be used // start from the end of the slots, try to find an empty one that can be used
for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) { for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) {
if (!_textures[i]) { if (!valid(_textures[i]._texture)) {
return i; return i;
} }
} }

View file

@ -66,7 +66,7 @@ GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePointer) {
} }
void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) { void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) {
TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); const auto& resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
if (!resourceTexture) { if (!resourceTexture) {
return; return;
} }

View file

@ -24,7 +24,7 @@ GLPipeline* GLPipeline::sync(GLBackend& backend, const Pipeline& pipeline) {
} }
// No object allocated yet, let's see if it's worth it... // No object allocated yet, let's see if it's worth it...
ShaderPointer shader = pipeline.getProgram(); const auto& shader = pipeline.getProgram();
// If this pipeline's shader has already failed to compile, don't try again // If this pipeline's shader has already failed to compile, don't try again
if (shader->compilationHasFailed()) { if (shader->compilationHasFailed()) {
@ -37,7 +37,7 @@ GLPipeline* GLPipeline::sync(GLBackend& backend, const Pipeline& pipeline) {
return nullptr; return nullptr;
} }
StatePointer state = pipeline.getState(); const auto& state = pipeline.getState();
GLState* stateObject = GLState::sync(*state); GLState* stateObject = GLState::sync(*state);
if (stateObject == nullptr) { if (stateObject == nullptr) {
return nullptr; return nullptr;

View file

@ -161,7 +161,7 @@ protected:
void updateTransform(const Batch& batch) override; void updateTransform(const Batch& batch) override;
// Resource Stage // Resource Stage
bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) override; bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) override;
void releaseResourceBuffer(uint32_t slot) override; void releaseResourceBuffer(uint32_t slot) override;
// Output stage // Output stage

View file

@ -100,7 +100,7 @@ GLBuffer* GL41Backend::syncGPUObject(const Buffer& buffer) {
return GL41Buffer::sync<GL41Buffer>(*this, buffer); return GL41Buffer::sync<GL41Buffer>(*this, buffer);
} }
bool GL41Backend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) { bool GL41Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) {
GLuint texBuffer = GL41Backend::getResourceBufferID((*buffer)); GLuint texBuffer = GL41Backend::getResourceBufferID((*buffer));
if (texBuffer) { if (texBuffer) {
glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot); glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot);
@ -108,7 +108,7 @@ bool GL41Backend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) {
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_resource._buffers[slot] = buffer; assign(_resource._buffers[slot], buffer);
return true; return true;
} }
@ -117,10 +117,11 @@ bool GL41Backend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) {
} }
void GL41Backend::releaseResourceBuffer(uint32_t slot) { void GL41Backend::releaseResourceBuffer(uint32_t slot) {
auto& buf = _resource._buffers[slot]; auto& bufferReference = _resource._buffers[slot];
if (buf) { auto buffer = acquire(bufferReference);
if (buffer) {
glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot); glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot);
glBindTexture(GL_TEXTURE_BUFFER, 0); glBindTexture(GL_TEXTURE_BUFFER, 0);
buf.reset(); reset(bufferReference);
} }
} }

View file

@ -35,14 +35,15 @@ void GL41Backend::updateInput() {
if (_input._invalidFormat || _input._invalidBuffers.any()) { if (_input._invalidFormat || _input._invalidBuffers.any()) {
auto format = acquire(_input._format);
if (_input._invalidFormat) { if (_input._invalidFormat) {
InputStageState::ActivationCache newActivation; InputStageState::ActivationCache newActivation;
_stats._ISNumFormatChanges++; _stats._ISNumFormatChanges++;
// Check expected activation // Check expected activation
if (_input._format) { if (format) {
for (auto& it : _input._format->getAttributes()) { for (auto& it : format->getAttributes()) {
const Stream::Attribute& attrib = (it).second; const Stream::Attribute& attrib = (it).second;
uint8_t locationCount = attrib._element.getLocationCount(); uint8_t locationCount = attrib._element.getLocationCount();
for (int i = 0; i < locationCount; ++i) { for (int i = 0; i < locationCount; ++i) {
@ -69,15 +70,15 @@ void GL41Backend::updateInput() {
} }
// now we need to bind the buffers and assign the attrib pointers // now we need to bind the buffers and assign the attrib pointers
if (_input._format) { if (format) {
bool hasColorAttribute{ false }; bool hasColorAttribute{ false };
const Buffers& buffers = _input._buffers; const auto& buffers = _input._buffers;
const Offsets& offsets = _input._bufferOffsets; const auto& offsets = _input._bufferOffsets;
const Offsets& strides = _input._bufferStrides; const auto& strides = _input._bufferStrides;
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); const auto& attributes = format->getAttributes();
auto& inputChannels = _input._format->getChannels(); const auto& inputChannels = format->getChannels();
int numInvalids = (int)_input._invalidBuffers.count(); int numInvalids = (int)_input._invalidBuffers.count();
_stats._ISNumInputBufferChanges += numInvalids; _stats._ISNumInputBufferChanges += numInvalids;

View file

@ -262,7 +262,7 @@ protected:
void updateTransform(const Batch& batch) override; void updateTransform(const Batch& batch) override;
// Resource Stage // Resource Stage
bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) override; bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) override;
void releaseResourceBuffer(uint32_t slot) override; void releaseResourceBuffer(uint32_t slot) override;
// Output stage // Output stage

View file

@ -60,14 +60,14 @@ GLBuffer* GL45Backend::syncGPUObject(const Buffer& buffer) {
} }
bool GL45Backend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) { bool GL45Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) {
GLBuffer* object = syncGPUObject((*buffer)); GLBuffer* object = syncGPUObject((*buffer));
if (object) { if (object) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, object->_id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, object->_id);
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_resource._buffers[slot] = buffer; assign(_resource._buffers[slot], buffer);
return true; return true;
} }
@ -76,11 +76,10 @@ bool GL45Backend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) {
} }
void GL45Backend::releaseResourceBuffer(uint32_t slot) { void GL45Backend::releaseResourceBuffer(uint32_t slot) {
auto& buf = _resource._buffers[slot]; auto& bufferReference = _resource._buffers[slot];
if (buf) { auto buffer = acquire(bufferReference);
if (buffer) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, 0);
buf.reset(); reset(bufferReference);
} }
} }

View file

@ -28,7 +28,7 @@ void GL45Backend::resetInputStage() {
void GL45Backend::updateInput() { void GL45Backend::updateInput() {
bool isStereoNow = isStereo(); bool isStereoNow = isStereo();
// track stereo state change potentially happening wihtout changing the input format // track stereo state change potentially happening without changing the input format
// this is a rare case requesting to invalid the format // this is a rare case requesting to invalid the format
#ifdef GPU_STEREO_DRAWCALL_INSTANCED #ifdef GPU_STEREO_DRAWCALL_INSTANCED
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState); _input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
@ -39,13 +39,14 @@ void GL45Backend::updateInput() {
InputStageState::ActivationCache newActivation; InputStageState::ActivationCache newActivation;
// Assign the vertex format required // Assign the vertex format required
if (_input._format) { auto format = acquire(_input._format);
if (format) {
bool hasColorAttribute{ false }; bool hasColorAttribute{ false };
_input._attribBindingBuffers.reset(); _input._attribBindingBuffers.reset();
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); const auto& attributes = format->getAttributes();
auto& inputChannels = _input._format->getChannels(); const auto& inputChannels = format->getChannels();
for (auto& channelIt : inputChannels) { for (auto& channelIt : inputChannels) {
auto bufferChannelNum = (channelIt).first; auto bufferChannelNum = (channelIt).first;
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second; const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;

View file

@ -157,7 +157,7 @@ protected:
void updateTransform(const Batch& batch) override; void updateTransform(const Batch& batch) override;
// Resource Stage // Resource Stage
bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) override; bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) override;
void releaseResourceBuffer(uint32_t slot) override; void releaseResourceBuffer(uint32_t slot) override;
// Output stage // Output stage

View file

@ -72,14 +72,14 @@ GLBuffer* GLESBackend::syncGPUObject(const Buffer& buffer) {
return GLESBuffer::sync<GLESBuffer>(*this, buffer); return GLESBuffer::sync<GLESBuffer>(*this, buffer);
} }
bool GLESBackend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) { bool GLESBackend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) {
GLBuffer* object = syncGPUObject((*buffer)); GLBuffer* object = syncGPUObject((*buffer));
if (object) { if (object) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, object->_id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, object->_id);
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_resource._buffers[slot] = buffer; assign(_resource._buffers[slot], buffer);
return true; return true;
} }
@ -88,10 +88,10 @@ bool GLESBackend::bindResourceBuffer(uint32_t slot, BufferPointer& buffer) {
} }
void GLESBackend::releaseResourceBuffer(uint32_t slot) { void GLESBackend::releaseResourceBuffer(uint32_t slot) {
auto& buf = _resource._buffers[slot]; auto& bufferReference = _resource._buffers[slot];
if (buf) { if (valid(bufferReference)) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, 0);
buf.reset(); reset(bufferReference);
} }
} }

View file

@ -498,7 +498,7 @@ void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Fun
captureNamedDrawCallInfo(instanceName); captureNamedDrawCallInfo(instanceName);
} }
BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) { const BufferPointer& Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) {
NamedBatchData& instance = _namedData[instanceName]; NamedBatchData& instance = _namedData[instanceName];
if (instance.buffers.size() <= index) { if (instance.buffers.size() <= index) {
instance.buffers.resize(index + 1); instance.buffers.resize(index + 1);

View file

@ -119,7 +119,7 @@ public:
void multiDrawIndexedIndirect(uint32 numCommands, Primitive primitiveType); void multiDrawIndexedIndirect(uint32 numCommands, Primitive primitiveType);
void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function); void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function);
BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0); const BufferPointer& getNamedBuffer(const std::string& instanceName, uint8_t index = 0);
// Input Stage // Input Stage
// InputFormat // InputFormat

View file

@ -203,11 +203,12 @@ uint32 Framebuffer::getNumRenderBuffers() const {
return nb; return nb;
} }
TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const { const TexturePointer& Framebuffer::getRenderBuffer(uint32 slot) const {
static const TexturePointer EMPTY;
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) { if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
return _renderBuffers[slot]._texture; return _renderBuffers[slot]._texture;
} else { } else {
return TexturePointer(); return EMPTY;
} }
} }
@ -297,9 +298,10 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const For
return false; return false;
} }
TexturePointer Framebuffer::getDepthStencilBuffer() const { const TexturePointer& Framebuffer::getDepthStencilBuffer() const {
static const TexturePointer EMPTY;
if (isSwapchain()) { if (isSwapchain()) {
return TexturePointer(); return EMPTY;
} else { } else {
return _depthStencilBuffer._texture; return _depthStencilBuffer._texture;
} }

View file

@ -95,7 +95,7 @@ public:
static Framebuffer* createShadowmap(uint16 width); static Framebuffer* createShadowmap(uint16 width);
bool isSwapchain() const; bool isSwapchain() const;
SwapchainPointer getSwapchain() const { return _swapchain; } const SwapchainPointer& getSwapchain() const { return _swapchain; }
uint32 getFrameCount() const; uint32 getFrameCount() const;
@ -105,13 +105,13 @@ public:
const TextureViews& getRenderBuffers() const { return _renderBuffers; } const TextureViews& getRenderBuffers() const { return _renderBuffers; }
int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0);
TexturePointer getRenderBuffer(uint32 slot) const; const TexturePointer& getRenderBuffer(uint32 slot) const;
uint32 getRenderBufferSubresource(uint32 slot) const; uint32 getRenderBufferSubresource(uint32 slot) const;
bool setDepthBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); bool setDepthBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0);
bool setStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); bool setStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0);
bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0);
TexturePointer getDepthStencilBuffer() const; const TexturePointer& getDepthStencilBuffer() const;
uint32 getDepthStencilBufferSubresource() const; uint32 getDepthStencilBufferSubresource() const;
Format getDepthStencilBufferFormat() const; Format getDepthStencilBufferFormat() const;