mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 10:49:14 +00:00
Move src/backend to src/dawn_native
This commit is contained in:
committed by
Corentin Wallez
parent
ff9626c751
commit
d37523fbde
150
src/dawn_native/CommandAllocator.h
Normal file
150
src/dawn_native/CommandAllocator.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2017 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BACKEND_COMMAND_ALLOCATOR_H_
|
||||
#define BACKEND_COMMAND_ALLOCATOR_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace backend {
|
||||
|
||||
// Allocation for command buffers should be fast. To avoid doing an allocation per command
|
||||
// or to avoid copying commands when reallocing, we use a linear allocator in a growing set
|
||||
// of large memory blocks. We also use this to have the format to be (u32 commandId, command),
|
||||
// so that iteration over the commands is easy.
|
||||
|
||||
// Usage of the allocator and iterator:
|
||||
// CommandAllocator allocator;
|
||||
// DrawCommand* cmd = allocator.Allocate<DrawCommand>(CommandType::Draw);
|
||||
// // Fill command
|
||||
// // Repeat allocation and filling commands
|
||||
//
|
||||
// CommandIterator commands(allocator);
|
||||
// CommandType type;
|
||||
// void* command;
|
||||
// while(commands.NextCommandId(&e)) {
|
||||
// switch(e) {
|
||||
// case CommandType::Draw:
|
||||
// DrawCommand* draw = commands.NextCommand<DrawCommand>();
|
||||
// // Do the draw
|
||||
// break;
|
||||
// // other cases
|
||||
// }
|
||||
// }
|
||||
|
||||
// Note that you need to extract the commands from the CommandAllocator before destroying it
|
||||
// and must tell the CommandIterator when the allocated commands have been processed for
|
||||
// deletion.
|
||||
|
||||
// These are the lists of blocks, should not be used directly, only through CommandAllocator
|
||||
// and CommandIterator
|
||||
struct BlockDef {
|
||||
size_t size;
|
||||
uint8_t* block;
|
||||
};
|
||||
using CommandBlocks = std::vector<BlockDef>;
|
||||
|
||||
class CommandAllocator;
|
||||
|
||||
// TODO(cwallez@chromium.org): prevent copy for both iterator and allocator
|
||||
class CommandIterator {
|
||||
public:
|
||||
CommandIterator();
|
||||
~CommandIterator();
|
||||
|
||||
CommandIterator(CommandIterator&& other);
|
||||
CommandIterator& operator=(CommandIterator&& other);
|
||||
|
||||
CommandIterator(CommandAllocator&& allocator);
|
||||
CommandIterator& operator=(CommandAllocator&& allocator);
|
||||
|
||||
template <typename E>
|
||||
bool NextCommandId(E* commandId) {
|
||||
return NextCommandId(reinterpret_cast<uint32_t*>(commandId));
|
||||
}
|
||||
template <typename T>
|
||||
T* NextCommand() {
|
||||
return reinterpret_cast<T*>(NextCommand(sizeof(T), alignof(T)));
|
||||
}
|
||||
template <typename T>
|
||||
T* NextData(size_t count) {
|
||||
return reinterpret_cast<T*>(NextData(sizeof(T) * count, alignof(T)));
|
||||
}
|
||||
|
||||
// Needs to be called if iteration was stopped early.
|
||||
void Reset();
|
||||
|
||||
void DataWasDestroyed();
|
||||
|
||||
private:
|
||||
bool IsEmpty() const;
|
||||
|
||||
bool NextCommandId(uint32_t* commandId);
|
||||
void* NextCommand(size_t commandSize, size_t commandAlignment);
|
||||
void* NextData(size_t dataSize, size_t dataAlignment);
|
||||
|
||||
CommandBlocks mBlocks;
|
||||
uint8_t* mCurrentPtr = nullptr;
|
||||
size_t mCurrentBlock = 0;
|
||||
// Used to avoid a special case for empty iterators.
|
||||
uint32_t mEndOfBlock;
|
||||
bool mDataWasDestroyed = false;
|
||||
};
|
||||
|
||||
class CommandAllocator {
|
||||
public:
|
||||
CommandAllocator();
|
||||
~CommandAllocator();
|
||||
|
||||
template <typename T, typename E>
|
||||
T* Allocate(E commandId) {
|
||||
static_assert(sizeof(E) == sizeof(uint32_t), "");
|
||||
static_assert(alignof(E) == alignof(uint32_t), "");
|
||||
return reinterpret_cast<T*>(
|
||||
Allocate(static_cast<uint32_t>(commandId), sizeof(T), alignof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* AllocateData(size_t count) {
|
||||
return reinterpret_cast<T*>(AllocateData(sizeof(T) * count, alignof(T)));
|
||||
}
|
||||
|
||||
private:
|
||||
friend CommandIterator;
|
||||
CommandBlocks&& AcquireBlocks();
|
||||
|
||||
uint8_t* Allocate(uint32_t commandId, size_t commandSize, size_t commandAlignment);
|
||||
uint8_t* AllocateData(size_t dataSize, size_t dataAlignment);
|
||||
bool GetNewBlock(size_t minimumSize);
|
||||
|
||||
CommandBlocks mBlocks;
|
||||
size_t mLastAllocationSize = 2048;
|
||||
|
||||
// Pointers to the current range of allocation in the block. Guaranteed to allow for at
|
||||
// least one uint32_t is not nullptr, so that the special EndOfBlock command id can always
|
||||
// be written. Nullptr iff the blocks were moved out.
|
||||
uint8_t* mCurrentPtr = nullptr;
|
||||
uint8_t* mEndPtr = nullptr;
|
||||
|
||||
// Data used for the block range at initialization so that the first call to Allocate sees
|
||||
// there is not enough space and calls GetNewBlock. This avoids having to special case the
|
||||
// initialization in Allocate.
|
||||
uint32_t mDummyEnum[1] = {0};
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
|
||||
#endif // BACKEND_COMMAND_ALLOCATOR_H_
|
||||
Reference in New Issue
Block a user