// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/RenderEncoderBase.h"

#include <math.h>

#include <cstring>
#include <utility>

#include "dawn/common/Constants.h"
#include "dawn/native/BindGroup.h"
#include "dawn/native/Buffer.h"
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/CommandValidation.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/RenderPipeline.h"
#include "dawn/native/ValidationUtils_autogen.h"

namespace dawn::native {

RenderEncoderBase::RenderEncoderBase(DeviceBase* device,
                                     StringView label,
                                     EncodingContext* encodingContext,
                                     Ref<AttachmentState> attachmentState,
                                     bool depthReadOnly,
                                     bool stencilReadOnly)
    : ProgrammableEncoder(device, label, encodingContext),
      mIndirectDrawMetadata(device->GetLimits()),
      mAttachmentState(std::move(attachmentState)),
      mDisableBaseVertex(device->IsToggleEnabled(Toggle::DisableBaseVertex)),
      mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {
    mDepthReadOnly = depthReadOnly;
    mStencilReadOnly = stencilReadOnly;
}

RenderEncoderBase::RenderEncoderBase(DeviceBase* device,
                                     EncodingContext* encodingContext,
                                     ErrorTag errorTag,
                                     StringView label)
    : ProgrammableEncoder(device, encodingContext, errorTag, label),
      mIndirectDrawMetadata(device->GetLimits()),
      mDisableBaseVertex(device->IsToggleEnabled(Toggle::DisableBaseVertex)),
      mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {}

void RenderEncoderBase::DestroyImpl(DestroyReason reason) {
    // Remove reference to the attachment state so that we don't have lingering references to
    // it preventing it from being uncached in the device.
    mAttachmentState = nullptr;
}

const AttachmentState* RenderEncoderBase::GetAttachmentState() const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(mAttachmentState != nullptr);
    return mAttachmentState.Get();
}

bool RenderEncoderBase::IsDepthReadOnly() const {
    DAWN_CHECK(!IsError());
    return mDepthReadOnly;
}

bool RenderEncoderBase::IsStencilReadOnly() const {
    DAWN_CHECK(!IsError());
    return mStencilReadOnly;
}

uint64_t RenderEncoderBase::GetDrawCount() const {
    DAWN_CHECK(!IsError());
    return mDrawCount;
}

Ref<AttachmentState> RenderEncoderBase::AcquireAttachmentState() {
    return std::move(mAttachmentState);
}

void RenderEncoderBase::APIDraw(uint32_t vertexCount,
                                uint32_t instanceCount,
                                uint32_t firstVertex,
                                uint32_t firstInstance) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                if (vertexCount == 0) {
                    GetDevice()->EmitWarningOnce(absl::StrFormat(
                        "Calling %s.Draw with a vertex count of 0 is unusual.", this));
                }
                if (instanceCount == 0) {
                    GetDevice()->EmitWarningOnce(absl::StrFormat(
                        "Calling %s.Draw with an instance count of 0 is unusual.", this));
                }

                DAWN_TRY(mCommandBufferState.ValidateCanDraw());

                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }

                DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0,
                                "First instance (%u) must be zero.", firstInstance);

                DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForVertexBuffer(vertexCount,
                                                                                  firstVertex));
                DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer(instanceCount,
                                                                                    firstInstance));
            }

            DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw);
            draw->vertexCount = vertexCount;
            draw->instanceCount = instanceCount;
            draw->firstVertex = firstVertex;
            draw->firstInstance = firstInstance;

            mDrawCount++;

            return {};
        },
        "encoding %s.Draw(%u, %u, %u, %u).", this, vertexCount, instanceCount, firstVertex,
        firstInstance);
}

void RenderEncoderBase::APIDrawIndexed(uint32_t indexCount,
                                       uint32_t instanceCount,
                                       uint32_t firstIndex,
                                       int32_t baseVertex,
                                       uint32_t firstInstance) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                if (indexCount == 0) {
                    GetDevice()->EmitWarningOnce(absl::StrFormat(
                        "Calling %s.Draw with an index count of 0 is unusual.", this));
                }
                if (instanceCount == 0) {
                    GetDevice()->EmitWarningOnce(absl::StrFormat(
                        "Calling %s.Draw with an instance count of 0 is unusual.", this));
                }

                DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed());

                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }

                DAWN_INVALID_IF(mDisableBaseInstance && firstInstance != 0,
                                "First instance (%u) must be zero.", firstInstance);

                DAWN_INVALID_IF(mDisableBaseVertex && baseVertex != 0,
                                "Base vertex (%u) must be zero.", baseVertex);

                DAWN_TRY(mCommandBufferState.ValidateIndexBufferInRange(indexCount, firstIndex));

                // DrawIndexed only validate instance step mode vertex buffer
                DAWN_TRY(mCommandBufferState.ValidateBufferInRangeForInstanceBuffer(instanceCount,
                                                                                    firstInstance));
            }

            DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed);
            draw->indexCount = indexCount;
            draw->instanceCount = instanceCount;
            draw->firstIndex = firstIndex;
            draw->baseVertex = baseVertex;
            draw->firstInstance = firstInstance;

            mDrawCount++;

            return {};
        },
        "encoding %s.DrawIndexed(%u, %u, %u, %i, %u).", this, indexCount, instanceCount, firstIndex,
        baseVertex, firstInstance);
}

void RenderEncoderBase::APIDrawIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
                DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
                DAWN_TRY(mCommandBufferState.ValidateCanDraw());
                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }

                DAWN_INVALID_IF(indirectOffset % 4 != 0,
                                "Indirect offset (%u) is not a multiple of 4.", indirectOffset);

                DAWN_INVALID_IF(
                    indirectOffset >= indirectBuffer->GetSize() ||
                        kDrawIndirectSize > indirectBuffer->GetSize() - indirectOffset,
                    "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).",
                    indirectOffset, indirectBuffer, indirectBuffer->GetSize());
            }

            DrawIndirectCmd* cmd = allocator->Allocate<DrawIndirectCmd>(Command::DrawIndirect);

            bool duplicateBaseVertexInstance =
                GetDevice()->ShouldDuplicateParametersForDrawIndirect(
                    mCommandBufferState.GetRenderPipeline());
            if (NeedsIndirectGPUValidation() &&
                (IsValidationEnabled() || duplicateBaseVertexInstance)) {
                // Later, EncodeIndirectDrawValidationCommands will allocate a scratch storage
                // buffer which will store the validated or duplicated indirect data. The buffer
                // and offset will be updated to point to it.
                // |EncodeIndirectDrawValidationCommands| is called at the end of encoding the
                // render pass, while the |cmd| pointer is still valid.
                cmd->indirectBuffer = nullptr;

                mIndirectDrawMetadata.AddIndirectDraw(indirectBuffer, indirectOffset,
                                                      duplicateBaseVertexInstance, cmd);

                // We only set usage as `kIndirectBufferForFrontendValidation` so that the indirect
                // usage can be ignored in the backends because `indirectBuffer` is actually not
                // used as an indirect buffer.
                mUsageTracker.BufferUsedAs(indirectBuffer, kIndirectBufferForFrontendValidation);
            } else {
                cmd->indirectBuffer = indirectBuffer;
                cmd->indirectOffset = indirectOffset;

                mUsageTracker.BufferUsedAs(indirectBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }

            mDrawCount++;

            return {};
        },
        "encoding %s.DrawIndirect(%s, %u).", this, indirectBuffer, indirectOffset);
}

void RenderEncoderBase::APIDrawIndexedIndirect(BufferBase* indirectBuffer,
                                               uint64_t indirectOffset) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
                DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
                DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed());
                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }

                DAWN_INVALID_IF(indirectOffset % 4 != 0,
                                "Indirect offset (%u) is not a multiple of 4.", indirectOffset);

                DAWN_INVALID_IF(
                    (indirectOffset >= indirectBuffer->GetSize() ||
                     kDrawIndexedIndirectSize > indirectBuffer->GetSize() - indirectOffset),
                    "Indirect offset (%u) is out of bounds of indirect buffer %s size (%u).",
                    indirectOffset, indirectBuffer, indirectBuffer->GetSize());
            }

            DrawIndexedIndirectCmd* cmd =
                allocator->Allocate<DrawIndexedIndirectCmd>(Command::DrawIndexedIndirect);

            bool duplicateBaseVertexInstance =
                GetDevice()->ShouldDuplicateParametersForDrawIndirect(
                    mCommandBufferState.GetRenderPipeline());
            bool applyIndexBufferOffsetToFirstIndex =
                GetDevice()->ShouldApplyIndexBufferOffsetToFirstIndex();
            if (NeedsIndirectGPUValidation() &&
                (IsValidationEnabled() || duplicateBaseVertexInstance ||
                 applyIndexBufferOffsetToFirstIndex)) {
                // Later, EncodeIndirectDrawValidationCommands will allocate a scratch storage
                // buffer which will store the validated or duplicated indirect data. The buffer
                // and offset will be updated to point to it.
                // |EncodeIndirectDrawValidationCommands| is called at the end of encoding the
                // render pass, while the |cmd| pointer is still valid.
                cmd->indirectBuffer = nullptr;

                mIndirectDrawMetadata.AddIndexedIndirectDraw(
                    mCommandBufferState.GetIndexFormat(), mCommandBufferState.GetIndexBufferSize(),
                    mCommandBufferState.GetIndexBufferOffset(), indirectBuffer, indirectOffset,
                    duplicateBaseVertexInstance, cmd);

                // We only set usage as `kIndirectBufferForFrontendValidation` so that the indirect
                // usage can be ignored in the backends because `indirectBuffer` is actually not
                // used as an indirect buffer.
                mUsageTracker.BufferUsedAs(indirectBuffer, kIndirectBufferForFrontendValidation);
            } else {
                cmd->indirectBuffer = indirectBuffer;
                cmd->indirectOffset = indirectOffset;

                mUsageTracker.BufferUsedAs(indirectBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }

            mDrawCount++;

            return {};
        },
        "encoding %s.DrawIndexedIndirect(%s, %u).", this, indirectBuffer, indirectOffset);
}

void RenderEncoderBase::APIMultiDrawIndirect(BufferBase* indirectBuffer,
                                             uint64_t indirectOffset,
                                             uint32_t maxDrawCount,
                                             BufferBase* drawCountBuffer,
                                             uint64_t drawCountBufferOffset) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_INVALID_IF(!GetDevice()->HasFeature(Feature::MultiDrawIndirect),
                                "%s is not enabled.", wgpu::FeatureName::MultiDrawIndirect);

                DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
                DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));

                DAWN_INVALID_IF(indirectOffset % 4 != 0,
                                "Indirect offset (%u) is not a multiple of 4.", indirectOffset);

                DAWN_INVALID_IF(indirectOffset >= indirectBuffer->GetSize(),
                                "Indirect offset (%u) is larger than or equal to the size (%u) of "
                                "the indirect buffer.",
                                indirectOffset, indirectBuffer->GetSize());

                // maxDrawCount * kDrawIndirectSize can't overflow because
                // kDrawIndirectSize is a uint64_t which results in a uint64_t
                DAWN_INVALID_IF(
                    indirectBuffer->GetSize() - indirectOffset < maxDrawCount * kDrawIndirectSize,
                    "Indirect Buffer size (%u) and offset (%u) can not hold maxDrawCount "
                    "(%u) draw commands.",
                    indirectBuffer->GetSize(), indirectOffset, maxDrawCount);

                // draw count buffer is optional
                if (drawCountBuffer != nullptr) {
                    DAWN_TRY(GetDevice()->ValidateObject(drawCountBuffer));
                    DAWN_TRY(ValidateCanUseAs(drawCountBuffer, wgpu::BufferUsage::Indirect));

                    DAWN_INVALID_IF(drawCountBufferOffset % 4 != 0,
                                    "Draw count buffer offset (%u) is not a multiple of 4.",
                                    drawCountBufferOffset);

                    DAWN_INVALID_IF(
                        drawCountBufferOffset >= drawCountBuffer->GetSize(),
                        "Draw count buffer offset (%u) is larger than or equal to the size "
                        "(%u) of the draw count buffer.",
                        drawCountBufferOffset, drawCountBuffer->GetSize());

                    // Can't underflow because the offset is checked to be smaller than the buffer.
                    DAWN_INVALID_IF(drawCountBuffer->GetSize() - drawCountBufferOffset < 4,
                                    "Draw count buffer offset (%u) is out of bounds of the draw "
                                    "count buffer %s size (%u).",
                                    drawCountBufferOffset, drawCountBuffer,
                                    drawCountBuffer->GetSize());
                }

                DAWN_TRY(mCommandBufferState.ValidateCanDraw());

                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }
            }

            MultiDrawIndirectCmd* cmd =
                allocator->Allocate<MultiDrawIndirectCmd>(Command::MultiDrawIndirect);

            cmd->indirectBuffer = indirectBuffer;
            cmd->indirectOffset = indirectOffset;
            cmd->maxDrawCount = maxDrawCount;
            cmd->drawCountBuffer = drawCountBuffer;
            cmd->drawCountOffset = drawCountBufferOffset;

            bool duplicateBaseVertexInstance =
                GetDevice()->ShouldDuplicateParametersForDrawIndirect(
                    mCommandBufferState.GetRenderPipeline());

            mIndirectDrawMetadata.AddMultiDrawIndirect(
                mCommandBufferState.GetRenderPipeline()->GetPrimitiveTopology(),
                duplicateBaseVertexInstance, cmd);

            if (NeedsIndirectGPUValidation() &&
                (IsValidationEnabled() ||
                 GetDevice()->MayRequireDuplicationOfIndirectParameters())) {
                // We only set usage as `kIndirectBufferForFrontendValidation` because
                // `indirectBuffer` may not be used as an indirect buffer. The usage of
                // `indirectBuffer` may be updated in `EncodeIndirectDrawValidationCommands()` in
                // `EncodingContext::ExitRenderPass()`, which is only called when above conditions
                // are both met.
                mUsageTracker.BufferUsedAs(indirectBuffer, kIndirectBufferForFrontendValidation);
            } else {
                mUsageTracker.BufferUsedAs(indirectBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }
            if (drawCountBuffer != nullptr) {
                mUsageTracker.BufferUsedAs(drawCountBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }

            mDrawCount += maxDrawCount;

            return {};
        },
        "encoding %s.MultiDrawIndirect(%s, %u, %u, %s, %u).", this, indirectBuffer, indirectOffset,
        maxDrawCount, drawCountBuffer, drawCountBufferOffset);
}

void RenderEncoderBase::APIMultiDrawIndexedIndirect(BufferBase* indirectBuffer,
                                                    uint64_t indirectOffset,
                                                    uint32_t maxDrawCount,
                                                    BufferBase* drawCountBuffer,
                                                    uint64_t drawCountBufferOffset) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_INVALID_IF(!GetDevice()->HasFeature(Feature::MultiDrawIndirect),
                                "%s is not enabled.", wgpu::FeatureName::MultiDrawIndirect);

                DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
                DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));

                DAWN_INVALID_IF(indirectOffset % 4 != 0,
                                "Indirect offset (%u) is not a multiple of 4.", indirectOffset);

                DAWN_INVALID_IF(indirectOffset >= indirectBuffer->GetSize(),
                                "Indirect offset (%u) is larger than or equal to the size (%u) of "
                                "the indirect buffer.",
                                indirectOffset, indirectBuffer->GetSize());

                // maxDrawCount * kDrawIndexedIndirectSize can't overflow because
                // kDrawIndexedIndirectSize is a uint64_t which results in a uint64_t
                DAWN_INVALID_IF(
                    indirectBuffer->GetSize() - indirectOffset <
                        maxDrawCount * kDrawIndexedIndirectSize,
                    "Indirect Buffer size (%u) and offset (%u) can not hold maxDrawCount "
                    "(%u) draw commands.",
                    indirectBuffer->GetSize(), indirectOffset, maxDrawCount);

                // draw count buffer is optional
                if (drawCountBuffer != nullptr) {
                    DAWN_TRY(GetDevice()->ValidateObject(drawCountBuffer));
                    DAWN_TRY(ValidateCanUseAs(drawCountBuffer, wgpu::BufferUsage::Indirect));

                    DAWN_INVALID_IF(drawCountBufferOffset % 4 != 0,
                                    "Draw count buffer offset (%u) is not a multiple of 4.",
                                    drawCountBufferOffset);

                    DAWN_INVALID_IF(
                        drawCountBufferOffset >= drawCountBuffer->GetSize(),
                        "Draw count buffer offset (%u) is larger than or equal to the size "
                        "(%u) of the draw count buffer.",
                        drawCountBufferOffset, drawCountBuffer->GetSize());

                    // Can't underflow because the offset is checked to be smaller than the buffer.
                    DAWN_INVALID_IF(drawCountBuffer->GetSize() - drawCountBufferOffset < 4,
                                    "Draw count buffer offset (%u) is out of bounds of the draw "
                                    "count buffer %s size (%u).",
                                    drawCountBufferOffset, drawCountBuffer,
                                    drawCountBuffer->GetSize());
                }

                DAWN_TRY(mCommandBufferState.ValidateCanDrawIndexed());

                if (!GetDevice()->HasFlexibleTextureViews()) {
                    DAWN_TRY(mCommandBufferState.ValidateNoDifferentTextureViewsOnSameTexture());
                }
            }

            MultiDrawIndexedIndirectCmd* cmd =
                allocator->Allocate<MultiDrawIndexedIndirectCmd>(Command::MultiDrawIndexedIndirect);

            cmd->indirectBuffer = indirectBuffer;
            cmd->indirectOffset = indirectOffset;
            cmd->maxDrawCount = maxDrawCount;
            cmd->drawCountBuffer = drawCountBuffer;
            cmd->drawCountOffset = drawCountBufferOffset;

            bool duplicateBaseVertexInstance =
                GetDevice()->ShouldDuplicateParametersForDrawIndirect(
                    mCommandBufferState.GetRenderPipeline());

            mIndirectDrawMetadata.AddMultiDrawIndexedIndirect(
                mCommandBufferState.GetIndexBuffer(), mCommandBufferState.GetIndexFormat(),
                mCommandBufferState.GetIndexBufferSize(),
                mCommandBufferState.GetIndexBufferOffset(),
                mCommandBufferState.GetRenderPipeline()->GetPrimitiveTopology(),
                duplicateBaseVertexInstance, cmd);

            if (NeedsIndirectGPUValidation() &&
                (IsValidationEnabled() ||
                 GetDevice()->MayRequireDuplicationOfIndirectParameters())) {
                // We only set usage as `kIndirectBufferForFrontendValidation` because
                // `indirectBuffer` may not be used as an indirect buffer. The usage of
                // `indirectBuffer` may be updated in `EncodeIndirectDrawValidationCommands()` in
                // `EncodingContext::ExitRenderPass()`, which is only called when above conditions
                // are both met.
                mUsageTracker.BufferUsedAs(indirectBuffer, kIndirectBufferForFrontendValidation);
            } else {
                mUsageTracker.BufferUsedAs(indirectBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }
            if (drawCountBuffer != nullptr) {
                mUsageTracker.BufferUsedAs(drawCountBuffer,
                                           kIndirectBufferForFrontendValidation |
                                               kIndirectBufferForBackendResourceTracking);
            }

            mDrawCount += maxDrawCount;

            return {};
        },
        "encoding %s.MultiDrawIndexedIndirect(%s, %u, %u, %s, %u).", this, indirectBuffer,
        indirectOffset, maxDrawCount, drawCountBuffer, drawCountBufferOffset);
}

void RenderEncoderBase::APISetPipeline(RenderPipelineBase* pipeline) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(pipeline));

                DAWN_INVALID_IF(pipeline->GetAttachmentState() != mAttachmentState.Get(),
                                "Attachment state of %s is not compatible with %s.\n"
                                "%s expects an attachment state of %s.\n"
                                "%s has an attachment state of %s.",
                                pipeline, this, this, mAttachmentState.Get(), pipeline,
                                pipeline->GetAttachmentState());

                DAWN_INVALID_IF(pipeline->WritesDepth() && mDepthReadOnly,
                                "%s writes depth while %s's depthReadOnly is true", pipeline, this);

                DAWN_INVALID_IF(pipeline->WritesStencil() && mStencilReadOnly,
                                "%s writes stencil while %s's stencilReadOnly is true", pipeline,
                                this);
            }

            mCommandBufferState.SetRenderPipeline(pipeline);

            SetRenderPipelineCmd* cmd =
                allocator->Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline);
            cmd->pipeline = pipeline;

            return {};
        },
        "encoding %s.SetPipeline(%s).", this, pipeline);
}

void RenderEncoderBase::APISetResourceTable(ResourceTableBase* table) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            DAWN_TRY(ProgrammableEncoder::SetResourceTable(table, allocator));
            mCommandBufferState.SetResourceTable(table);
            if (table) {
                mUsageTracker.AddResourceTableUsage(table);
            }
            return {};
        },
        "encoding %s.SetResourceTable(%s).", this, table);
}

void RenderEncoderBase::APISetIndexBuffer(BufferBase* buffer,
                                          wgpu::IndexFormat format,
                                          uint64_t offset,
                                          uint64_t size) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_TRY(GetDevice()->ValidateObject(buffer));
                DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index));

                DAWN_TRY(ValidateIndexFormat(format));

                DAWN_INVALID_IF(format == wgpu::IndexFormat::Undefined,
                                "Index format must be specified");

                DAWN_INVALID_IF(offset % uint64_t(IndexFormatSize(format)) != 0,
                                "Index buffer offset (%u) is not a multiple of the size (%u) "
                                "of %s.",
                                offset, IndexFormatSize(format), format);

                uint64_t bufferSize = buffer->GetSize();
                DAWN_INVALID_IF(offset > bufferSize,
                                "Index buffer offset (%u) is larger than the size (%u) of %s.",
                                offset, bufferSize, buffer);

                uint64_t remainingSize = bufferSize - offset;

                if (size == wgpu::kWholeSize) {
                    size = remainingSize;
                } else {
                    DAWN_INVALID_IF(size > remainingSize,
                                    "Index buffer range (offset: %u, size: %u) doesn't fit in "
                                    "the size (%u) of "
                                    "%s.",
                                    offset, size, bufferSize, buffer);
                }
            } else {
                if (size == wgpu::kWholeSize) {
                    DAWN_CHECK(buffer->GetSize() >= offset);
                    size = buffer->GetSize() - offset;
                }
            }

            mCommandBufferState.SetIndexBuffer(buffer, format, offset, size);

            SetIndexBufferCmd* cmd =
                allocator->Allocate<SetIndexBufferCmd>(Command::SetIndexBuffer);
            cmd->buffer = buffer;
            cmd->format = format;
            cmd->offset = offset;
            cmd->size = size;

            mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Index);

            return {};
        },
        "encoding %s.SetIndexBuffer(%s, %s, %u, %u).", this, buffer, format, offset, size);
}

void RenderEncoderBase::APISetVertexBuffer(uint32_t slot,
                                           BufferBase* buffer,
                                           uint64_t offset,
                                           uint64_t size) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_INVALID_IF(slot >= kMaxVertexBuffers,
                                "Vertex buffer slot (%u) is larger the maximum (%u)", slot,
                                kMaxVertexBuffers - 1);

                if (buffer == nullptr) {
                    DAWN_INVALID_IF(offset != 0, "Offset (%u) must be 0 if buffer is null", offset);
                    DAWN_INVALID_IF(
                        size != 0 && size != wgpu::kWholeSize,
                        "Size (%u) must be either 0 or wgpu::kWholeSize if buffer is null", size);
                } else {
                    DAWN_TRY(GetDevice()->ValidateObject(buffer));
                    DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex));
                    DAWN_INVALID_IF(offset % 4 != 0,
                                    "Vertex buffer offset (%u) is not a multiple of 4", offset);

                    uint64_t bufferSize = buffer->GetSize();
                    DAWN_INVALID_IF(offset > bufferSize,
                                    "Vertex buffer offset (%u) is larger than the size (%u) of %s.",
                                    offset, bufferSize, buffer);

                    uint64_t remainingSize = bufferSize - offset;

                    if (size == wgpu::kWholeSize) {
                        size = remainingSize;
                    } else {
                        DAWN_INVALID_IF(size > remainingSize,
                                        "Vertex buffer range (offset: %u, size: %u) doesn't fit in "
                                        "the size (%u) "
                                        "of %s.",
                                        offset, size, bufferSize, buffer);
                    }
                }
            } else {
                if (size == wgpu::kWholeSize && buffer != nullptr) {
                    DAWN_CHECK(buffer->GetSize() >= offset);
                    size = buffer->GetSize() - offset;
                }
            }

            VertexBufferSlot vbSlot = VertexBufferSlot(static_cast<uint8_t>(slot));
            if (buffer == nullptr) {
                mCommandBufferState.UnsetVertexBuffer(vbSlot);
            } else {
                mCommandBufferState.SetVertexBuffer(vbSlot, size);

                SetVertexBufferCmd* cmd =
                    allocator->Allocate<SetVertexBufferCmd>(Command::SetVertexBuffer);
                cmd->slot = vbSlot;
                cmd->buffer = buffer;
                cmd->offset = offset;
                cmd->size = size;

                mUsageTracker.BufferUsedAs(buffer, wgpu::BufferUsage::Vertex);
            }
            return {};
        },
        "encoding %s.SetVertexBuffer(%u, %s, %u, %u).", this, slot, buffer, offset, size);
}

void RenderEncoderBase::APISetBindGroup(uint32_t groupIndexIn,
                                        BindGroupBase* group,
                                        uint32_t dynamicOffsetCount,
                                        const uint32_t* dynamicOffsets) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            BindGroupIndex groupIndex(groupIndexIn);

            if (IsValidationEnabled()) {
                DAWN_TRY(
                    ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount, dynamicOffsets));
            }

            if (group == nullptr) {
                mCommandBufferState.UnsetBindGroup(groupIndex);
            } else {
                RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount,
                                   dynamicOffsets);
                mCommandBufferState.SetBindGroup(groupIndex, group, dynamicOffsetCount,
                                                 dynamicOffsets);
                mUsageTracker.AddBindGroup(group);
            }

            return {};
        },
        "encoding %s.SetBindGroup(%u, %s, %u, ...).", this, groupIndexIn, group,
        dynamicOffsetCount);
}

void RenderEncoderBase::APISetImmediates(uint32_t offset, const void* data, size_t size) {
    mEncodingContext->TryEncode(
        this,
        [&](CommandAllocator* allocator) -> MaybeError {
            if (IsValidationEnabled()) {
                DAWN_TRY(ValidateSetImmediates(offset, size));
            }

            // Skip SetImmediates when uploading constants are empty.
            if (size == 0) {
                return {};
            }

            SetImmediatesCmd* cmd = allocator->Allocate<SetImmediatesCmd>(Command::SetImmediates);
            cmd->offset = offset;
            cmd->size = uint32_t(size);
            uint8_t* immediateDatas = allocator->AllocateData<uint8_t>(cmd->size);
            memcpy(immediateDatas, data, size);

            mCommandBufferState.SetImmediateData(offset, uint32_t(size));

            return {};
        },
        "encoding %s.SetImmediates(%u, %u, ...).", this, offset, size);
}

}  // namespace dawn::native
