DXBuffer.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. if (this->len != len)
  35. {
  36. this->len = len;
  37. changed = 1;
  38. }
  39. }
  40. // Sets what will be copied on the next call to 'copy'
  41. // data: A pointer to the data
  42. void DXBuffer::setData(void* data)
  43. {
  44. if (this->data != data)
  45. {
  46. this->data = data;
  47. changed = 1;
  48. }
  49. }
  50. // Returns the length of an element in bytes
  51. int DXBuffer::getElementLength() const
  52. {
  53. return elLen;
  54. }
  55. // Returns the number of elements in the buffer
  56. int DXBuffer::getElementCount() const
  57. {
  58. return len / elLen;
  59. }
  60. #ifdef WIN32
  61. // Contents of the DX11Buffer class
  62. // Constructor
  63. // eSize: The length of an element in bytes
  64. DX11Buffer::DX11Buffer(int eSize,
  65. ID3D11Device* device,
  66. ID3D11DeviceContext* context,
  67. int bindFlags,
  68. Critical& deviceLock)
  69. : DXBuffer(eSize),
  70. deviceLock(deviceLock)
  71. {
  72. buffer = 0;
  73. description = new D3D11_BUFFER_DESC();
  74. memset(description, 0, sizeof(description));
  75. description->Usage = D3D11_USAGE_DYNAMIC;
  76. description->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  77. description->BindFlags = bindFlags;
  78. this->device = device;
  79. this->context = context;
  80. }
  81. // Destructor
  82. DX11Buffer::~DX11Buffer()
  83. {
  84. if (buffer) buffer->Release();
  85. delete description;
  86. }
  87. // Copies the data into the buffer if it has changed
  88. // zRObj: The object used to communicate with the graphics card
  89. void DX11Buffer::copyToGPU(int byteCount)
  90. {
  91. if (!len) return;
  92. if (byteCount < 0) byteCount = len;
  93. if (description->ByteWidth < (unsigned)len)
  94. {
  95. if (buffer) buffer->Release();
  96. buffer = 0;
  97. }
  98. if (!buffer)
  99. {
  100. description->ByteWidth = len;
  101. deviceLock.lock();
  102. device->CreateBuffer(description, 0, &buffer);
  103. deviceLock.unlock();
  104. if (data) changed = 1;
  105. }
  106. if (changed)
  107. {
  108. HRESULT res;
  109. D3D11_MAPPED_SUBRESOURCE map;
  110. deviceLock.lock();
  111. if ((description->Usage | D3D11_USAGE_DYNAMIC) == description->Usage)
  112. res = context->Map(
  113. buffer, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &map);
  114. else
  115. res = context->Map(buffer, 0, D3D11_MAP::D3D11_MAP_WRITE, 0, &map);
  116. deviceLock.unlock();
  117. if (res == S_OK)
  118. {
  119. memcpy(map.pData, data, byteCount);
  120. deviceLock.lock();
  121. context->Unmap(buffer, 0);
  122. deviceLock.unlock();
  123. changed = 0;
  124. }
  125. else
  126. {
  127. Logging::error()
  128. << "Could not update buffer: " << std::hex << res << std::endl;
  129. }
  130. }
  131. }
  132. // Returns the buffer
  133. ID3D11Buffer* DX11Buffer::zBuffer() const
  134. {
  135. return buffer;
  136. }
  137. // Contents of the DXStructuredBuffer class
  138. // Constructor
  139. // eSize: The length of an element in bytes
  140. DX11StructuredBuffer::DX11StructuredBuffer(int eSize,
  141. ID3D11Device* device,
  142. ID3D11DeviceContext* context,
  143. Critical& deviceLock)
  144. : DX11Buffer(eSize,
  145. device,
  146. context,
  147. D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE,
  148. deviceLock)
  149. {
  150. description->MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
  151. description->StructureByteStride = eSize;
  152. description->Usage = D3D11_USAGE_DEFAULT;
  153. view = 0;
  154. }
  155. // Destructor
  156. DX11StructuredBuffer::~DX11StructuredBuffer()
  157. {
  158. if (view) view->Release();
  159. }
  160. // Copies the data into the buffer if it has changed
  161. // zRObj: The object used to communicate with the graphics card
  162. void DX11StructuredBuffer::copyToGPU(int byteCount)
  163. {
  164. ID3D11Buffer* old = buffer;
  165. DX11Buffer::copyToGPU(byteCount);
  166. if (buffer != old)
  167. {
  168. if (view) view->Release();
  169. D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
  170. desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
  171. desc.BufferEx.FirstElement = 0;
  172. desc.Format = DXGI_FORMAT_UNKNOWN;
  173. desc.BufferEx.NumElements
  174. = description->ByteWidth / description->StructureByteStride;
  175. deviceLock.lock();
  176. device->CreateShaderResourceView(buffer, &desc, &view);
  177. deviceLock.unlock();
  178. }
  179. }
  180. // Returns the used shader resource view
  181. DX11StructuredBuffer::operator ID3D11ShaderResourceView*() const
  182. {
  183. return view;
  184. }
  185. #endif