3#include "GraphicsDeviceVK.h"
13Cogs::BufferPageVK::BufferPageVK(BufferContextVK & context,
size_t pageSize)
15 VkBufferCreateInfo bufferInfo = {};
16 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
17 bufferInfo.pNext =
nullptr;
18 bufferInfo.size = context.elementSize * pageSize;
19 bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
22 VkMemoryAllocateInfo allocateInfo = {};
23 allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
24 allocateInfo.pNext =
nullptr;
25 allocateInfo.allocationSize = 0;
26 allocateInfo.memoryTypeIndex = 0;
28 auto result = vkCreateBuffer(context.device, &bufferInfo,
nullptr, &buffer);
30 if (VK_FAILED(result)) {
31 VK_LOG_ERROR(result,
"Could not create buffer.");
35 VkMemoryRequirements memoryRequirements;
36 vkGetBufferMemoryRequirements(context.device, buffer, &memoryRequirements);
39 allocateInfo.allocationSize = memoryRequirements.size;
40 auto pass = context.graphicsDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &allocateInfo.memoryTypeIndex);
43 result = vkAllocateMemory(context.device, &allocateInfo,
nullptr, &deviceMemory);
46 result = vkBindBufferMemory(context.device, buffer, deviceMemory, 0);
49 storage.resize(
sizeof(PoolBufferVK) * pageSize);
51 auto head =
reinterpret_cast<PoolBufferVK *
>(storage.data());
53 vkMapMemory(context.device, deviceMemory, 0, memoryRequirements.size, 0, ((
void **)&mappedRegion));
56 for (
size_t i = 0; i < pageSize; ++i) {
57 PoolBufferVK * block = head + i;
59 auto offset = i * context.elementSize;
60 block->mappedRegion = mappedRegion + offset;
61 block->pool = context.pool;
62 block->offset = offset;
63 block->size = context.elementSize;
64 block->buffer = buffer;
66 block->next = block + 1;
69 (head + pageSize - 1)->next =
nullptr;
72#define VERTEX_BUFFER_BIND_ID 0
74void Cogs::BuffersVK::initialize(GraphicsDeviceVK * graphicsDevice)
76 pool256.initialize(graphicsDevice, graphicsDevice->device, 1, 256, 1024);
77 pool1024.initialize(graphicsDevice, graphicsDevice->device, 1, 1024, 256);
82 const uint32_t vertexSize = getSize(vertexFormat);
83 const size_t size = vertexSize * count;
87 auto & buffer = buffers[handle];
89 auto hashCode = getHash(vertexFormat);
92 auto vIt = vertexFormats.find(hashCode);
94 if (vIt != vertexFormats.end()) {
95 buffer.vertexFormat = &vIt->second;
97 buffer.vertexFormat = &(vertexFormats[hashCode] = vertexFormat);
118 auto & buffer = buffers[handle];
121 buffer.indexSize = indexSize;
132 const char * Semantics[] = {
142 const uint32_t NoRegister = ~0ul;
147 if (!HandleIsValid(effectHandle)) {
148 LOG_ERROR(logger,
"Cannot create input layout for invalid effect.");
153 auto & inputLayout = inputLayouts[handle];
155 auto findSemantic = [&](
const char * semantic,
size_t index = 0) -> uint32_t
157 auto & effect = graphicsDevice->effects.effects[effectHandle];
159 for (
auto & ia : effect.vertexShader.reflection.inputAttributes) {
160 if (ia.semantic == semantic && ia.index == index)
return ia.reg;
166 size_t attribCount = 0;
167 for (
size_t i = 0; i < count; ++i) {
168 const VertexFormat *format = getVertexFormat(vertexFormats[i]);
169 for (
size_t j = 0; j < format->
elements.size(); ++j) {
170 auto & element = format->
elements[j];
172 if (findSemantic(Semantics[(
size_t)element.semantic], element.semanticIndex) == NoRegister)
continue;
182 inputLayout.vertexInputBinding.resize(count);
183 inputLayout.vertexInputAttribs.resize(attribCount);
185 inputLayout.vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
186 inputLayout.vertexInputState.pNext =
nullptr;
187 inputLayout.vertexInputState.vertexBindingDescriptionCount =
static_cast<uint32_t
>(count);
188 inputLayout.vertexInputState.pVertexBindingDescriptions = inputLayout.vertexInputBinding.data();
189 inputLayout.vertexInputState.vertexAttributeDescriptionCount =
static_cast<uint32_t
>(attribCount);
190 inputLayout.vertexInputState.pVertexAttributeDescriptions = inputLayout.vertexInputAttribs.data();
192 for (uint32_t i = 0; i < count; ++i) {
193 const VertexFormat *format = getVertexFormat(vertexFormats[i]);
194 inputLayout.vertexInputBinding[i].binding = i;
195 inputLayout.vertexInputBinding[i].stride = getSize(*format);
196 inputLayout.vertexInputBinding[i].inputRate = format->
elements.front().inputType ==
InputType::VertexData ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
199 uint32_t location = 0;
201 for (uint32_t i = 0; i < count; ++i) {
202 const VertexFormat &format = *getVertexFormat(vertexFormats[i]);
203 for (
auto & element : format.
elements) {
204 auto reg = findSemantic(Semantics[(
size_t)element.semantic], element.semanticIndex);
206 if (reg == NoRegister)
continue;
209 for (uint32_t j = 0; j < 4; ++j) {
210 inputLayout.vertexInputAttribs[location].binding = i;
211 inputLayout.vertexInputAttribs[location].location = reg + j;
212 inputLayout.vertexInputAttribs[location].format = Vulkan::TextureFormats[(size_t)element.format];
213 inputLayout.vertexInputAttribs[location].offset = element.offset + 16 * j;
218 inputLayout.vertexInputAttribs[location].binding = i;
219 inputLayout.vertexInputAttribs[location].location = reg;
220 inputLayout.vertexInputAttribs[location].format = Vulkan::TextureFormats[(size_t)element.format];
221 inputLayout.vertexInputAttribs[location].offset = element.offset;
233 inputLayouts.removeResource(inputLayoutHandle);
241 VkBufferUsageFlags usageFlags = 0;
244 usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
246 usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
248 usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
252 usageFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
254 usageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
258 buffer.poolBuffer = pool256.allocate();
259 buffer.bufferInfo.buffer = buffer.poolBuffer->buffer;
260 buffer.bufferInfo.offset = buffer.poolBuffer->offset;
261 buffer.bufferInfo.range = buffer.poolBuffer->size;
263 return buffers.addResource(buffer);
265 buffer.poolBuffer = pool1024.allocate();
266 buffer.bufferInfo.buffer = buffer.poolBuffer->buffer;
267 buffer.bufferInfo.offset = buffer.poolBuffer->offset;
268 buffer.bufferInfo.range = buffer.poolBuffer->size;
270 return buffers.addResource(buffer);
273 VkBufferCreateInfo bufferInfo = {};
274 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
275 bufferInfo.pNext =
nullptr;
276 bufferInfo.size = size;
277 bufferInfo.usage = usageFlags;
278 bufferInfo.flags = 0;
280 VkMemoryAllocateInfo allocateInfo = {};
281 allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
282 allocateInfo.pNext =
nullptr;
283 allocateInfo.allocationSize = 0;
284 allocateInfo.memoryTypeIndex = 0;
286 auto result = vkCreateBuffer(graphicsDevice->device, &bufferInfo,
nullptr, &buffer.buffer);
288 if (VK_FAILED(result)) {
289 VK_LOG_ERROR(result,
"Could not create buffer.");
293 VkMemoryRequirements memoryRequirements;
294 vkGetBufferMemoryRequirements(graphicsDevice->device, buffer.buffer, &memoryRequirements);
297 buffer.size = memoryRequirements.size;
299 allocateInfo.allocationSize = memoryRequirements.size;
300 auto pass = graphicsDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &allocateInfo.memoryTypeIndex);
303 result = vkAllocateMemory(graphicsDevice->device, &allocateInfo,
nullptr, &buffer.deviceMemory);
308 result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, allocateInfo.allocationSize, 0, &mappedMemory);
312 std::memcpy(mappedMemory, data, size);
314 vkUnmapMemory(graphicsDevice->device, buffer.deviceMemory);
317 buffer.bufferInfo.buffer = buffer.buffer;
318 buffer.bufferInfo.offset = 0;
319 buffer.bufferInfo.range = size;
321 result = vkBindBufferMemory(graphicsDevice->device, buffer.buffer, buffer.deviceMemory, 0);
323 return buffers.addResource(buffer);
338 return (
void*)(buffers[bufferHandle].buffer);
void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle) override
Release the vertex buffer with the given handle.
BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0) override
Loads a new buffer using the given data to populate the buffer.
void releaseBuffer(BufferHandle bufferHandle) override
Releases the buffer with the given bufferHandle.
VertexBufferHandle loadVertexBuffer(const void *vertexData, const size_t count, const VertexFormat &vertexFormat) override
Loads a new vertex buffer and populates it with the given data.
void releaseInputLayout(InputLayoutHandle inputLayoutHandle) override
Releases the input layout with the given inputLayoutHandle.
IndexBufferHandle loadIndexBuffer(const void *indexData, const size_t count, const size_t indexSize) override
Loads a new index buffer and populates it with the given indexData.
void releaseIndexBuffer(IndexBufferHandle indexBufferHandle) override
Releases the index buffer with the given handle.
void retrieveSubBuffer(void *data, BufferHandle source, const size_t offset, const size_t size) override
Retrieves the contents of a buffer.
void * getNativeHandle(BufferHandle bufferHandle) override
Get the device-specific handle (D3D buffer pointer, OpenGL buffer ID etc) associated with the given b...
void releaseResources() override
Releases all allocated buffer resources.
InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle) override
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
Log implementation class.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ VertexData
Per vertex data.
@ InstanceMatrix
Instance matrix semantic.
@ InstanceVector
Instance vector semantic.
@ Read
The buffer can be mapped and read from by the CPU after creation.
@ Write
The buffer can be mapped and written to by the CPU after creation.
EBindFlags
Bind flags enumeration.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
static const Handle_t NoHandle
Represents a handle to nothing.
static const Handle_t InvalidHandle
Represents an invalid handle.
@ Dynamic
Buffer will be loaded and modified with some frequency.