Код: Выделить всё
void RenderShadowMaps::Render(D3D12_GPU_VIRTUAL_ADDRESS lightGPUVirtualAdress, ID3D12GraphicsCommandList* commandList)
{
commandList->SetGraphicsRootSignature(m_rootSignature);
commandList->SetPipelineState(m_PSO);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
commandList->SetGraphicsRootConstantBufferView(0, LightConstantBufferSingleton::instance()->getLightCountUploadHeap()->GetGPUVirtualAddress());
commandList->SetGraphicsRootConstantBufferView(1, LightConstantBufferSingleton::instance()->getMainUploadHeap()->GetGPUVirtualAddress());
commandList->SetGraphicsRootConstantBufferView(2, lightGPUVirtualAdress);
//...
}
< /code>
строка, вызывающая ошибку. У меня есть массив огней, и мне нужно получить доступ к светам индивидуально: < /p>
commandList->SetGraphicsRootConstantBufferView(2, lightGPUVirtualAdress);
Код: Выделить всё
std::vector LightConstantBuffer::getMainLightGPUVirtualAddresses(const Scene::BaseScene& scene)
{
const auto& lights = scene.getLights();
_ASSERT(lights.size());
std::vector ret;
ret.reserve(lights.size());
for (uint32_t i = 0u; i < lights.size(); ++i)
{
ret.push_back(m_mainLightCBUploadHeap->GetGPUVirtualAddress() + i * sizeof(DX12Light));
}
return ret;
}
Код: Выделить всё
__declspec(align(16)) struct DX12Light
{
DirectX::XMFLOAT4 position;
DirectX::XMFLOAT4 direction;
DirectX::XMFLOAT4 color;
DirectX::XMFLOAT4X4 transform1;
DirectX::XMFLOAT4X4 transform2;
FLOAT range;
INT type;
INT linearIdx;
};
< /code>
Буфер света: < /p>
struct LightMainCB
{
DX12Light lights[Graphics::Light::MaxLightsPerScene];
};
< /code>
so hlsl side (постоянный буфер на данный момент, возможно, переключится на структурированный буфер в будущем): < /p>
struct DX12Light
{
float4 position;
float4 direction;
float4 color;
float4x4 transform1;
float4x4 transform2;
float range;
int type;
int linearIdx;
};
cbuffer LightCountCB : register(b0)
{
int NbLights;
};
cbuffer LightMainCB : register(b1)
{
DX12Light Lights[MAX_LIGHTS];
};
< /code>
Я разделил количество света и освещение на 2 буфера, думая, что он решит ошибку, но это не так. HRESULT hr = D3D12Device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(MainLightCBAlignedSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_mainLightCBUploadHeap));
//#define _ALIGN_SIZE(x) (sizeof(x) + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)
//const nbUint32 MainLightCBAlignedSize = _ALIGN_SIZE(LightMainCB);
_ASSERT(SUCCEEDED(hr));
m_mainLightCBUploadHeap->SetName(L"Main lights constant buffer upload heap");
hr = m_mainLightCBUploadHeap->Map(0, &ReadRangeGPUOnly, reinterpret_cast(&m_mainLightCBGPUAddress));
_ASSERT(SUCCEEDED(hr));
Код: Выделить всё
struct DX12Light
{
DirectX::XMFLOAT4 position;
DirectX::XMFLOAT4 direction;
DirectX::XMFLOAT4 color;
DirectX::XMFLOAT4X4 transform1;
DirectX::XMFLOAT4X4 transform2;
FLOAT range;
INT type;
INT linearIdx;
INT padding[17];
};
Код: Выделить всё
void LightConstantBuffer::updateLight(const Scene::BaseScene& scene, const EntityIdentifier& lightId, ID3D12GraphicsCommandList* commandList)
{
const EntityIdentifierArray& lights = scene.getLights();
int lightLinearIdx = 0;
for (const auto& entityId : lights)
{
if (entityId == lightId)
{
updateLightEntry(scene, lightId, lightLinearIdx);// m_mainLightTransientBUffer.lights[lightLinearIdx] is updated here.
memcpy(m_mainLightCBGPUAddress + lightLinearIdx * sizeof(DX12Light), &m_mainLightTransientBUffer.lights[lightLinearIdx], sizeof(DX12Light));
break;
}
++lightLinearIdx;
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... ligned-how
Мобильная версия