2013-06-11 31 views
5

Tôi đang điều tra một ngoại lệ E_INVALIDARG đó là ném khi tôi cố gắng để tạo ra một bộ đệm thứ hai liên tục lưu trữ thông tin cho đèn của tôi:Làm thế nào để đổ bóng liên tục cần phải được đệm để tránh một E_INVALIDARG?

// create matrix stack early 
    CD3D11_BUFFER_DESC constantMatrixBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); 
    DX::ThrowIfFailed(
     m_d3dDevice->CreateBuffer(
     &constantMatrixBufferDesc, 
     nullptr, 
     &m_constantMatrixBuffer 
     ) 
     ); 

    DX::ThrowIfFailed(
     m_matrixStack.Initialize(m_d3dContext, m_constantMatrixBuffer, &m_constantMatrixBufferData) 
     ); 

    // also create the light buffer early, we must create it now but we will later 
    // update it with the light information that we parsed from the model 
    CD3D11_BUFFER_DESC constantLightBufferDesc(sizeof(LightConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); 

/* !!!!---- AN E_INVALIDARG IS THROWN BY THE FOLLOWING LINE ----!!!! */ 
    DX::ThrowIfFailed(
     m_d3dDevice->CreateBuffer(
     &constantLightBufferDesc, 
     nullptr, 
     &m_constantLightBuffer 
     ) 
     ); 

Tại thời điểm này, dường như các thông số được truyền vào CreateBuffer của ánh sáng cuộc gọi đang ở trong trạng thái giống như của Ma trận! Vấn đề dường như phải làm với số byte được lưu trữ trong mô tả bộ đệm.

Bộ đệm được xác định như vậy trong các mô-đun:

// a constant buffer that contains the 3 matrices needed to 
// transform points so that they're rendered correctly 
struct ModelViewProjectionConstantBuffer 
{ 
    DirectX::XMFLOAT4X4 model; 
    DirectX::XMFLOAT4X4 view; 
    DirectX::XMFLOAT4X4 projection; 
}; 

// a constant buffer that contains up to 4 directional or point lights 
struct LightConstantBuffer 
{ 
    DirectX::XMFLOAT3 ambient[4]; 
    DirectX::XMFLOAT3 diffuse[4]; 
    DirectX::XMFLOAT3 specular[4]; 

    // the first spot in the array is the constant attenuation term, 
    // the second is the linear term, and the third is quadradic 
    DirectX::XMFLOAT3 attenuation[4]; 

    // the position and direction of the light 
    DirectX::XMFLOAT3 position[4]; 
    DirectX::XMFLOAT3 direction[4]; 

    // the type of light that we're working with, defined in lights.h 
    UINT type[4]; 

    // a number from 0 to 4 that tells us how many lights there are 
    UINT num; 
}; 

Và như vậy trong vertex shader (.hlsl):

cbuffer ModelViewProjectionConstantBuffer : register (b0) 
{ 
    matrix model; 
    matrix view; 
    matrix projection; 
}; 

cbuffer LightConstantBuffer : register (b1) 
{ 
    float3 ambient[4]; 
    float3 diffuse[4]; 
    float3 specular[4]; 

    // the first spot in the array is the constant attenuation term, 
    // the second is the linear term, and the third is quadradic 
    float3 attenuation[4]; 

    // the position and direction of the light 
    float3 position[4]; 
    float3 direction[4]; 

    // the type of light that we're working with, defined in lights.h 
    uint type[4]; 

    // a number from 0 to 4 that tells us how many lights there are 
    uint num; 
} 

Trong một nỗ lực để tìm ra những gì đang gây ra này , Tôi đã tình cờ gặp phải dòng này trong tài liệu MSDN HLSL Shader (http://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs.85).aspx):

Each element stores a 1-to-4 component constant, determined by the format of the data stored.

Điều này có nghĩa là gì và đó có phải là lý do cho ngoại lệ này không? Tôi đã nhận thấy rằng trong Visual Studio 3D Starter Kit (http://code.msdn.microsoft.com/wpapps/Visual-Studio-3D-Starter-455a15f1), các bộ đệm đã nổi extra padding họ:

/////////////////////////////////////////////////////////////////////////////////////////// 
    // 
    // Constant buffer structures 
    // 
    // These structs use padding and different data types in places to adhere 
    // to the shader constant's alignment. 
    // 
    struct MaterialConstants 
    { 
     MaterialConstants() 
     { 
      Ambient = DirectX::XMFLOAT4(0.0f,0.0f,0.0f,1.0f); 
      Diffuse = DirectX::XMFLOAT4(1.0f,1.0f,1.0f,1.0f); 
      Specular = DirectX::XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); 
      Emissive = DirectX::XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); 
      SpecularPower = 1.0f; 
      Padding0 = 0.0f; 
      Padding1 = 0.0f; 
      Padding2 = 0.0f; 
     } 

     DirectX::XMFLOAT4 Ambient; 
     DirectX::XMFLOAT4 Diffuse; 
     DirectX::XMFLOAT4 Specular; 
     DirectX::XMFLOAT4 Emissive; 
     float    SpecularPower; 
     float    Padding0; 
     float    Padding1; 
     float    Padding2; 
    }; 

    struct LightConstants 
    { 
     LightConstants() 
     { 
      ZeroMemory(this, sizeof(LightConstants)); 
      Ambient = DirectX::XMFLOAT4(1.0f,1.0f,1.0f,1.0f); 
     } 

     DirectX::XMFLOAT4 Ambient; 
     DirectX::XMFLOAT4 LightColor[4]; 
     DirectX::XMFLOAT4 LightAttenuation[4]; 
     DirectX::XMFLOAT4 LightDirection[4]; 
     DirectX::XMFLOAT4 LightSpecularIntensity[4]; 
     UINT    IsPointLight[4*4]; 
     UINT    ActiveLights; 
     float    Padding0; 
     float    Padding1; 
     float    Padding2; 
    }; 

    ... // and there's even more where that came from 

Vì vậy, tôi chỉ không đệm những điều này một cách chính xác? Và nếu vậy, làm thế nào tôi nên đệm chúng? Hay nó là một cái gì đó hoàn toàn khác mà tôi đang thiếu?

Tôi đánh giá cao việc bạn đọc và cố gắng trợ giúp.

Trả lời

8

Rất khó để khắc phục sự cố của bạn vì thiếu thông tin quan trọng, nhưng hãy thử.

Rõ ràng, 'E_INVALIDARG' cho biết đối số không hợp lệ được chuyển đến hàm. Bây giờ chúng ta phải tìm ra tham số nào là sai. Phương pháp ID3D11Device::CreateBuffer chấp nhận 3 tham số: D3D11_BUFFER_DESC, D3D11_SUBRESOURCE_DATAID3D11Buffer ** chính nó.

Và bạn nuôi nó & constantLightBufferDesc, nullptr, & m_constantLightBuffer. Bây giờ bạn phải đọc kỹ tất cả 4 bài viết MSDN để tìm hiểu xem có gì sai.

  1. constantLightBuffer nó không phải là một vấn đề, chỉ cần kiểm tra xem nó có ID3D11Buffer kiểu con trỏ.
  2. nullptr không có vấn đề gì, nhưng AFAIK không phải là từ khóa chuẩn C++, vì vậy có lẽ đơn giản '0' sẽ tốt hơn ở đây. Trên thực tế, nó là một tiêu chuẩn kể từ C++ 11
  3. Đáng tiếc là bạn không cung cấp định nghĩa constantLightBufferDesc của bạn, đó là một ứng cử viên là một vấn đề: như bạn đã nói có thể có sự liên kết đệm sai lầm: nếu constantLightBufferDesc.BindFlags của bạn có D3D11_BIND_CONSTANT_BUFFER cờ và constantLightBufferDesc.ByteWidthis not a multiple of 16, việc tạo bộ đệm không thành công. Nhưng đó chỉ là một phỏng đoán. Bạn có thể có bất kỳ sự không phù hợp nào khác ở đây, vì vậy, bạn có thể đoán một cách vô cùng.

Fortunalely, có một cách khác để chẩn đoán: nếu bạn tạo ra bạn ID3D11Device với D3D11_CREATE_DEVICE_DEBUG cờ, trong Visual Studio cửa sổ đầu ra bạn sẽ thấy tất cả những lời cảnh báo và các lỗi theo D3D11. Ví dụ, trong trường hợp không thẳng hàng, bạn sẽ thấy:

D3D11 ERROR: ID3D11Device::CreateBuffer: The Dimensions are invalid. For ConstantBuffers, marked with the D3D11_BIND_CONSTANT_BUFFER BindFlag, the ByteWidth (value = 10) must be a multiple of 16. ByteWidth must also be less than or equal to 65536 on the current driver. [ STATE_CREATION ERROR #66: CREATEBUFFER_INVALIDDIMENSIONS]

Vì vậy, nếu CreateBuffer() thất bại vì kích thước bộ đệm sai, có một số cách để xử lý này:

  1. Thay đổi kích thước cấu trúc của bạn: thêm thành viên đệm vì vậy tổng số sizeof() sẽ trở thành bội số của 16.
  2. Khai báo cấu trúc của bạn dưới dạng căn chỉnh 16 bit. AFAIK chỉ có các cách trình biên dịch cụ thể để thực hiện việc này: ví dụ #pragma pack cho msvc.
  3. Assign để ByteWidth không phải là một kích thước cấu trúc thật, nhưng làm tròn lên đến nhiều tiếp theo của 16: link

Chúc mừng gỡ lỗi! =)

+0

Cảm ơn bạn! Vấn đề là những gì bạn intuited và tôi giải quyết nó bằng cách thêm các thành viên đệm để làm cho sizeof trở thành một bội số của 16. Tôi đánh giá cao sự giúp đỡ của bạn rất nhiều. – Nico

Các vấn đề liên quan