DXBuffer.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. deviceLock.lock();
  104. if ((description->Usage | D3D11_USAGE_DYNAMIC) == description->Usage)
  105. res = context->Map(
  106. buffer, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &map);
  107. else
  108. res = context->Map(buffer, 0, D3D11_MAP::D3D11_MAP_WRITE, 0, &map);
  109. deviceLock.unlock();
  110. if (res == S_OK)
  111. {
  112. memcpy(map.pData, data, byteCount);
  113. deviceLock.lock();
  114. context->Unmap(buffer, 0);
  115. deviceLock.unlock();
  116. changed = 0;
  117. }
  118. else
  119. {
  120. Logging::error()
  121. << "Could not update buffer: " << std::hex << res << std::endl;
  122. }
  123. }
  124. }
  125. // Returns the buffer
  126. ID3D11Buffer* DX11Buffer::zBuffer() const
  127. {
  128. return buffer;
  129. }
  130. // Contents of the DXStructuredBuffer class
  131. // Constructor
  132. // eSize: The length of an element in bytes
  133. DX11StructuredBuffer::DX11StructuredBuffer(int eSize,
  134. ID3D11Device* device,
  135. ID3D11DeviceContext* context,
  136. Critical& deviceLock)
  137. : DX11Buffer(eSize,
  138. device,
  139. context,
  140. D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE,
  141. deviceLock)
  142. {
  143. description->MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
  144. description->StructureByteStride = eSize;
  145. description->Usage = D3D11_USAGE_DEFAULT;
  146. view = 0;
  147. }
  148. // Destructor
  149. DX11StructuredBuffer::~DX11StructuredBuffer()
  150. {
  151. if (view) view->Release();
  152. }
  153. // Copies the data into the buffer if it has changed
  154. // zRObj: The object used to communicate with the graphics card
  155. void DX11StructuredBuffer::copyToGPU(int byteCount)
  156. {
  157. ID3D11Buffer* old = buffer;
  158. DX11Buffer::copyToGPU(byteCount);
  159. if (buffer != old)
  160. {
  161. if (view) view->Release();
  162. D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
  163. desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
  164. desc.BufferEx.FirstElement = 0;
  165. desc.Format = DXGI_FORMAT_UNKNOWN;
  166. desc.BufferEx.NumElements
  167. = description->ByteWidth / description->StructureByteStride;
  168. deviceLock.lock();
  169. device->CreateShaderResourceView(buffer, &desc, &view);
  170. deviceLock.unlock();
  171. }
  172. }
  173. // Returns the used shader resource view
  174. DX11StructuredBuffer::operator ID3D11ShaderResourceView*() const
  175. {
  176. return view;
  177. }
  178. #endif