blob: 35b6745eb1387f27962ee56ea45f6222ed735cde [file] [log] [blame]
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D.
#include <array>
#include <map>
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl
class FramebufferAttachment;
namespace rx
struct PackPixelsParams;
class Renderer11;
struct SourceIndexData;
struct TranslatedAttribute;
// The order of this enum governs priority of 'getLatestBufferStorage'.
enum BufferUsage
typedef size_t DataRevision;
class Buffer11 : public BufferD3D
Buffer11(const gl::BufferState &state, Renderer11 *renderer);
~Buffer11() override;
angle::Result getBuffer(const gl::Context *context,
BufferUsage usage,
ID3D11Buffer **bufferOut);
angle::Result getEmulatedIndexedBuffer(const gl::Context *context,
SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
GLint startVertex,
ID3D11Buffer **bufferOut);
angle::Result getConstantBufferRange(const gl::Context *context,
GLintptr offset,
GLsizeiptr size,
const d3d11::Buffer **bufferOut,
UINT *firstConstantOut,
UINT *numConstantsOut);
angle::Result getSRV(const gl::Context *context,
DXGI_FORMAT srvFormat,
const d3d11::ShaderResourceView **srvOut);
angle::Result getRawUAVRange(const gl::Context *context,
GLintptr offset,
GLsizeiptr size,
d3d11::UnorderedAccessView **uavOut);
bool isMapped() const { return mMappedStorage != nullptr; }
angle::Result packPixels(const gl::Context *context,
const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params);
size_t getTotalCPUBufferMemoryBytes() const;
// BufferD3D implementation
size_t getSize() const override;
bool supportsDirectBinding() const override;
angle::Result getData(const gl::Context *context, const uint8_t **outData) override;
void initializeStaticData(const gl::Context *context) override;
void invalidateStaticData(const gl::Context *context) override;
// BufferImpl implementation
angle::Result setData(const gl::Context *context,
gl::BufferBinding target,
const void *data,
size_t size,
gl::BufferUsage usage) override;
angle::Result setSubData(const gl::Context *context,
gl::BufferBinding target,
const void *data,
size_t size,
size_t offset) override;
angle::Result copySubData(const gl::Context *context,
BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size) override;
angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
angle::Result mapRange(const gl::Context *context,
size_t offset,
size_t length,
GLbitfield access,
void **mapPtr) override;
angle::Result unmap(const gl::Context *context, GLboolean *result) override;
angle::Result markTransformFeedbackUsage(const gl::Context *context) override;
class BufferStorage;
class EmulatedIndexedStorage;
class NativeStorage;
class PackStorage;
class SystemMemoryStorage;
struct ConstantBufferCacheEntry
ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {}
BufferStorage *storage;
unsigned int lruCount;
void markBufferUsage(BufferUsage usage);
angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage);
angle::Result updateBufferStorage(const gl::Context *context,
BufferStorage *storage,
size_t sourceOffset,
size_t storageSize);
angle::Result getNativeStorageForUAV(const gl::Context *context,
Buffer11::NativeStorage **storageOut);
template <typename StorageOutT>
angle::Result getBufferStorage(const gl::Context *context,
BufferUsage usage,
StorageOutT **storageOut);
template <typename StorageOutT>
angle::Result getStagingStorage(const gl::Context *context, StorageOutT **storageOut);
angle::Result getLatestBufferStorage(const gl::Context *context,
BufferStorage **storageOut) const;
angle::Result getConstantBufferRangeStorage(const gl::Context *context,
GLintptr offset,
GLsizeiptr size,
NativeStorage **storageOut);
BufferStorage *allocateStorage(BufferUsage usage);
void updateDeallocThreshold(BufferUsage usage);
// Free the storage if we decide it isn't being used very often.
angle::Result checkForDeallocation(const gl::Context *context, BufferUsage usage);
// For some cases of uniform buffer storage, we can't deallocate system memory storage.
bool canDeallocateSystemMemory() const;
// Updates data revisions and latest storage.
void onCopyStorage(BufferStorage *dest, BufferStorage *source);
void onStorageUpdate(BufferStorage *updatedStorage);
Renderer11 *mRenderer;
size_t mSize;
BufferStorage *mMappedStorage;
// Buffer storages are sorted by usage. It's important that the latest buffer storage picks
// the lowest usage in the case where two storages are tied on data revision - this ensures
// we never do anything dangerous like map a uniform buffer over a staging or system memory
// copy.
std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
BufferStorage *mLatestBufferStorage;
// These two arrays are used to track when to free unused storage.
std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds;
std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness;
// Cache of D3D11 constant buffer for specific ranges of buffer data.
// This is used to emulate UBO ranges on 11.0 devices.
// Constant buffers are indexed by there start offset.
typedef std::map<GLintptr /*offset*/, ConstantBufferCacheEntry> ConstantBufferCache;
ConstantBufferCache mConstantBufferRangeStoragesCache;
size_t mConstantBufferStorageAdditionalSize;
unsigned int mMaxConstantBufferLruCount;
} // namespace rx