DXBuffer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "DXBuffer.h"
  2. #include <iostream>
  3. #include "Logging.h"
  4. #ifdef WIN32
  5. # include <d3d11.h>
  6. # include <d3d12.h>
  7. # include "d3dx12.h"
  8. #endif
  9. using namespace Framework;
  10. // Contents of the DXBuffer class
  11. // Constructor
  12. // bind: The usage purpose of the buffer. Example: D3D11_BIND_INDEX_BUFFER,
  13. // D3D11_BIND_VERTEX_BUFFER. eLaen: Length of a single element in bytes
  14. DXBuffer::DXBuffer(int eLen)
  15. : ReferenceCounter()
  16. {
  17. data = 0;
  18. changed = 0;
  19. len = 0;
  20. elLen = eLen;
  21. }
  22. // Destructor
  23. DXBuffer::~DXBuffer() {}
  24. // Sets the changed flag so that data is re-copied on the next call to
  25. // 'copy'
  26. void DXBuffer::setChanged()
  27. {
  28. changed = 1;
  29. }
  30. // Changes the length of the buffer on the next call to 'copy'
  31. // laen: The length in bytes
  32. void DXBuffer::setLength(int len)
  33. {
  34. this->len = len;
  35. }
  36. // Sets what will be copied on the next call to 'copy'
  37. // data: A pointer to the data
  38. void DXBuffer::setData(void* data)
  39. {
  40. this->data = data;
  41. changed = 1;
  42. }
  43. // Returns the length of an element in bytes
  44. int DXBuffer::getElementLength() const
  45. {
  46. return elLen;
  47. }
  48. // Returns the number of elements in the buffer
  49. int DXBuffer::getElementCount() const
  50. {
  51. return len / elLen;
  52. }
  53. #ifdef WIN32
  54. // Contents of the DX11Buffer class
  55. // Constructor
  56. // eSize: The length of an element in bytes
  57. DX11Buffer::DX11Buffer(int eSize,
  58. ID3D11Device* device,
  59. ID3D11DeviceContext* context,
  60. int bindFlags,
  61. Critical& deviceLock)
  62. : DXBuffer(eSize),
  63. deviceLock(deviceLock)
  64. {
  65. buffer = 0;
  66. description = new D3D11_BUFFER_DESC();
  67. memset(description, 0, sizeof(description));
  68. description->Usage = D3D11_USAGE_DYNAMIC;
  69. description->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  70. description->BindFlags = bindFlags;
  71. this->device = device;
  72. this->context = context;
  73. }
  74. // Destructor
  75. DX11Buffer::~DX11Buffer()
  76. {
  77. if (buffer) buffer->Release();
  78. delete description;
  79. }
  80. // Copies the data into the buffer if it has changed
  81. // zRObj: The object used to communicate with the graphics card
  82. void DX11Buffer::copyToGPU(int byteCount)
  83. {
  84. if (!len) return;
  85. if (byteCount < 0) byteCount = len;
  86. if (description->ByteWidth < (unsigned)len)
  87. {
  88. if (buffer) buffer->Release();
  89. buffer = 0;
  90. }
  91. if (!buffer)
  92. {
  93. description->ByteWidth = len;
  94. deviceLock.lock();
  95. device->CreateBuffer(description, 0, &buffer);
  96. deviceLock.unlock();
  97. if (data) changed = 1;
  98. }
  99. if (changed)
  100. {
  101. HRESULT res;
  102. D3D11_MAPPED_SUBRESOURCE map;
  103. if ((description->Usage | D3D11_USAGE_DYNAMIC) == description->Usage)
  104. res = context->Map(
  105. buffer, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &map);
  106. else
  107. res = context->Map(buffer, 0, D3D11_MAP::D3D11_MAP_WRITE, 0, &map);
  108. if (res == S_OK)
  109. {
  110. memcpy(map.pData, data, byteCount);
  111. context->Unmap(buffer, 0);
  112. changed = 0;
  113. }
  114. else
  115. {
  116. Logging::error()
  117. << "Could not update buffer: " << std::hex << res << std::endl;
  118. }
  119. }
  120. }
  121. // Returns the buffer
  122. ID3D11Buffer* DX11Buffer::zBuffer() const
  123. {
  124. return buffer;
  125. }
  126. // Contents of the DXStructuredBuffer class
  127. // Constructor
  128. // eSize: The length of an element in bytes
  129. DX11StructuredBuffer::DX11StructuredBuffer(int eSize,
  130. ID3D11Device* device,
  131. ID3D11DeviceContext* context,
  132. Critical& deviceLock)
  133. : DX11Buffer(eSize,
  134. device,
  135. context,
  136. D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE,
  137. deviceLock)
  138. {
  139. description->MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
  140. description->StructureByteStride = eSize;
  141. description->Usage = D3D11_USAGE_DEFAULT;
  142. view = 0;
  143. }
  144. // Destructor
  145. DX11StructuredBuffer::~DX11StructuredBuffer()
  146. {
  147. if (view) view->Release();
  148. }
  149. // Copies the data into the buffer if it has changed
  150. // zRObj: The object used to communicate with the graphics card
  151. void DX11StructuredBuffer::copyToGPU(int byteCount)
  152. {
  153. ID3D11Buffer* old = buffer;
  154. DX11Buffer::copyToGPU(byteCount);
  155. if (buffer != old)
  156. {
  157. if (view) view->Release();
  158. D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
  159. desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
  160. desc.BufferEx.FirstElement = 0;
  161. desc.Format = DXGI_FORMAT_UNKNOWN;
  162. desc.BufferEx.NumElements
  163. = description->ByteWidth / description->StructureByteStride;
  164. deviceLock.lock();
  165. device->CreateShaderResourceView(buffer, &desc, &view);
  166. deviceLock.unlock();
  167. }
  168. }
  169. // Returns the used shader resource view
  170. DX11StructuredBuffer::operator ID3D11ShaderResourceView*() const
  171. {
  172. return view;
  173. }
  174. #endif