Tuesday, 14 October 2014

Cross-API Rendering: An Aside

Just as an aside, an insight into why I need to wrapper-up some perfectly serviceable rendering API's. Suppose I want to create a structured buffer to be used in a compute shader, for both read-only and read-write usage.
Here's how I want to declare it:
simul::crossplatform::StructuredBuffer<vec2> tempBuffer;

Here's how I'd like to initialize it:
tempBuffer.RestoreDeviceObjects(renderPlatform,num_elements,true);

- where passing "true" in the third element means "make it writeable by compute shaders".

Now in DirectX 11, I'd declare it like this:
ID3D11Buffer *pBuffer_Tmp;
ID3D11UnorderedAccessView *pUAV_Tmp;
ID3D11ShaderResourceView *pSRV_Tmp;

And initialize it like so (get ready):

  D3D11_BUFFER_DESC buf_desc;
  buf_desc.ByteWidth = sizeof(float) * 2 * num_elements;
  buf_desc.Usage = D3D11_USAGE_DEFAULT;
  buf_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
  buf_desc.CPUAccessFlags = 0;
  buf_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
  buf_desc.StructureByteStride = sizeof(float) * 2;

  renderPlatform->AsD3D11Device()->CreateBuffer(&buf_desc, NULL, &pBuffer_Tmp);
  assert(pBuffer_Tmp);

  // Temp undordered access view
  D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc;
  uav_desc.Format = DXGI_FORMAT_UNKNOWN;
  uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
  uav_desc.Buffer.FirstElement = 0;
  uav_desc.Buffer.NumElements =num_elements;
  uav_desc.Buffer.Flags = 0;

  renderPlatform->AsD3D11Device()->CreateUnorderedAccessView(pBuffer_Tmp, &uav_desc, &pUAV_Tmp);

  // Temp shader resource view
  D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
  srv_desc.Format = DXGI_FORMAT_UNKNOWN;
  srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
  srv_desc.Buffer.FirstElement = 0;
  srv_desc.Buffer.NumElements =num_elements;

  renderPlatform->AsD3D11Device()->CreateShaderResourceView(pBuffer_Tmp, &srv_desc, &pSRV_Tmp);
So, that was a bit longer; with a lot of redundant "match-up" values - you can't create an unordered access view of pBuffer_Tmp unless it was created with BindFlags containing D3D11_BIND_UNORDERED_ACCESS, for example. Now I know you can do clever things like create a view into a specific part of a buffer, and so on, but let's at least make a neat interface for the 99% case.