Refactor bindings to allow for eliminating duplicates... (#1831)

Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Tim Sylvester
2023-11-06 10:12:34 -08:00
committed by GitHub
parent 1670b2c3ee
commit ef69472f56
29 changed files with 441 additions and 244 deletions

View File

@@ -43,16 +43,6 @@ Drawable::Drawable(std::string name_)
Drawable::~Drawable() {}
namespace {
// Downcast a generic vertex buffer resource and extract the Metal buffer
MTL::Buffer* getMetalBuffer(const gfx::VertexBufferResource* resource_) {
if (const auto* resource = static_cast<const VertexBufferResource*>(resource_)) {
if (const auto& bufferResource = resource->get()) {
return bufferResource.getMetalBuffer().get();
}
}
return nullptr;
}
#if !defined(NDEBUG)
std::size_t getBufferSize(const gfx::VertexBufferResource* resource_) {
if (const auto* resource = static_cast<const VertexBufferResource*>(resource_)) {
@@ -64,7 +54,7 @@ std::size_t getBufferSize(const gfx::VertexBufferResource* resource_) {
}
#endif // !defined(NDEBUG)
MTL::PrimitiveType getPrimitiveType(const gfx::DrawModeType type) {
MTL::PrimitiveType getPrimitiveType(const gfx::DrawModeType type) noexcept {
switch (type) {
default:
assert(false);
@@ -88,7 +78,7 @@ std::string debugLabel(const gfx::Drawable& drawable) {
}
#endif // !defined(NDEBUG)
MTL::Buffer* getMetalBuffer(const gfx::IndexVectorBasePtr& indexes) {
MTL::Buffer* getMetalBuffer(const gfx::IndexVectorBasePtr& indexes) noexcept {
if (const auto* buf0 = indexes->getBuffer()) {
if (const auto* buf1 = static_cast<const IndexBuffer*>(buf0)->buffer.get()) {
const auto& buf2 = buf1->getResource<IndexBufferResource>().get();
@@ -98,7 +88,7 @@ MTL::Buffer* getMetalBuffer(const gfx::IndexVectorBasePtr& indexes) {
return nullptr;
}
MTL::CullMode mapCullMode(const gfx::CullFaceSideType mode) {
MTL::CullMode mapCullMode(const gfx::CullFaceSideType mode) noexcept {
switch (mode) {
case gfx::CullFaceSideType::Front:
return MTL::CullModeFront;
@@ -110,7 +100,7 @@ MTL::CullMode mapCullMode(const gfx::CullFaceSideType mode) {
}
}
MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) {
MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) noexcept {
switch (mode) {
case gfx::CullFaceWindingType::Clockwise:
return MTL::Winding::WindingClockwise;
@@ -158,7 +148,7 @@ void Drawable::draw(PaintParameters& parameters) const {
}
auto& context = static_cast<Context&>(parameters.context);
const auto& renderPass = static_cast<RenderPass&>(*parameters.renderPass);
auto& renderPass = static_cast<RenderPass&>(*parameters.renderPass);
const auto& encoder = renderPass.getMetalEncoder();
if (!encoder) {
assert(false);
@@ -284,16 +274,6 @@ void Drawable::draw(PaintParameters& parameters) const {
assert(mlSegment.indexOffset + mlSegment.indexLength <= indexBufferLength);
assert(static_cast<std::size_t>(maxIndex) < mlSegment.vertexLength);
for (const auto& binding : impl->attributeBindings) {
if (binding) {
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
assert((maxIndex + mlSegment.vertexOffset) * binding->vertexStride <= buffer->length());
} else if (impl->noBindingBuffer) {
assert(binding->vertexStride <= impl->noBindingBuffer->length());
}
}
}
#endif
encoder->drawIndexedPrimitives(primitiveType,
@@ -364,103 +344,74 @@ void Drawable::setVertexAttrNameId(const StringIdentity value) {
impl->idVertexAttrName = value;
}
void Drawable::bindAttributes(const RenderPass& renderPass) const {
void Drawable::bindAttributes(RenderPass& renderPass) const noexcept {
const auto& encoder = renderPass.getMetalEncoder();
NS::UInteger attributeIndex = 0;
for (const auto& binding : impl->attributeBindings) {
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
const auto* buffer = static_cast<const mtl::VertexBufferResource*>(binding ? binding->vertexBufferResource
: nullptr);
if (buffer && buffer->get()) {
assert(binding->vertexStride * impl->vertexCount <= getBufferSize(binding->vertexBufferResource));
encoder->setVertexBuffer(buffer, /*offset=*/0, attributeIndex);
renderPass.bindVertex(buffer->get(), /*offset=*/0, attributeIndex);
} else if (impl->noBindingBuffer) {
encoder->setVertexBuffer(impl->noBindingBuffer, /*offset=*/0, attributeIndex);
renderPass.bindVertex(impl->noBindingBuffer->get(), /*offset=*/0, attributeIndex);
}
attributeIndex += 1;
}
}
void Drawable::unbindAttributes(const RenderPass& renderPass) const {
const auto& encoder = renderPass.getMetalEncoder();
NS::UInteger attributeIndex = 0;
for (const auto& binding : impl->attributeBindings) {
encoder->setVertexBuffer(nullptr, /*offset=*/0, attributeIndex);
attributeIndex += 1;
}
}
void Drawable::bindUniformBuffers(const RenderPass& renderPass) const {
void Drawable::bindUniformBuffers(RenderPass& renderPass) const noexcept {
if (shader) {
const auto& shaderMTL = static_cast<const ShaderProgram&>(*shader);
const auto& encoder = renderPass.getMetalEncoder();
for (const auto& element : shaderMTL.getUniformBlocks().getMap()) {
const auto& uniformBuffer = getUniformBuffers().get(element.first);
if (!uniformBuffer) {
using namespace std::string_literals;
const auto tileID = getTileID() ? util::toString(*getTileID()) : "<no tile>";
const auto tileLabel = util::toString(getID()) + "/" + getName() + "/" + tileID;
Log::Error(Event::General,
"bindUniformBuffers: UBO "s + stringIndexer().get(element.first) + " not found on " +
tileLabel + ". skipping.");
assert(false);
continue;
}
assert(uniformBuffer && "UBO missing, drawable skipped");
if (uniformBuffer) {
const auto& buffer = static_cast<UniformBuffer&>(*uniformBuffer.get());
const auto& resource = buffer.getBufferResource();
const auto& block = static_cast<const UniformBlock&>(*element.second);
const auto index = block.getIndex();
const auto& buffer = static_cast<UniformBuffer&>(*uniformBuffer.get());
const auto& bufferMTL = buffer.getBufferResource().getMetalBuffer().get();
const auto& block = static_cast<const UniformBlock&>(*element.second);
const auto index = block.getIndex();
if (block.getBindVertex()) {
encoder->setVertexBuffer(bufferMTL, /*offset=*/0, index);
}
if (block.getBindFragment()) {
encoder->setFragmentBuffer(bufferMTL, /*offset=*/0, index);
if (block.getBindVertex()) {
renderPass.bindVertex(resource, /*offset=*/0, index);
}
if (block.getBindFragment()) {
renderPass.bindFragment(resource, /*offset=*/0, index);
}
}
}
}
}
void Drawable::unbindUniformBuffers(const RenderPass& renderPass) const {
if (shader) {
const auto& shaderMTL = static_cast<const ShaderProgram&>(*shader);
const auto& encoder = renderPass.getMetalEncoder();
for (const auto& element : shaderMTL.getUniformBlocks().getMap()) {
const auto index = element.second->getIndex();
encoder->setVertexBuffer(nullptr, 0, index);
}
}
}
void Drawable::bindTextures(const RenderPass& renderPass) const {
void Drawable::bindTextures(RenderPass& renderPass) const noexcept {
for (const auto& pair : textures) {
if (const auto& tex = pair.second) {
const auto& location = pair.first;
std::static_pointer_cast<mtl::Texture2D>(tex)->bind(renderPass, location);
static_cast<mtl::Texture2D&>(*tex).bind(renderPass, location);
}
}
}
void Drawable::unbindTextures(const RenderPass& renderPass) const {
void Drawable::unbindTextures(RenderPass& renderPass) const noexcept {
for (const auto& pair : textures) {
if (const auto& tex = pair.second) {
const auto& location = pair.first;
std::static_pointer_cast<mtl::Texture2D>(tex)->unbind(renderPass, location);
static_cast<mtl::Texture2D&>(*tex).unbind(renderPass, location);
}
}
}
void Drawable::uploadTextures() const {
void Drawable::uploadTextures(UploadPass&) const noexcept {
for (const auto& pair : textures) {
if (const auto& tex = pair.second) {
std::static_pointer_cast<mtl::Texture2D>(tex)->upload();
static_cast<mtl::Texture2D&>(*tex).upload();
}
}
}
namespace {
MTL::VertexFormat mtlVertexTypeOf(gfx::AttributeDataType type) {
MTL::VertexFormat mtlVertexTypeOf(gfx::AttributeDataType type) noexcept {
switch (type) {
case gfx::AttributeDataType::Byte:
return MTL::VertexFormatChar;
@@ -548,8 +499,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
}
if (impl->indexes->getDirty()) {
auto indexBufferResource{
uploadPass.createIndexBufferResource(impl->indexes->data(), impl->indexes->bytes(), usage)};
auto indexBufferResource{uploadPass.createIndexBufferResource(
impl->indexes->data(), impl->indexes->bytes(), usage, /*persistent=*/false)};
auto indexBuffer = std::make_unique<gfx::IndexBuffer>(impl->indexes->elements(),
std::move(indexBufferResource));
auto buffer = std::make_unique<IndexBuffer>(std::move(indexBuffer));
@@ -581,7 +532,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
[](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
if (impl->attributeBindings != attributeBindings_) {
impl->attributeBindings = attributeBindings_;
impl->attributeBindings = std::move(attributeBindings_);
// Create a layout descriptor for each attribute
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
@@ -595,7 +546,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
if (const auto& buf = context.getEmptyVertexBuffer()) {
impl->noBindingBuffer = getMetalBuffer(buf.get());
impl->noBindingBuffer = buf.get();
}
}
@@ -626,23 +577,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
textures.begin(), textures.end(), [](const auto& pair) { return pair.second && pair.second->needsUpload(); });
if (texturesNeedUpload) {
uploadTextures();
uploadTextures(uploadPass);
}
}
/*
gfx::ColorMode Drawable::makeColorMode(PaintParameters& parameters) const {
return enableColor ? parameters.colorModeForRenderPass() : gfx::ColorMode::disabled();
}
gfx::StencilMode Drawable::makeStencilMode(PaintParameters& parameters) const {
if (enableStencil) {
if (!is3D && tileID) {
return parameters.stencilModeForClipping(tileID->toUnwrapped());
}
assert(false);
}
return gfx::StencilMode::disabled();
}
*/
} // namespace mtl
} // namespace mbgl