Dynamic resource view equivalent in OpenGL/DX11

Started by
3 comments, last by zhangdoa 4 years, 11 months ago

Hello everyone here in GameDev forums,

It's my first post and I'm very happy to participate in the discussion here, thanks for everyone!

My question is, is there any workaround that we could implement something in DX11 that similar to the DX12's CBV with the offset, and/or something in OpenGL similar to the dynamic UBO descriptor in Vulkan?

My initial purpose is about to achieve a unified per-object resource updating design across different APIs in my engine. I've gathered all the per-object resource updating to a few of coherent memory write operations in DX12 and Vulkan rendering backends, and later record all the descriptor binding commands with the per-object offset.

DX12 example code:


WriteMemoryFromCPUSide();
for(auto object : objects)
{
  offset = object->offset;
  commandListPtr->SetGraphicsRootConstantBufferView(startSlot, constantBufferPtr->GetGPUVirtualAddress() + offset * elementSize);
  // record drawcall
}

Vulkan example code:


WriteMemoryFromCPUSide();
for(auto object : objects)
{
  offset = object->offset;
  vkCmdBindDescriptorSets(commandBufferPtr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayoutPtr, firstSet, setCount, descriptorSetPtr, dynamicOffsetCount, offset);
  // record drawcall
}

 

I have an idea to record the per-object offset as the index/UUID, then use explicit UBO/SSBO array in OpenGL and StructuredBuffer in DX11, but still, I need to submit the index to GPU memory at a certain moment.

Hope everyone has a good day!

Advertisement

D3D11.1 (initally added for Windows 8 and back-ported to Windows 7) includes a feature called "partial constant buffer updates", which is functionally similar to what you can do in D3D12 and Vulkan. Basically it lets you bind a constant buffer + offset, which lets you sub-allocate within a very large constant buffer however you see fit. It's still not as nice as binding with GPU virtual address, but it is what it is. You can read through this article from Nvidia for all of the details. We used it in the D3D11 version of our engine at work whenever the driver supported it, and it definitely gave us improved and more stable CPU times. 

Unfortunately I can't help you with OpenGL, since I am very far from an expert on that API.

12 hours ago, MJP said:

D3D11.1 (initally added for Windows 8 and back-ported to Windows 7) includes a feature called "partial constant buffer updates", which is functionally similar to what you can do in D3D12 and Vulkan. Basically it lets you bind a constant buffer + offset, which lets you sub-allocate within a very large constant buffer however you see fit. It's still not as nice as binding with GPU virtual address, but it is what it is. You can read through this article from Nvidia for all of the details. We used it in the D3D11 version of our engine at work whenever the driver supported it, and it definitely gave us improved and more stable CPU times. 

Unfortunately I can't help you with OpenGL, since I am very far from an expert on that API.

Thanks for help MJP!

For anyone who occurred this problem, here is the example code about how to bind partial ConstantBuffer in DX11:


WriteMemoryFromCPUSide();
for(auto object : objects)
{ 
  offset = object->offset;
  // Each shader constant is 16 bytes (4*32-bit components), and shader needs to access the constant with a count of 16, so we must provide the l_constantCount as the multiple of 16.
  // Assume constantBufferElementSize is the multiple of 16 (bytes) * 16 (counts) = 256 bytes, thus the l_constantCount would always be satisfied with the count-of-16 requirement, so the total constant count is
  unsigned int l_constantCount = constantBufferElementSize / 16;
  unsigned int l_firstConstant = offset * l_constantCount;
  deviceContext->VSSetConstantBuffers1(startSlot, 1, &ConstantBufferPtr, &l_firstConstant, &l_constantCount);
  // issue drawcall
}

 

The OpenGL solution:


WriteMemoryFromCPUSide();
for(auto object : objects)
{ 
  offset = object->offset;
  // The 3rd parameter should be aligned to GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, and the 4th parameter should be at least GL_UNIFORM_BLOCK_SIZE_DATA 
  glBindBufferRange(GL_UNIFORM_BUFFER, uniformBlockBindingPoint, UBO, offset * UBOElementSize, UBOElementSize);
  // issue drawcall
}

 

This topic is closed to new replies.

Advertisement