Skip to content

Commit

Permalink
Dynamically allocate shader constant buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
elnormous committed Oct 23, 2018
1 parent 7e70863 commit d053005
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
3 changes: 2 additions & 1 deletion ouzel/graphics/metal/RenderDeviceMetal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ namespace ouzel

struct ShaderConstantBuffer
{
MTLBufferPtr buffer = nil;
std::vector<MTLBufferPtr> buffers;
uint32_t index = 0;
uint32_t offset = 0;
};

Expand Down
50 changes: 41 additions & 9 deletions ouzel/graphics/metal/RenderDeviceMetal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
resources.clear();

for (const ShaderConstantBuffer& shaderConstantBuffer : shaderConstantBuffers)
[shaderConstantBuffer.buffer release];
for (MTLBufferPtr buffer : shaderConstantBuffer.buffers)
[buffer release];

for (id<MTLDepthStencilState> depthStencilState : depthStencilStates)
if (depthStencilState) [depthStencilState release];
Expand Down Expand Up @@ -143,11 +144,13 @@

for (ShaderConstantBuffer& shaderConstantBuffer : shaderConstantBuffers)
{
shaderConstantBuffer.buffer = [device newBufferWithLength:BUFFER_SIZE
options:MTLResourceCPUCacheModeWriteCombined];
MTLBufferPtr buffer = [device newBufferWithLength:BUFFER_SIZE
options:MTLResourceCPUCacheModeWriteCombined];

if (!shaderConstantBuffer.buffer)
if (!buffer)
throw SystemError("Failed to create Metal buffer");

shaderConstantBuffer.buffers.push_back(buffer);
}
}

Expand Down Expand Up @@ -287,6 +290,8 @@

if (++shaderConstantBufferIndex >= BUFFER_COUNT) shaderConstantBufferIndex = 0;
ShaderConstantBuffer& shaderConstantBuffer = shaderConstantBuffers[shaderConstantBufferIndex];
shaderConstantBuffer.index = 0;
shaderConstantBuffer.offset = 0;
ShaderResourceMetal* currentShader = nullptr;

std::unique_ptr<Command> command;
Expand Down Expand Up @@ -753,19 +758,33 @@
shaderData.insert(shaderData.end(), fragmentShaderConstant.begin(), fragmentShaderConstant.end());
}

//ShaderConstantBuffer& shaderConstantBuffer = shaderConstantBuffers[shaderConstantBufferIndex];
MTLBufferPtr currentBuffer;

shaderConstantBuffer.offset = ((shaderConstantBuffer.offset + currentShader->getFragmentShaderAlignment() - 1) /
currentShader->getFragmentShaderAlignment()) * currentShader->getFragmentShaderAlignment(); // round up to nearest aligned pointer


if (shaderConstantBuffer.offset + getVectorSize(shaderData) > BUFFER_SIZE)
{
currentBuffer = [device newBufferWithLength:BUFFER_SIZE
options:MTLResourceCPUCacheModeWriteCombined];

if (!currentBuffer)
throw SystemError("Failed to create Metal buffer");

shaderConstantBuffer.buffers.push_back(currentBuffer);

++shaderConstantBuffer.index;
shaderConstantBuffer.offset = 0;
}
else
currentBuffer = shaderConstantBuffer.buffers[shaderConstantBuffer.index];

std::copy(reinterpret_cast<const char*>(shaderData.data()),
reinterpret_cast<const char*>(shaderData.data()) + static_cast<uint32_t>(sizeof(float) * shaderData.size()),
static_cast<char*>([shaderConstantBuffer.buffer contents]) + shaderConstantBuffer.offset);
static_cast<char*>([currentBuffer contents]) + shaderConstantBuffer.offset);

[currentRenderCommandEncoder setFragmentBuffer:shaderConstantBuffer.buffer
[currentRenderCommandEncoder setFragmentBuffer:currentBuffer
offset:shaderConstantBuffer.offset
atIndex:1];

Expand Down Expand Up @@ -794,13 +813,26 @@
currentShader->getVertexShaderAlignment()) * currentShader->getVertexShaderAlignment(); // round up to nearest aligned pointer

if (shaderConstantBuffer.offset + getVectorSize(shaderData) > BUFFER_SIZE)
{
currentBuffer = [device newBufferWithLength:BUFFER_SIZE
options:MTLResourceCPUCacheModeWriteCombined];

if (!currentBuffer)
throw SystemError("Failed to create Metal buffer");

shaderConstantBuffer.buffers.push_back(currentBuffer);

++shaderConstantBuffer.index;
shaderConstantBuffer.offset = 0;
}
else
currentBuffer = shaderConstantBuffer.buffers[shaderConstantBuffer.index];

std::copy(reinterpret_cast<const char*>(shaderData.data()),
reinterpret_cast<const char*>(shaderData.data()) + static_cast<uint32_t>(sizeof(float) * shaderData.size()),
static_cast<char*>([shaderConstantBuffer.buffer contents]) + shaderConstantBuffer.offset);
static_cast<char*>([currentBuffer contents]) + shaderConstantBuffer.offset);

[currentRenderCommandEncoder setVertexBuffer:shaderConstantBuffer.buffer
[currentRenderCommandEncoder setVertexBuffer:currentBuffer
offset:shaderConstantBuffer.offset
atIndex:1];

Expand Down

0 comments on commit d053005

Please sign in to comment.