Reduce duplicate GPU buffer uploads (#3577)
Co-authored-by: “Malcolm <“mtoon@atlasprogramming.com”> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -41,6 +41,9 @@ public:
|
||||
/// Set the sampler for a texture binding
|
||||
void setFragmentSamplerState(const MTLSamplerStatePtr&, int32_t location);
|
||||
|
||||
/// Set the render pipeline state
|
||||
void setRenderPipelineState(const MTLRenderPipelineStatePtr&);
|
||||
|
||||
void endEncoding();
|
||||
|
||||
/// Resets the states and bindings of the render pass to deal
|
||||
@@ -69,6 +72,8 @@ private:
|
||||
mtl::CommandEncoder& commandEncoder;
|
||||
MTLRenderCommandEncoderPtr encoder;
|
||||
MTLDepthStencilStatePtr currentDepthStencilState;
|
||||
MTLRenderPipelineStatePtr currentPipelineState;
|
||||
|
||||
int32_t currentStencilReferenceValue = 0;
|
||||
std::vector<gfx::DebugGroup<gfx::RenderPass>> debugGroups;
|
||||
|
||||
|
||||
@@ -103,15 +103,22 @@ void BufferResource::update(const void* newData, std::size_t updateSize, std::si
|
||||
// Until we can be sure that the buffer is not still in use to render the
|
||||
// previous frame, replace it with a new buffer instead of updating it.
|
||||
|
||||
auto& device = context.getBackend().getDevice();
|
||||
const uint8_t* newBufferSource = nullptr;
|
||||
std::unique_ptr<uint8_t[]> tempBuffer;
|
||||
const bool updateIsEntireBuffer = (offset == 0 && updateSize == size);
|
||||
|
||||
// If the entire buffer is being updated, make sure it's changed
|
||||
if (updateIsEntireBuffer) {
|
||||
if (memcmp(buffer->contents(), newData, updateSize) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto& device = context.getBackend().getDevice();
|
||||
// `[MTLBuffer contents]` may involve memory mapping and/or synchronization. If the entire
|
||||
// buffer is being replaced, avoid accessing the old one by creating the new buffer directly
|
||||
// from the given data. If it's just being updated, apply the update to a local buffer to
|
||||
// avoid needing to access the new buffer.
|
||||
const bool updateIsEntireBuffer = (offset == 0 && updateSize == size);
|
||||
if (updateIsEntireBuffer) {
|
||||
newBufferSource = static_cast<const uint8_t*>(newData);
|
||||
} else {
|
||||
|
||||
@@ -223,7 +223,7 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
mbgl::util::hash(getColorMode().hash(), impl->vertexDescHash));
|
||||
}
|
||||
if (impl->pipelineState) {
|
||||
encoder->setRenderPipelineState(impl->pipelineState.get());
|
||||
renderPass.setRenderPipelineState(impl->pipelineState);
|
||||
} else {
|
||||
assert(!"Failed to create render pipeline state");
|
||||
return;
|
||||
|
||||
@@ -66,6 +66,7 @@ void RenderPass::endEncoding() {
|
||||
}
|
||||
|
||||
void RenderPass::resetState() {
|
||||
currentPipelineState.reset();
|
||||
currentDepthStencilState.reset();
|
||||
currentStencilReferenceValue = 0;
|
||||
for (int i = 0; i < maxBinds; ++i) {
|
||||
@@ -193,6 +194,14 @@ void RenderPass::setFragmentSamplerState(const MTLSamplerStatePtr& state, int32_
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the render pipeline state
|
||||
void RenderPass::setRenderPipelineState(const MTLRenderPipelineStatePtr& pipelineState) {
|
||||
if (pipelineState != currentPipelineState) {
|
||||
currentPipelineState = pipelineState;
|
||||
encoder->setRenderPipelineState(currentPipelineState.get());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::setCullMode(const MTL::CullMode mode) {
|
||||
if (mode != currentCullMode) {
|
||||
encoder->setCullMode(mode);
|
||||
|
||||
Reference in New Issue
Block a user