microsoft descargar como arreglar activar aceleracion c++ graphics windows-phone-8 directx hlsl

c++ - descargar - ¿Cómo deben rellenarse los sombreadores constantes para evitar un E_INVALIDARG?



direct3d windows 7 (1)

Estoy investigando una excepción E_INVALIDARG que se lanza cuando intento crear un segundo buffer constante que almacena la información para mis luces:

// 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 ) );

En este punto, parece que los parámetros que pasan a la llamada CreateBuffer de Light están en el mismo estado que los de Matrix. El problema parece tener que ver con la cantidad de bytes almacenados en la descripción del búfer.

El buffer se define como tal en el módulo:

// 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; };

Y como tal en el sombreador de vértices (.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; }

En un intento por descubrir qué está causando esto, me encontré con esta línea en la documentación de MSDN HLSL Shader ( http://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs. 85) .aspx ):

Cada elemento almacena una constante de componente de 1 a 4, determinada por el formato de los datos almacenados.

¿Qué significa esto y es la razón de esta excepción? Me he dado cuenta de que en el Visual Studio 3D Starter Kit ( http://code.msdn.microsoft.com/wpapps/Visual-Studio-3D-Starter-455a15f1 ), los buffers tienen flotadores adicionales que los protegen:

/////////////////////////////////////////////////////////////////////////////////////////// // // 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

Entonces, ¿no estoy rellenando estas cosas correctamente? Y si es así, ¿cómo debo rellenarlos? ¿O es algo completamente diferente de lo que me estoy perdiendo?

Te agradezco mucho que leas esto y trates de ayudar.


Es difícil solucionar su problema debido a la falta de información importante, pero intentémoslo.

Obviamente, ''E_INVALIDARG'' dice que el argumento inválido pasó a la función. Ahora debemos averiguar qué parámetro está mal. El método ID3D11Device :: CreateBuffer acepta 3 parámetros: D3D11_BUFFER_DESC , D3D11_SUBRESOURCE_DATA e ID3D11Buffer ** en sí.

Y usted lo alimenta y es constanteLightBufferDesc , nullptr , y m_constantLightBuffer . Ahora debe leer detenidamente los 4 artículos de MSDN para descubrir qué está mal.

  1. constantLightBuffer no es un problema, solo verifica que tenga el tipo de puntero ID3D11Buffer.
  2. nullptr es poco probable que sea un problema, pero AFAIK no es la palabra clave estándar de C ++, por lo que probablemente el simple ''0'' sea mejor aquí. En realidad, es un estándar desde C ++ 11
  3. Lamentablemente, no proporciona su definición constantLightBufferDesc , que es un candidato para ser un problema: como ha indicado, puede haber un error de alineación del búfer: si su constantLightBufferDesc.BindFlags tiene el indicador D3D11_BIND_CONSTANT_BUFFER y constantLightBufferDesc.ByteWidth no es un múltiplo de 16 , la creación del búfer falla. Pero eso es solo una suposición. Puede tener cualquier otra discrepancia aquí, por lo tanto, puede hacer una adivinanza de forma infinecial.

Afortunadamente, hay otra forma de diagnóstico: si crea su dispositivo ID3D11 con el indicador D3D11_CREATE_DEVICE_DEBUG , en la ventana de salida de Visual Studio verá todas las advertencias y errores de acuerdo con D3D11. Por ejemplo, en caso de desalineación, verá:

D3D11 ERROR: ID3D11Device :: CreateBuffer: Las dimensiones no son válidas. Para ConstantBuffers, marcado con D3D11_BIND_CONSTANT_BUFFER BindFlag, ByteWidth (value = 10) debe ser un múltiplo de 16. ByteWidth también debe ser menor o igual que 65536 en el controlador actual. [STATE_CREATION ERROR # 66: CREATEBUFFER_INVALIDDIMENSIONS]

Por lo tanto, si CreateBuffer() falla debido a un tamaño de búfer incorrecto, existen varias maneras de manejarlo:

  1. Cambie el tamaño de sus estructuras: agregue miembros de relleno para que sizeof() se multiplique por 16.
  2. Declara tus estructuras como alineadas a 16 bits. AFAIK solo hay formas específicas de compilación para hacer esto: por ejemplo, #pragma pack for msvc.
  3. Asignar a ByteWidth no es un tamaño de estructura real, sino redondeado al siguiente múltiplo de 16: enlace

Feliz depuración! =)