DX12) 部分常量缓冲区被截断

DX12) Part of the Constants buffer is cut off

这是我的对象绘图常量缓冲区。 实际上,gWorld 和 gOldWorld 的值是正确的,但是 gCubemapOn、gMotionBlurOn、gRimLightOn 的值是错误的。

gCubemapOn 必须为 TRUE,它看起来像,但实际上该值是 65537。 gRimLightOn 必须为 TRUE,但如您所见,实际值为 FALSE。

下面的代码是我如何使用常量缓冲区的。

template<typename Cnst>
class ConstantBuffer
{
public:
    ConstantBuffer(ID3D12Device* device, UINT count, bool isConstant=true)
    {   
        if (isConstant)
            mByteSize = (sizeof(Cnst) + 255) & ~255;
        else
            mByteSize = sizeof(Cnst);

        ThrowIfFailed(device->CreateCommittedResource(
            &Extension::HeapProperties(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &Extension::BufferResourceDesc(D3D12_RESOURCE_DIMENSION_BUFFER, mByteSize * count),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr, IID_PPV_ARGS(&mUploadBuffer)));

        ThrowIfFailed(mUploadBuffer->Map(0, nullptr, (void**)(&mData)));
    }
    ConstantBuffer(const ConstantBuffer& rhs) = delete;
    ConstantBuffer& operator=(const ConstantBuffer& rhs) = delete;
    virtual ~ConstantBuffer()
    {
        if (mUploadBuffer)
            mUploadBuffer->Unmap(0, nullptr);
        mData = nullptr;
    }

    D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress(int idx) const
    {
        return mUploadBuffer->GetGPUVirtualAddress() + idx * mByteSize;
    }

    void CopyData(int index, const Cnst& data)
    {
        memcpy(&mData[index * mByteSize], &data, sizeof(Cnst));
    }

    UINT GetByteSize() const
    {
        return mByteSize;
    }

private:
    ComPtr<ID3D12Resource> mUploadBuffer = nullptr;
    BYTE* mData = nullptr;
    UINT mByteSize = 0;
};

这就是我更新常量缓冲区的方式

void Pipeline::UpdateConstants()
{
    UINT matOffset = 0;
    for (int i = 0; i < mRenderObjects.size(); i++)
    {
        mObjectCB->CopyData(i, mRenderObjects[i]->GetObjectConstants());
        mRenderObjects[i]->UpdateMatConstants(mMaterialCB.get(), matOffset);        
        matOffset += mRenderObjects[i]->GetMeshCount();
    }
}
ObjectConstants GameObject::GetObjectConstants()
{
    ObjectConstants objCnst = {};
    if (mReflected)
    {
        objCnst.World = Matrix4x4::Transpose(Matrix4x4::Multiply(mWorld, mReflectMatrix));
        objCnst.oldWorld = Matrix4x4::Transpose(Matrix4x4::Multiply(mOldWorld, mReflectMatrix));
    }
    else
    {
        objCnst.World = Matrix4x4::Transpose(mWorld);
        objCnst.oldWorld = Matrix4x4::Transpose(mOldWorld);
    }
    objCnst.cubemapOn = mCubemapOn;
    objCnst.motionBlurOn = mMotionBlurOn;
    objCnst.rimLightOn = mRimLightOn;

    return objCnst;
}
struct ObjectConstants
{
    XMFLOAT4X4 World;
    XMFLOAT4X4 oldWorld;
    bool cubemapOn;
    bool motionBlurOn;
    bool rimLightOn;
};

我相信这与看到的问题相同 。 HLSL bool 是 4 个字节,C++ bool 是 1 个字节。如果您将 CPU 结构声明为

struct ObjectConstants
{
    XMFLOAT4X4 World;
    XMFLOAT4X4 oldWorld;
    int32_t cubemapOn;
    int32_t motionBlurOn;
    int32_t rimLightOn;
};

应该可以。