mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-13 05:37:18 +02:00
188 lines
6.5 KiB
C++
188 lines
6.5 KiB
C++
//
|
|
// Created by Bradley Austin Davis on 2016/05/15
|
|
// Copyright 2013-2016 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_gl_GLTexture_h
|
|
#define hifi_gpu_gl_GLTexture_h
|
|
|
|
#include "GLShared.h"
|
|
#include "GLBackend.h"
|
|
#include "GLTexelFormat.h"
|
|
#include <thread>
|
|
|
|
#define THREADED_TEXTURE_BUFFERING 1
|
|
|
|
namespace gpu { namespace gl {
|
|
|
|
struct GLFilterMode {
|
|
GLint minFilter;
|
|
GLint magFilter;
|
|
};
|
|
|
|
class GLVariableAllocationSupport {
|
|
friend class GLBackend;
|
|
|
|
public:
|
|
GLVariableAllocationSupport();
|
|
virtual ~GLVariableAllocationSupport();
|
|
|
|
enum class MemoryPressureState {
|
|
Idle,
|
|
Transfer,
|
|
Oversubscribed,
|
|
Undersubscribed,
|
|
};
|
|
|
|
using QueuePair = std::pair<TextureWeakPointer, float>;
|
|
struct QueuePairLess {
|
|
bool operator()(const QueuePair& a, const QueuePair& b) {
|
|
return a.second < b.second;
|
|
}
|
|
};
|
|
using WorkQueue = std::priority_queue<QueuePair, std::vector<QueuePair>, QueuePairLess>;
|
|
|
|
class TransferJob {
|
|
using VoidLambda = std::function<void()>;
|
|
using VoidLambdaQueue = std::queue<VoidLambda>;
|
|
using ThreadPointer = std::shared_ptr<std::thread>;
|
|
const GLTexture& _parent;
|
|
// Holds the contents to transfer to the GPU in CPU memory
|
|
std::vector<uint8_t> _buffer;
|
|
// Indicates if a transfer from backing storage to interal storage has started
|
|
bool _bufferingStarted { false };
|
|
bool _bufferingCompleted { false };
|
|
VoidLambda _transferLambda;
|
|
VoidLambda _bufferingLambda;
|
|
|
|
#if THREADED_TEXTURE_BUFFERING
|
|
static Mutex _mutex;
|
|
static VoidLambdaQueue _bufferLambdaQueue;
|
|
static ThreadPointer _bufferThread;
|
|
static std::atomic<bool> _shutdownBufferingThread;
|
|
static void bufferLoop();
|
|
#endif
|
|
|
|
public:
|
|
TransferJob(const TransferJob& other) = delete;
|
|
TransferJob(const GLTexture& parent, std::function<void()> transferLambda);
|
|
TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t targetMip, uint8_t face, uint32_t lines = 0, uint32_t lineOffset = 0);
|
|
~TransferJob();
|
|
bool tryTransfer();
|
|
|
|
#if THREADED_TEXTURE_BUFFERING
|
|
static void startTransferLoop();
|
|
static void stopTransferLoop();
|
|
#endif
|
|
|
|
private:
|
|
size_t _transferSize { 0 };
|
|
#if THREADED_TEXTURE_BUFFERING
|
|
void startBuffering();
|
|
#endif
|
|
void transfer();
|
|
};
|
|
|
|
using TransferQueue = std::queue<std::unique_ptr<TransferJob>>;
|
|
static MemoryPressureState _memoryPressureState;
|
|
|
|
public:
|
|
static void addMemoryManagedTexture(const TexturePointer& texturePointer);
|
|
|
|
protected:
|
|
static size_t _frameTexturesCreated;
|
|
static std::atomic<bool> _memoryPressureStateStale;
|
|
static std::list<TextureWeakPointer> _memoryManagedTextures;
|
|
static WorkQueue _transferQueue;
|
|
static WorkQueue _promoteQueue;
|
|
static WorkQueue _demoteQueue;
|
|
static TexturePointer _currentTransferTexture;
|
|
static const uvec3 INITIAL_MIP_TRANSFER_DIMENSIONS;
|
|
static const uvec3 MAX_TRANSFER_DIMENSIONS;
|
|
static const size_t MAX_TRANSFER_SIZE;
|
|
|
|
|
|
static void updateMemoryPressure();
|
|
static void processWorkQueues();
|
|
static void addToWorkQueue(const TexturePointer& texture);
|
|
static WorkQueue& getActiveWorkQueue();
|
|
|
|
static void manageMemory();
|
|
|
|
//bool canPromoteNoAllocate() const { return _allocatedMip < _populatedMip; }
|
|
bool canPromote() const { return _allocatedMip > 0; }
|
|
bool canDemote() const { return _allocatedMip < _maxAllocatedMip; }
|
|
bool hasPendingTransfers() const { return _populatedMip > _allocatedMip; }
|
|
void executeNextTransfer(const TexturePointer& currentTexture);
|
|
virtual void populateTransferQueue() = 0;
|
|
virtual void promote() = 0;
|
|
virtual void demote() = 0;
|
|
|
|
// The allocated mip level, relative to the number of mips in the gpu::Texture object
|
|
// The relationship between a given glMip to the original gpu::Texture mip is always
|
|
// glMip + _allocatedMip
|
|
uint16 _allocatedMip { 0 };
|
|
// The populated mip level, relative to the number of mips in the gpu::Texture object
|
|
// This must always be >= the allocated mip
|
|
uint16 _populatedMip { 0 };
|
|
// The highest (lowest resolution) mip that we will support, relative to the number
|
|
// of mips in the gpu::Texture object
|
|
uint16 _maxAllocatedMip { 0 };
|
|
// Contains a series of lambdas that when executed will transfer data to the GPU, modify
|
|
// the _populatedMip and update the sampler in order to fully populate the allocated texture
|
|
// until _populatedMip == _allocatedMip
|
|
TransferQueue _pendingTransfers;
|
|
};
|
|
|
|
class GLTexture : public GLObject<Texture> {
|
|
using Parent = GLObject<Texture>;
|
|
friend class GLBackend;
|
|
friend class GLVariableAllocationSupport;
|
|
public:
|
|
static const uint16_t INVALID_MIP { (uint16_t)-1 };
|
|
static const uint8_t INVALID_FACE { (uint8_t)-1 };
|
|
|
|
~GLTexture();
|
|
|
|
const GLuint& _texture { _id };
|
|
const std::string _source;
|
|
const GLenum _target;
|
|
|
|
static const std::vector<GLenum>& getFaceTargets(GLenum textureType);
|
|
static uint8_t getFaceCount(GLenum textureType);
|
|
static GLenum getGLTextureType(const Texture& texture);
|
|
|
|
static const uint8_t TEXTURE_2D_NUM_FACES = 1;
|
|
static const uint8_t TEXTURE_CUBE_NUM_FACES = 6;
|
|
static const GLenum CUBE_FACE_LAYOUT[TEXTURE_CUBE_NUM_FACES];
|
|
static const GLFilterMode FILTER_MODES[Sampler::NUM_FILTERS];
|
|
static const GLenum WRAP_MODES[Sampler::NUM_WRAP_MODES];
|
|
|
|
protected:
|
|
virtual Size size() const = 0;
|
|
virtual void generateMips() const = 0;
|
|
virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const = 0;
|
|
virtual void copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, uint8_t face) const final;
|
|
|
|
GLTexture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLuint id);
|
|
};
|
|
|
|
class GLExternalTexture : public GLTexture {
|
|
using Parent = GLTexture;
|
|
friend class GLBackend;
|
|
public:
|
|
~GLExternalTexture();
|
|
protected:
|
|
GLExternalTexture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLuint id);
|
|
void generateMips() const override {}
|
|
void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override {}
|
|
|
|
Size size() const override { return 0; }
|
|
};
|
|
|
|
|
|
} }
|
|
|
|
#endif
|