BsD3D11RenderAPI.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsD3D11RenderAPI.h"
  4. #include "BsD3D11DriverList.h"
  5. #include "BsD3D11Driver.h"
  6. #include "BsD3D11Device.h"
  7. #include "BsD3D11TextureManager.h"
  8. #include "BsD3D11Texture.h"
  9. #include "BsD3D11HardwareBufferManager.h"
  10. #include "BsD3D11RenderWindowManager.h"
  11. #include "BsD3D11HLSLProgramFactory.h"
  12. #include "BsD3D11BlendState.h"
  13. #include "BsD3D11RasterizerState.h"
  14. #include "BsD3D11DepthStencilState.h"
  15. #include "BsD3D11SamplerState.h"
  16. #include "BsD3D11GpuProgram.h"
  17. #include "BsD3D11Mappings.h"
  18. #include "BsD3D11VertexBuffer.h"
  19. #include "BsD3D11IndexBuffer.h"
  20. #include "BsD3D11RenderStateManager.h"
  21. #include "BsD3D11GpuParamBlockBuffer.h"
  22. #include "BsD3D11InputLayoutManager.h"
  23. #include "BsD3D11TextureView.h"
  24. #include "BsD3D11RenderUtility.h"
  25. #include "BsGpuParams.h"
  26. #include "BsCoreThread.h"
  27. #include "BsD3D11QueryManager.h"
  28. #include "BsDebug.h"
  29. #include "BsException.h"
  30. #include "BsRenderStats.h"
  31. #include "BsGpuParamDesc.h"
  32. #include "BsD3D11GpuBuffer.h"
  33. #include "BsD3D11CommandBuffer.h"
  34. namespace bs
  35. {
  36. D3D11RenderAPI::D3D11RenderAPI()
  37. : mDXGIFactory(nullptr), mDevice(nullptr), mDriverList(nullptr), mActiveD3DDriver(nullptr)
  38. , mFeatureLevel(D3D_FEATURE_LEVEL_11_0), mHLSLFactory(nullptr), mIAManager(nullptr), mPSUAVsBound(false)
  39. , mCSUAVsBound(false), mStencilRef(0), mActiveDrawOp(DOT_TRIANGLE_LIST), mViewportNorm(0.0f, 0.0f, 1.0f, 1.0f)
  40. { }
  41. D3D11RenderAPI::~D3D11RenderAPI()
  42. {
  43. }
  44. const StringID& D3D11RenderAPI::getName() const
  45. {
  46. static StringID strName("D3D11RenderAPI");
  47. return strName;
  48. }
  49. const String& D3D11RenderAPI::getShadingLanguageName() const
  50. {
  51. static String strName("hlsl");
  52. return strName;
  53. }
  54. void D3D11RenderAPI::initialize()
  55. {
  56. THROW_IF_NOT_CORE_THREAD;
  57. HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&mDXGIFactory);
  58. if(FAILED(hr))
  59. BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 DXGIFactory");
  60. mDriverList = bs_new<D3D11DriverList>(mDXGIFactory);
  61. mActiveD3DDriver = mDriverList->item(0); // TODO: Always get first driver, for now
  62. mVideoModeInfo = mActiveD3DDriver->getVideoModeInfo();
  63. IDXGIAdapter* selectedAdapter = mActiveD3DDriver->getDeviceAdapter();
  64. D3D_FEATURE_LEVEL requestedLevels[] = {
  65. D3D_FEATURE_LEVEL_11_0,
  66. D3D_FEATURE_LEVEL_10_1,
  67. D3D_FEATURE_LEVEL_10_0,
  68. D3D_FEATURE_LEVEL_9_3,
  69. D3D_FEATURE_LEVEL_9_2,
  70. D3D_FEATURE_LEVEL_9_1
  71. };
  72. UINT32 numRequestedLevel = sizeof(requestedLevels) / sizeof(requestedLevels[0]);
  73. UINT32 deviceFlags = 0;
  74. #if BS_DEBUG_MODE
  75. deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
  76. #endif
  77. ID3D11Device* device;
  78. hr = D3D11CreateDevice(selectedAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, deviceFlags,
  79. requestedLevels, numRequestedLevel, D3D11_SDK_VERSION, &device, &mFeatureLevel, nullptr);
  80. if(FAILED(hr))
  81. BS_EXCEPT(RenderingAPIException, "Failed to create Direct3D11 object. D3D11CreateDeviceN returned this error code: " + toString(hr));
  82. mDevice = bs_new<D3D11Device>(device);
  83. // Create the texture manager for use by others
  84. TextureManager::startUp<D3D11TextureManager>();
  85. TextureCoreManager::startUp<D3D11TextureCoreManager>();
  86. // Create hardware buffer manager
  87. HardwareBufferManager::startUp();
  88. HardwareBufferCoreManager::startUp<D3D11HardwareBufferCoreManager>(std::ref(*mDevice));
  89. // Create render window manager
  90. RenderWindowManager::startUp<D3D11RenderWindowManager>(this);
  91. RenderWindowCoreManager::startUp<D3D11RenderWindowCoreManager>(this);
  92. // Create & register HLSL factory
  93. mHLSLFactory = bs_new<D3D11HLSLProgramFactory>();
  94. // Create render state manager
  95. RenderStateCoreManager::startUp<D3D11RenderStateCoreManager>();
  96. mNumDevices = 1;
  97. mCurrentCapabilities = bs_newN<RenderAPICapabilities>(mNumDevices);
  98. initCapabilites(selectedAdapter, mCurrentCapabilities[0]);
  99. GpuProgramCoreManager::instance().addFactory(mHLSLFactory);
  100. mIAManager = bs_new<D3D11InputLayoutManager>();
  101. RenderAPICore::initialize();
  102. }
  103. void D3D11RenderAPI::initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow)
  104. {
  105. D3D11RenderUtility::startUp(mDevice);
  106. QueryManager::startUp<D3D11QueryManager>();
  107. RenderAPICore::initializeWithWindow(primaryWindow);
  108. }
  109. void D3D11RenderAPI::destroyCore()
  110. {
  111. THROW_IF_NOT_CORE_THREAD;
  112. for (auto& boundUAV : mBoundUAVs)
  113. {
  114. if (boundUAV.second != nullptr)
  115. boundUAV.first->releaseView(boundUAV.second);
  116. boundUAV.second = nullptr;
  117. boundUAV.first = nullptr;
  118. }
  119. // Ensure that all GPU commands finish executing before shutting down the device. If we don't do this a crash
  120. // on shutdown may occurr as the driver is still executing the commands, and we unload this library.
  121. mDevice->getImmediateContext()->Flush();
  122. SPtr<EventQuery> query = EventQuery::create();
  123. query->begin();
  124. while(!query->isReady())
  125. {
  126. // Spin
  127. }
  128. query = nullptr;
  129. QueryManager::shutDown();
  130. D3D11RenderUtility::shutDown();
  131. if(mIAManager != nullptr)
  132. {
  133. bs_delete(mIAManager);
  134. mIAManager = nullptr;
  135. }
  136. if(mHLSLFactory != nullptr)
  137. {
  138. bs_delete(mHLSLFactory);
  139. mHLSLFactory = nullptr;
  140. }
  141. mActiveVertexDeclaration = nullptr;
  142. mActiveVertexShader = nullptr;
  143. mActiveRenderTarget = nullptr;
  144. mActiveDepthStencilState = nullptr;
  145. RenderStateCoreManager::shutDown();
  146. RenderWindowCoreManager::shutDown();
  147. RenderWindowManager::shutDown();
  148. HardwareBufferCoreManager::shutDown();
  149. HardwareBufferManager::shutDown();
  150. TextureCoreManager::shutDown();
  151. TextureManager::shutDown();
  152. SAFE_RELEASE(mDXGIFactory);
  153. if(mDevice != nullptr)
  154. {
  155. bs_delete(mDevice);
  156. mDevice = nullptr;
  157. }
  158. if(mDriverList != nullptr)
  159. {
  160. bs_delete(mDriverList);
  161. mDriverList = nullptr;
  162. }
  163. mActiveD3DDriver = nullptr;
  164. RenderAPICore::destroyCore();
  165. }
  166. void D3D11RenderAPI::setGraphicsPipeline(const SPtr<GraphicsPipelineStateCore>& pipelineState,
  167. const SPtr<CommandBuffer>& commandBuffer)
  168. {
  169. auto executeRef = [&](const SPtr<GraphicsPipelineStateCore>& pipelineState)
  170. {
  171. THROW_IF_NOT_CORE_THREAD;
  172. D3D11BlendStateCore* d3d11BlendState;
  173. D3D11RasterizerStateCore* d3d11RasterizerState;
  174. D3D11GpuFragmentProgramCore* d3d11FragmentProgram;
  175. D3D11GpuGeometryProgramCore* d3d11GeometryProgram;
  176. D3D11GpuDomainProgramCore* d3d11DomainProgram;
  177. D3D11GpuHullProgramCore* d3d11HullProgram;
  178. if(pipelineState != nullptr)
  179. {
  180. d3d11BlendState = static_cast<D3D11BlendStateCore*>(pipelineState->getBlendState().get());
  181. d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(pipelineState->getRasterizerState().get());
  182. mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(pipelineState->getDepthStencilState());
  183. mActiveVertexShader = std::static_pointer_cast<D3D11GpuVertexProgramCore>(pipelineState->getVertexProgram());
  184. d3d11FragmentProgram = static_cast<D3D11GpuFragmentProgramCore*>(pipelineState->getFragmentProgram().get());
  185. d3d11GeometryProgram = static_cast<D3D11GpuGeometryProgramCore*>(pipelineState->getGeometryProgram().get());
  186. d3d11DomainProgram = static_cast<D3D11GpuDomainProgramCore*>(pipelineState->getDomainProgram().get());
  187. d3d11HullProgram = static_cast<D3D11GpuHullProgramCore*>(pipelineState->getHullProgram().get());
  188. if (d3d11BlendState == nullptr)
  189. d3d11BlendState = static_cast<D3D11BlendStateCore*>(BlendStateCore::getDefault().get());
  190. if (d3d11RasterizerState == nullptr)
  191. d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(RasterizerStateCore::getDefault().get());
  192. if (mActiveDepthStencilState == nullptr)
  193. mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(DepthStencilStateCore::getDefault());
  194. }
  195. else
  196. {
  197. d3d11BlendState = static_cast<D3D11BlendStateCore*>(BlendStateCore::getDefault().get());
  198. d3d11RasterizerState = static_cast<D3D11RasterizerStateCore*>(RasterizerStateCore::getDefault().get());
  199. mActiveDepthStencilState = std::static_pointer_cast<D3D11DepthStencilStateCore>(DepthStencilStateCore::getDefault());
  200. mActiveVertexShader = nullptr;
  201. d3d11FragmentProgram = nullptr;
  202. d3d11GeometryProgram = nullptr;
  203. d3d11DomainProgram = nullptr;
  204. d3d11HullProgram = nullptr;
  205. }
  206. ID3D11DeviceContext* d3d11Context = mDevice->getImmediateContext();
  207. d3d11Context->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
  208. d3d11Context->RSSetState(d3d11RasterizerState->getInternal());
  209. d3d11Context->OMSetDepthStencilState(mActiveDepthStencilState->getInternal(), mStencilRef);
  210. if (mActiveVertexShader != nullptr)
  211. {
  212. D3D11GpuVertexProgramCore* vertexProgram = static_cast<D3D11GpuVertexProgramCore*>(mActiveVertexShader.get());
  213. d3d11Context->VSSetShader(vertexProgram->getVertexShader(), nullptr, 0);
  214. }
  215. else
  216. d3d11Context->VSSetShader(nullptr, nullptr, 0);
  217. if(d3d11FragmentProgram != nullptr)
  218. d3d11Context->PSSetShader(d3d11FragmentProgram->getPixelShader(), nullptr, 0);
  219. else
  220. d3d11Context->PSSetShader(nullptr, nullptr, 0);
  221. if (d3d11GeometryProgram != nullptr)
  222. d3d11Context->GSSetShader(d3d11GeometryProgram->getGeometryShader(), nullptr, 0);
  223. else
  224. d3d11Context->GSSetShader(nullptr, nullptr, 0);
  225. if (d3d11DomainProgram != nullptr)
  226. d3d11Context->DSSetShader(d3d11DomainProgram->getDomainShader(), nullptr, 0);
  227. else
  228. d3d11Context->DSSetShader(nullptr, nullptr, 0);
  229. if (d3d11HullProgram != nullptr)
  230. d3d11Context->HSSetShader(d3d11HullProgram->getHullShader(), nullptr, 0);
  231. else
  232. d3d11Context->HSSetShader(nullptr, nullptr, 0);
  233. };
  234. if (commandBuffer == nullptr)
  235. executeRef(pipelineState);
  236. else
  237. {
  238. auto execute = [=]() { executeRef(pipelineState); };
  239. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  240. cb->queueCommand(execute);
  241. }
  242. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  243. }
  244. void D3D11RenderAPI::setComputePipeline(const SPtr<ComputePipelineStateCore>& pipelineState,
  245. const SPtr<CommandBuffer>& commandBuffer)
  246. {
  247. auto executeRef = [&](const SPtr<ComputePipelineStateCore>& pipelineState)
  248. {
  249. THROW_IF_NOT_CORE_THREAD;
  250. SPtr<GpuProgramCore> program;
  251. if (pipelineState != nullptr)
  252. program = pipelineState->getProgram();
  253. if (program != nullptr && program->getProperties().getType() == GPT_COMPUTE_PROGRAM)
  254. {
  255. D3D11GpuComputeProgramCore *d3d11ComputeProgram = static_cast<D3D11GpuComputeProgramCore*>(program.get());
  256. mDevice->getImmediateContext()->CSSetShader(d3d11ComputeProgram->getComputeShader(), nullptr, 0);
  257. }
  258. else
  259. mDevice->getImmediateContext()->CSSetShader(nullptr, nullptr, 0);
  260. };
  261. if (commandBuffer == nullptr)
  262. executeRef(pipelineState);
  263. else
  264. {
  265. auto execute = [=]() { executeRef(pipelineState); };
  266. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  267. cb->queueCommand(execute);
  268. }
  269. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  270. }
  271. void D3D11RenderAPI::setGpuParams(const SPtr<GpuParamsCore>& gpuParams, const SPtr<CommandBuffer>& commandBuffer)
  272. {
  273. auto executeRef = [&](const SPtr<GpuParamsCore>& gpuParams)
  274. {
  275. THROW_IF_NOT_CORE_THREAD;
  276. ID3D11DeviceContext* context = mDevice->getImmediateContext();
  277. // Clear any previously bound UAVs (otherwise shaders attempting to read resources viewed by those view will
  278. // be unable to)
  279. if (mPSUAVsBound || mCSUAVsBound)
  280. {
  281. ID3D11UnorderedAccessView* emptyUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
  282. bs_zero_out(emptyUAVs);
  283. if(mPSUAVsBound)
  284. {
  285. context->OMSetRenderTargetsAndUnorderedAccessViews(
  286. D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 0,
  287. D3D11_PS_CS_UAV_REGISTER_COUNT, emptyUAVs, nullptr);
  288. mPSUAVsBound = false;
  289. }
  290. if(mCSUAVsBound)
  291. {
  292. context->CSSetUnorderedAccessViews(0, D3D11_PS_CS_UAV_REGISTER_COUNT, emptyUAVs, nullptr);
  293. mCSUAVsBound = false;
  294. }
  295. }
  296. bs_frame_mark();
  297. {
  298. FrameVector<ID3D11ShaderResourceView*> srvs(8);
  299. FrameVector<ID3D11UnorderedAccessView*> uavs(8);
  300. FrameVector<ID3D11Buffer*> constBuffers(8);
  301. FrameVector<ID3D11SamplerState*> samplers(8);
  302. auto populateViews = [&](GpuProgramType type)
  303. {
  304. srvs.clear();
  305. uavs.clear();
  306. constBuffers.clear();
  307. samplers.clear();
  308. SPtr<GpuParamDesc> paramDesc = gpuParams->getParamDesc(type);
  309. if (paramDesc == nullptr)
  310. return;
  311. for (auto iter = paramDesc->textures.begin(); iter != paramDesc->textures.end(); ++iter)
  312. {
  313. UINT32 slot = iter->second.slot;
  314. SPtr<TextureCore> texture = gpuParams->getTexture(iter->second.set, slot);
  315. while (slot >= (UINT32)srvs.size())
  316. srvs.push_back(nullptr);
  317. if (texture != nullptr)
  318. {
  319. D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texture.get());
  320. srvs[slot] = d3d11Texture->getSRV();
  321. }
  322. }
  323. for (auto iter = paramDesc->buffers.begin(); iter != paramDesc->buffers.end(); ++iter)
  324. {
  325. UINT32 slot = iter->second.slot;
  326. SPtr<GpuBufferCore> buffer = gpuParams->getBuffer(iter->second.set, slot);
  327. bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
  328. iter->second.type != GPOT_STRUCTURED_BUFFER;
  329. if (!isLoadStore)
  330. {
  331. while (slot >= (UINT32)srvs.size())
  332. srvs.push_back(nullptr);
  333. if (buffer != nullptr)
  334. {
  335. D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
  336. srvs[slot] = d3d11buffer->getSRV();
  337. }
  338. }
  339. else
  340. {
  341. while (slot >= (UINT32)uavs.size())
  342. uavs.push_back(nullptr);
  343. if (buffer != nullptr)
  344. {
  345. D3D11GpuBufferCore* d3d11buffer = static_cast<D3D11GpuBufferCore*>(buffer.get());
  346. uavs[slot] = d3d11buffer->getUAV();
  347. }
  348. }
  349. }
  350. for (auto iter = paramDesc->loadStoreTextures.begin(); iter != paramDesc->loadStoreTextures.end(); ++iter)
  351. {
  352. UINT32 slot = iter->second.slot;
  353. SPtr<TextureCore> texture = gpuParams->getLoadStoreTexture(iter->second.set, slot);
  354. const TextureSurface& surface = gpuParams->getLoadStoreSurface(iter->second.set, slot);
  355. while (slot >= (UINT32)uavs.size())
  356. uavs.push_back(nullptr);
  357. if (texture != nullptr)
  358. {
  359. SPtr<TextureView> texView = TextureCore::requestView(texture, surface.mipLevel, 1,
  360. surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
  361. D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
  362. uavs[slot] = d3d11texView->getUAV();
  363. if (mBoundUAVs[slot].second != nullptr)
  364. mBoundUAVs[slot].first->releaseView(mBoundUAVs[slot].second);
  365. mBoundUAVs[slot] = std::make_pair(texture, texView);
  366. }
  367. else
  368. {
  369. uavs[slot] = nullptr;
  370. if (mBoundUAVs[slot].second != nullptr)
  371. mBoundUAVs[slot].first->releaseView(mBoundUAVs[slot].second);
  372. mBoundUAVs[slot] = std::pair<SPtr<TextureCore>, SPtr<TextureView>>();
  373. }
  374. }
  375. for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
  376. {
  377. UINT32 slot = iter->second.slot;
  378. SPtr<SamplerStateCore> samplerState = gpuParams->getSamplerState(iter->second.set, slot);
  379. while (slot >= (UINT32)samplers.size())
  380. samplers.push_back(nullptr);
  381. if (samplerState == nullptr)
  382. samplerState = SamplerStateCore::getDefault();
  383. D3D11SamplerStateCore* d3d11SamplerState =
  384. static_cast<D3D11SamplerStateCore*>(const_cast<SamplerStateCore*>(samplerState.get()));
  385. samplers[slot] = d3d11SamplerState->getInternal();
  386. }
  387. for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
  388. {
  389. UINT32 slot = iter->second.slot;
  390. SPtr<GpuParamBlockBufferCore> buffer = gpuParams->getParamBlockBuffer(iter->second.set, slot);
  391. while (slot >= (UINT32)constBuffers.size())
  392. constBuffers.push_back(nullptr);
  393. if (buffer != nullptr)
  394. {
  395. buffer->flushToGPU();
  396. const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer =
  397. static_cast<const D3D11GpuParamBlockBufferCore*>(buffer.get());
  398. constBuffers[slot] = d3d11paramBlockBuffer->getD3D11Buffer();
  399. }
  400. }
  401. };
  402. UINT32 numSRVs = 0;
  403. UINT32 numUAVs = 0;
  404. UINT32 numConstBuffers = 0;
  405. UINT32 numSamplers = 0;
  406. populateViews(GPT_VERTEX_PROGRAM);
  407. numSRVs = (UINT32)srvs.size();
  408. numConstBuffers = (UINT32)constBuffers.size();
  409. numSamplers = (UINT32)samplers.size();
  410. if(numSRVs > 0)
  411. context->VSSetShaderResources(0, numSRVs, srvs.data());
  412. if (numConstBuffers > 0)
  413. context->VSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  414. if (numSamplers > 0)
  415. context->VSSetSamplers(0, numSamplers, samplers.data());
  416. populateViews(GPT_FRAGMENT_PROGRAM);
  417. numSRVs = (UINT32)srvs.size();
  418. numUAVs = (UINT32)uavs.size();
  419. numConstBuffers = (UINT32)constBuffers.size();
  420. numSamplers = (UINT32)samplers.size();
  421. if (numSRVs > 0)
  422. context->PSSetShaderResources(0, numSRVs, srvs.data());
  423. if (numUAVs > 0)
  424. {
  425. context->OMSetRenderTargetsAndUnorderedAccessViews(
  426. D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 0, numUAVs, uavs.data(), nullptr);
  427. mPSUAVsBound = true;
  428. }
  429. if (numConstBuffers > 0)
  430. context->PSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  431. if (numSamplers > 0)
  432. context->PSSetSamplers(0, numSamplers, samplers.data());
  433. populateViews(GPT_GEOMETRY_PROGRAM);
  434. numSRVs = (UINT32)srvs.size();
  435. numConstBuffers = (UINT32)constBuffers.size();
  436. numSamplers = (UINT32)samplers.size();
  437. if (numSRVs > 0)
  438. context->GSSetShaderResources(0, numSRVs, srvs.data());
  439. if (numConstBuffers > 0)
  440. context->GSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  441. if (numSamplers > 0)
  442. context->GSSetSamplers(0, numSamplers, samplers.data());
  443. populateViews(GPT_HULL_PROGRAM);
  444. numSRVs = (UINT32)srvs.size();
  445. numConstBuffers = (UINT32)constBuffers.size();
  446. numSamplers = (UINT32)samplers.size();
  447. if (numSRVs > 0)
  448. context->HSSetShaderResources(0, numSRVs, srvs.data());
  449. if (numConstBuffers > 0)
  450. context->HSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  451. if (numSamplers > 0)
  452. context->HSSetSamplers(0, numSamplers, samplers.data());
  453. populateViews(GPT_DOMAIN_PROGRAM);
  454. numSRVs = (UINT32)srvs.size();
  455. numConstBuffers = (UINT32)constBuffers.size();
  456. numSamplers = (UINT32)samplers.size();
  457. if (numSRVs > 0)
  458. context->DSSetShaderResources(0, numSRVs, srvs.data());
  459. if (numConstBuffers > 0)
  460. context->DSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  461. if (numSamplers > 0)
  462. context->DSSetSamplers(0, numSamplers, samplers.data());
  463. populateViews(GPT_COMPUTE_PROGRAM);
  464. numSRVs = (UINT32)srvs.size();
  465. numUAVs = (UINT32)uavs.size();
  466. numConstBuffers = (UINT32)constBuffers.size();
  467. numSamplers = (UINT32)samplers.size();
  468. if (numSRVs > 0)
  469. context->CSSetShaderResources(0, numSRVs, srvs.data());
  470. if (numUAVs > 0)
  471. {
  472. context->CSSetUnorderedAccessViews(0, numUAVs, uavs.data(), nullptr);
  473. mCSUAVsBound = true;
  474. }
  475. if (numConstBuffers > 0)
  476. context->CSSetConstantBuffers(0, numConstBuffers, constBuffers.data());
  477. if (numSamplers > 0)
  478. context->CSSetSamplers(0, numSamplers, samplers.data());
  479. }
  480. bs_frame_clear();
  481. if (mDevice->hasError())
  482. BS_EXCEPT(RenderingAPIException, "Failed to set GPU parameters: " + mDevice->getErrorDescription());
  483. };
  484. if (commandBuffer == nullptr)
  485. executeRef(gpuParams);
  486. else
  487. {
  488. auto execute = [=]() { executeRef(gpuParams); };
  489. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  490. cb->queueCommand(execute);
  491. }
  492. BS_INC_RENDER_STAT(NumGpuParamBinds);
  493. }
  494. void D3D11RenderAPI::setViewport(const Rect2& vp, const SPtr<CommandBuffer>& commandBuffer)
  495. {
  496. auto executeRef = [&](const Rect2& vp)
  497. {
  498. THROW_IF_NOT_CORE_THREAD;
  499. mViewportNorm = vp;
  500. applyViewport();
  501. };
  502. if (commandBuffer == nullptr)
  503. executeRef(vp);
  504. else
  505. {
  506. auto execute = [=]() { executeRef(vp); };
  507. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  508. cb->queueCommand(execute);
  509. }
  510. }
  511. void D3D11RenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers,
  512. const SPtr<CommandBuffer>& commandBuffer)
  513. {
  514. auto executeRef = [&](UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
  515. {
  516. THROW_IF_NOT_CORE_THREAD;
  517. UINT32 maxBoundVertexBuffers = mCurrentCapabilities[0].getMaxBoundVertexBuffers();
  518. if (index < 0 || (index + numBuffers) >= maxBoundVertexBuffers)
  519. {
  520. BS_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) +
  521. ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));
  522. }
  523. ID3D11Buffer* dx11buffers[BS_MAX_BOUND_VERTEX_BUFFERS];
  524. UINT32 strides[BS_MAX_BOUND_VERTEX_BUFFERS];
  525. UINT32 offsets[BS_MAX_BOUND_VERTEX_BUFFERS];
  526. for (UINT32 i = 0; i < numBuffers; i++)
  527. {
  528. SPtr<D3D11VertexBufferCore> vertexBuffer = std::static_pointer_cast<D3D11VertexBufferCore>(buffers[i]);
  529. const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
  530. dx11buffers[i] = vertexBuffer->getD3DVertexBuffer();
  531. strides[i] = vbProps.getVertexSize();
  532. offsets[i] = 0;
  533. }
  534. mDevice->getImmediateContext()->IASetVertexBuffers(index, numBuffers, dx11buffers, strides, offsets);
  535. };
  536. if (commandBuffer == nullptr)
  537. executeRef(index, buffers, numBuffers);
  538. else
  539. {
  540. auto execute = [=]() { executeRef(index, buffers, numBuffers); };
  541. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  542. cb->queueCommand(execute);
  543. }
  544. BS_INC_RENDER_STAT(NumVertexBufferBinds);
  545. }
  546. void D3D11RenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer, const SPtr<CommandBuffer>& commandBuffer)
  547. {
  548. auto executeRef = [&](const SPtr<IndexBufferCore>& buffer)
  549. {
  550. THROW_IF_NOT_CORE_THREAD;
  551. SPtr<D3D11IndexBufferCore> indexBuffer = std::static_pointer_cast<D3D11IndexBufferCore>(buffer);
  552. DXGI_FORMAT indexFormat = DXGI_FORMAT_R16_UINT;
  553. if (indexBuffer->getProperties().getType() == IT_16BIT)
  554. indexFormat = DXGI_FORMAT_R16_UINT;
  555. else if (indexBuffer->getProperties().getType() == IT_32BIT)
  556. indexFormat = DXGI_FORMAT_R32_UINT;
  557. else
  558. BS_EXCEPT(InternalErrorException, "Unsupported index format: " + toString(indexBuffer->getProperties().getType()));
  559. mDevice->getImmediateContext()->IASetIndexBuffer(indexBuffer->getD3DIndexBuffer(), indexFormat, 0);
  560. };
  561. if (commandBuffer == nullptr)
  562. executeRef(buffer);
  563. else
  564. {
  565. auto execute = [=]() { executeRef(buffer); };
  566. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  567. cb->queueCommand(execute);
  568. }
  569. BS_INC_RENDER_STAT(NumIndexBufferBinds);
  570. }
  571. void D3D11RenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration,
  572. const SPtr<CommandBuffer>& commandBuffer)
  573. {
  574. auto executeRef = [&](const SPtr<VertexDeclarationCore>& vertexDeclaration)
  575. {
  576. THROW_IF_NOT_CORE_THREAD;
  577. mActiveVertexDeclaration = vertexDeclaration;
  578. };
  579. if (commandBuffer == nullptr)
  580. executeRef(vertexDeclaration);
  581. else
  582. {
  583. auto execute = [=]() { executeRef(vertexDeclaration); };
  584. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  585. cb->queueCommand(execute);
  586. }
  587. }
  588. void D3D11RenderAPI::setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer)
  589. {
  590. auto executeRef = [&](DrawOperationType op)
  591. {
  592. THROW_IF_NOT_CORE_THREAD;
  593. mDevice->getImmediateContext()->IASetPrimitiveTopology(D3D11Mappings::getPrimitiveType(op));
  594. mActiveDrawOp = op;
  595. };
  596. if (commandBuffer == nullptr)
  597. executeRef(op);
  598. else
  599. {
  600. auto execute = [=]() { executeRef(op); };
  601. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  602. cb->queueCommand(execute);
  603. cb->mActiveDrawOp = op;
  604. }
  605. }
  606. void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount,
  607. const SPtr<CommandBuffer>& commandBuffer)
  608. {
  609. auto executeRef = [&](UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
  610. {
  611. THROW_IF_NOT_CORE_THREAD;
  612. applyInputLayout();
  613. if (instanceCount <= 1)
  614. mDevice->getImmediateContext()->Draw(vertexCount, vertexOffset);
  615. else
  616. mDevice->getImmediateContext()->DrawInstanced(vertexCount, instanceCount, vertexOffset, 0);
  617. #if BS_DEBUG_MODE
  618. if (mDevice->hasError())
  619. LOGWRN(mDevice->getErrorDescription());
  620. #endif
  621. };
  622. UINT32 primCount;
  623. if (commandBuffer == nullptr)
  624. {
  625. executeRef(vertexOffset, vertexCount, instanceCount);
  626. primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
  627. }
  628. else
  629. {
  630. auto execute = [=]() { executeRef(vertexOffset, vertexCount, instanceCount); };
  631. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  632. cb->queueCommand(execute);
  633. primCount = vertexCountToPrimCount(cb->mActiveDrawOp, vertexCount);
  634. }
  635. BS_INC_RENDER_STAT(NumDrawCalls);
  636. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  637. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  638. }
  639. void D3D11RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
  640. UINT32 instanceCount, const SPtr<CommandBuffer>& commandBuffer)
  641. {
  642. auto executeRef = [&](UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
  643. UINT32 instanceCount)
  644. {
  645. THROW_IF_NOT_CORE_THREAD;
  646. applyInputLayout();
  647. if (instanceCount <= 1)
  648. mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, vertexOffset);
  649. else
  650. mDevice->getImmediateContext()->DrawIndexedInstanced(indexCount, instanceCount, startIndex, vertexOffset, 0);
  651. #if BS_DEBUG_MODE
  652. if (mDevice->hasError())
  653. LOGWRN(mDevice->getErrorDescription());
  654. #endif
  655. };
  656. UINT32 primCount;
  657. if (commandBuffer == nullptr)
  658. {
  659. executeRef(startIndex, indexCount, vertexOffset, vertexCount, instanceCount);
  660. primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
  661. }
  662. else
  663. {
  664. auto execute = [=]() { executeRef(startIndex, indexCount, vertexOffset, vertexCount, instanceCount); };
  665. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  666. cb->queueCommand(execute);
  667. primCount = vertexCountToPrimCount(cb->mActiveDrawOp, vertexCount);
  668. }
  669. BS_INC_RENDER_STAT(NumDrawCalls);
  670. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  671. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  672. }
  673. void D3D11RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ,
  674. const SPtr<CommandBuffer>& commandBuffer)
  675. {
  676. auto executeRef = [&](UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
  677. {
  678. THROW_IF_NOT_CORE_THREAD;
  679. mDevice->getImmediateContext()->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
  680. #if BS_DEBUG_MODE
  681. if (mDevice->hasError())
  682. LOGWRN(mDevice->getErrorDescription());
  683. #endif
  684. };
  685. if (commandBuffer == nullptr)
  686. executeRef(numGroupsX, numGroupsY, numGroupsZ);
  687. else
  688. {
  689. auto execute = [=]() { executeRef(numGroupsX, numGroupsY, numGroupsZ); };
  690. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  691. cb->queueCommand(execute);
  692. }
  693. BS_INC_RENDER_STAT(NumComputeCalls);
  694. }
  695. void D3D11RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom,
  696. const SPtr<CommandBuffer>& commandBuffer)
  697. {
  698. auto executeRef = [&](UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
  699. {
  700. THROW_IF_NOT_CORE_THREAD;
  701. mScissorRect.left = static_cast<LONG>(left);
  702. mScissorRect.top = static_cast<LONG>(top);
  703. mScissorRect.bottom = static_cast<LONG>(bottom);
  704. mScissorRect.right = static_cast<LONG>(right);
  705. mDevice->getImmediateContext()->RSSetScissorRects(1, &mScissorRect);
  706. };
  707. if (commandBuffer == nullptr)
  708. executeRef(left, top, right, bottom);
  709. else
  710. {
  711. auto execute = [=]() { executeRef(left, top, right, bottom); };
  712. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  713. cb->queueCommand(execute);
  714. }
  715. }
  716. void D3D11RenderAPI::setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer)
  717. {
  718. auto executeRef = [&](UINT32 value)
  719. {
  720. THROW_IF_NOT_CORE_THREAD;
  721. mStencilRef = value;
  722. if(mActiveDepthStencilState != nullptr)
  723. mDevice->getImmediateContext()->OMSetDepthStencilState(mActiveDepthStencilState->getInternal(), mStencilRef);
  724. else
  725. mDevice->getImmediateContext()->OMSetDepthStencilState(nullptr, mStencilRef);
  726. };
  727. if (commandBuffer == nullptr)
  728. executeRef(value);
  729. else
  730. {
  731. auto execute = [=]() { executeRef(value); };
  732. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  733. cb->queueCommand(execute);
  734. }
  735. }
  736. void D3D11RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
  737. const SPtr<CommandBuffer>& commandBuffer)
  738. {
  739. auto executeRef = [&](UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
  740. {
  741. THROW_IF_NOT_CORE_THREAD;
  742. if (mActiveRenderTarget == nullptr)
  743. return;
  744. const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
  745. Rect2I clearArea((int)mViewport.TopLeftX, (int)mViewport.TopLeftY, (int)mViewport.Width, (int)mViewport.Height);
  746. bool clearEntireTarget = clearArea.width == 0 || clearArea.height == 0;
  747. clearEntireTarget |= (clearArea.x == 0 && clearArea.y == 0 && clearArea.width == rtProps.getWidth() &&
  748. clearArea.height == rtProps.getHeight());
  749. if (!clearEntireTarget)
  750. {
  751. // TODO - Ignoring targetMask here
  752. D3D11RenderUtility::instance().drawClearQuad(buffers, color, depth, stencil);
  753. BS_INC_RENDER_STAT(NumClears);
  754. }
  755. else
  756. clearRenderTarget(buffers, color, depth, stencil, targetMask);
  757. };
  758. if (commandBuffer == nullptr)
  759. executeRef(buffers, color, depth, stencil, targetMask);
  760. else
  761. {
  762. auto execute = [=]() { executeRef(buffers, color, depth, stencil, targetMask); };
  763. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  764. cb->queueCommand(execute);
  765. }
  766. }
  767. void D3D11RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil,
  768. UINT8 targetMask, const SPtr<CommandBuffer>& commandBuffer)
  769. {
  770. auto executeRef = [&](UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
  771. {
  772. THROW_IF_NOT_CORE_THREAD;
  773. if (mActiveRenderTarget == nullptr)
  774. return;
  775. // Clear render surfaces
  776. if (buffers & FBT_COLOR)
  777. {
  778. UINT32 maxRenderTargets = mCurrentCapabilities[0].getNumMultiRenderTargets();
  779. ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
  780. memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
  781. mActiveRenderTarget->getCustomAttribute("RTV", views);
  782. if (!views[0])
  783. {
  784. bs_deleteN(views, maxRenderTargets);
  785. return;
  786. }
  787. float clearColor[4];
  788. clearColor[0] = color.r;
  789. clearColor[1] = color.g;
  790. clearColor[2] = color.b;
  791. clearColor[3] = color.a;
  792. for (UINT32 i = 0; i < maxRenderTargets; i++)
  793. {
  794. if (views[i] != nullptr && ((1 << i) & targetMask) != 0)
  795. mDevice->getImmediateContext()->ClearRenderTargetView(views[i], clearColor);
  796. }
  797. bs_deleteN(views, maxRenderTargets);
  798. }
  799. // Clear depth stencil
  800. if ((buffers & FBT_DEPTH) != 0 || (buffers & FBT_STENCIL) != 0)
  801. {
  802. ID3D11DepthStencilView* depthStencilView = nullptr;
  803. mActiveRenderTarget->getCustomAttribute("DSV", &depthStencilView);
  804. D3D11_CLEAR_FLAG clearFlag;
  805. if ((buffers & FBT_DEPTH) != 0 && (buffers & FBT_STENCIL) != 0)
  806. clearFlag = (D3D11_CLEAR_FLAG)(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL);
  807. else if ((buffers & FBT_STENCIL) != 0)
  808. clearFlag = D3D11_CLEAR_STENCIL;
  809. else
  810. clearFlag = D3D11_CLEAR_DEPTH;
  811. if (depthStencilView != nullptr)
  812. mDevice->getImmediateContext()->ClearDepthStencilView(depthStencilView, clearFlag, depth, (UINT8)stencil);
  813. }
  814. };
  815. if (commandBuffer == nullptr)
  816. executeRef(buffers, color, depth, stencil, targetMask);
  817. else
  818. {
  819. auto execute = [=]() { executeRef(buffers, color, depth, stencil, targetMask); };
  820. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  821. cb->queueCommand(execute);
  822. }
  823. BS_INC_RENDER_STAT(NumClears);
  824. }
  825. void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil,
  826. RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
  827. {
  828. auto executeRef = [&](const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
  829. {
  830. THROW_IF_NOT_CORE_THREAD;
  831. mActiveRenderTarget = target;
  832. UINT32 maxRenderTargets = mCurrentCapabilities[0].getNumMultiRenderTargets();
  833. ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
  834. memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
  835. ID3D11DepthStencilView* depthStencilView = nullptr;
  836. if (target != nullptr)
  837. {
  838. target->getCustomAttribute("RTV", views);
  839. if (readOnlyDepthStencil)
  840. target->getCustomAttribute("RODSV", &depthStencilView);
  841. else
  842. target->getCustomAttribute("DSV", &depthStencilView);
  843. }
  844. // Bind render targets
  845. mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);
  846. if (mDevice->hasError())
  847. BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + mDevice->getErrorDescription());
  848. bs_deleteN(views, maxRenderTargets);
  849. applyViewport();
  850. };
  851. if (commandBuffer == nullptr)
  852. executeRef(target, readOnlyDepthStencil);
  853. else
  854. {
  855. auto execute = [=]() { executeRef(target, readOnlyDepthStencil); };
  856. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  857. cb->queueCommand(execute);
  858. }
  859. BS_INC_RENDER_STAT(NumRenderTargetChanges);
  860. }
  861. void D3D11RenderAPI::swapBuffers(const SPtr<RenderTargetCore>& target, UINT32 syncMask)
  862. {
  863. THROW_IF_NOT_CORE_THREAD;
  864. target->swapBuffers();
  865. BS_INC_RENDER_STAT(NumPresents);
  866. }
  867. void D3D11RenderAPI::addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary)
  868. {
  869. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  870. SPtr<D3D11CommandBuffer> secondaryCb = std::static_pointer_cast<D3D11CommandBuffer>(secondary);
  871. cb->appendSecondary(secondaryCb);
  872. }
  873. void D3D11RenderAPI::submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask)
  874. {
  875. SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
  876. if (cb == nullptr)
  877. return;
  878. cb->executeCommands();
  879. cb->clear();
  880. }
  881. void D3D11RenderAPI::applyViewport()
  882. {
  883. if (mActiveRenderTarget == nullptr)
  884. return;
  885. const RenderTargetProperties& rtProps = mActiveRenderTarget->getProperties();
  886. // Set viewport dimensions
  887. mViewport.TopLeftX = (FLOAT)(rtProps.getWidth() * mViewportNorm.x);
  888. mViewport.TopLeftY = (FLOAT)(rtProps.getHeight() * mViewportNorm.y);
  889. mViewport.Width = (FLOAT)(rtProps.getWidth() * mViewportNorm.width);
  890. mViewport.Height = (FLOAT)(rtProps.getHeight() * mViewportNorm.height);
  891. if (rtProps.requiresTextureFlipping())
  892. {
  893. // Convert "top-left" to "bottom-left"
  894. mViewport.TopLeftY = rtProps.getHeight() - mViewport.Height - mViewport.TopLeftY;
  895. }
  896. mViewport.MinDepth = 0.0f;
  897. mViewport.MaxDepth = 1.0f;
  898. mDevice->getImmediateContext()->RSSetViewports(1, &mViewport);
  899. }
  900. void D3D11RenderAPI::initCapabilites(IDXGIAdapter* adapter, RenderAPICapabilities& caps) const
  901. {
  902. THROW_IF_NOT_CORE_THREAD;
  903. // This must query for DirectX 10 interface as this is unsupported for DX11
  904. LARGE_INTEGER driverVersionNum;
  905. DriverVersion driverVersion;
  906. if (SUCCEEDED(adapter->CheckInterfaceSupport(IID_ID3D10Device, &driverVersionNum)))
  907. {
  908. driverVersion.major = HIWORD(driverVersionNum.HighPart);
  909. driverVersion.minor = LOWORD(driverVersionNum.HighPart);
  910. driverVersion.release = HIWORD(driverVersionNum.LowPart);
  911. driverVersion.build = LOWORD(driverVersionNum.LowPart);
  912. }
  913. caps.setDriverVersion(driverVersion);
  914. caps.setDeviceName(mActiveD3DDriver->getDriverDescription());
  915. caps.setRenderAPIName(getName());
  916. caps.setCapability(RSC_TEXTURE_COMPRESSION_BC);
  917. caps.addShaderProfile("hlsl");
  918. if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_1)
  919. caps.setMaxBoundVertexBuffers(32);
  920. else
  921. caps.setMaxBoundVertexBuffers(16);
  922. if(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0)
  923. {
  924. caps.setCapability(RSC_GEOMETRY_PROGRAM);
  925. caps.setNumTextureUnits(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
  926. caps.setNumTextureUnits(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
  927. caps.setNumTextureUnits(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
  928. caps.setNumCombinedTextureUnits(caps.getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
  929. + caps.getNumTextureUnits(GPT_VERTEX_PROGRAM) + caps.getNumTextureUnits(GPT_GEOMETRY_PROGRAM));
  930. caps.setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  931. caps.setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  932. caps.setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  933. caps.setNumCombinedGpuParamBlockBuffers(caps.getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
  934. + caps.getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM));
  935. }
  936. if(mFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
  937. {
  938. caps.setCapability(RSC_TESSELLATION_PROGRAM);
  939. caps.setCapability(RSC_COMPUTE_PROGRAM);
  940. caps.setNumTextureUnits(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT);
  941. caps.setNumTextureUnits(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT);
  942. caps.setNumTextureUnits(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT);
  943. caps.setNumCombinedTextureUnits(caps.getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
  944. + caps.getNumTextureUnits(GPT_VERTEX_PROGRAM) + caps.getNumTextureUnits(GPT_GEOMETRY_PROGRAM)
  945. + caps.getNumTextureUnits(GPT_HULL_PROGRAM) + caps.getNumTextureUnits(GPT_DOMAIN_PROGRAM)
  946. + caps.getNumTextureUnits(GPT_COMPUTE_PROGRAM));
  947. caps.setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  948. caps.setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  949. caps.setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
  950. caps.setNumCombinedGpuParamBlockBuffers(caps.getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
  951. + caps.getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM)
  952. + caps.getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
  953. + caps.getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
  954. caps.setNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM, D3D11_PS_CS_UAV_REGISTER_COUNT);
  955. caps.setNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM, D3D11_PS_CS_UAV_REGISTER_COUNT);
  956. caps.setNumCombinedLoadStoreTextureUnits(caps.getNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM)
  957. + caps.getNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM));
  958. }
  959. // Adapter details
  960. const DXGI_ADAPTER_DESC& adapterID = mActiveD3DDriver->getAdapterIdentifier();
  961. // Determine vendor
  962. switch(adapterID.VendorId)
  963. {
  964. case 0x10DE:
  965. caps.setVendor(GPU_NVIDIA);
  966. break;
  967. case 0x1002:
  968. caps.setVendor(GPU_AMD);
  969. break;
  970. case 0x163C:
  971. case 0x8086:
  972. caps.setVendor(GPU_INTEL);
  973. break;
  974. default:
  975. caps.setVendor(GPU_UNKNOWN);
  976. break;
  977. };
  978. caps.setNumMultiRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
  979. }
  980. void D3D11RenderAPI::determineMultisampleSettings(UINT32 multisampleCount, DXGI_FORMAT format, DXGI_SAMPLE_DESC* outputSampleDesc)
  981. {
  982. bool tryCSAA = false; // Note: Disabled for now, but leaving the code for later so it might be useful
  983. enum CSAAMode { CSAA_Normal, CSAA_Quality };
  984. CSAAMode csaaMode = CSAA_Normal;
  985. bool foundValid = false;
  986. size_t origNumSamples = multisampleCount;
  987. while (!foundValid)
  988. {
  989. // Deal with special cases
  990. if (tryCSAA)
  991. {
  992. switch(multisampleCount)
  993. {
  994. case 8:
  995. if (csaaMode == CSAA_Quality)
  996. {
  997. outputSampleDesc->Count = 8;
  998. outputSampleDesc->Quality = 8;
  999. }
  1000. else
  1001. {
  1002. outputSampleDesc->Count = 4;
  1003. outputSampleDesc->Quality = 8;
  1004. }
  1005. break;
  1006. case 16:
  1007. if (csaaMode == CSAA_Quality)
  1008. {
  1009. outputSampleDesc->Count = 8;
  1010. outputSampleDesc->Quality = 16;
  1011. }
  1012. else
  1013. {
  1014. outputSampleDesc->Count = 4;
  1015. outputSampleDesc->Quality = 16;
  1016. }
  1017. break;
  1018. }
  1019. }
  1020. else // !CSAA
  1021. {
  1022. outputSampleDesc->Count = multisampleCount == 0 ? 1 : multisampleCount;
  1023. outputSampleDesc->Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
  1024. }
  1025. HRESULT hr;
  1026. UINT outQuality;
  1027. hr = mDevice->getD3D11Device()->CheckMultisampleQualityLevels(format, outputSampleDesc->Count, &outQuality);
  1028. if (SUCCEEDED(hr) && (!tryCSAA || outQuality > outputSampleDesc->Quality))
  1029. {
  1030. foundValid = true;
  1031. }
  1032. else
  1033. {
  1034. // Downgrade
  1035. if (tryCSAA && multisampleCount == 8)
  1036. {
  1037. // For CSAA, we'll try downgrading with quality mode at all samples.
  1038. // then try without quality, then drop CSAA
  1039. if (csaaMode == CSAA_Quality)
  1040. {
  1041. // Drop quality first
  1042. csaaMode = CSAA_Normal;
  1043. }
  1044. else
  1045. {
  1046. // Drop CSAA entirely
  1047. tryCSAA = false;
  1048. }
  1049. // Return to original requested samples
  1050. multisampleCount = static_cast<UINT32>(origNumSamples);
  1051. }
  1052. else
  1053. {
  1054. // Drop samples
  1055. multisampleCount--;
  1056. if (multisampleCount == 1)
  1057. {
  1058. // Ran out of options, no multisampling
  1059. multisampleCount = 0;
  1060. foundValid = true;
  1061. }
  1062. }
  1063. }
  1064. }
  1065. }
  1066. void D3D11RenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
  1067. {
  1068. dest = matrix;
  1069. // Convert depth range from [-1,+1] to [0,1]
  1070. dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
  1071. dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
  1072. dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
  1073. dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
  1074. }
  1075. const RenderAPIInfo& D3D11RenderAPI::getAPIInfo() const
  1076. {
  1077. static RenderAPIInfo info(0.0f, 0.0f, 0.0f, 1.0f, VET_COLOR_ABGR, false, false, false, false, false);
  1078. return info;
  1079. }
  1080. GpuParamBlockDesc D3D11RenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
  1081. {
  1082. GpuParamBlockDesc block;
  1083. block.blockSize = 0;
  1084. block.isShareable = true;
  1085. block.name = name;
  1086. block.slot = 0;
  1087. block.set = 0;
  1088. for (auto& param : params)
  1089. {
  1090. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[param.type];
  1091. UINT32 size = typeInfo.size / 4;
  1092. if (param.arraySize > 1)
  1093. {
  1094. // Arrays perform no packing and their elements are always padded and aligned to four component vectors
  1095. UINT32 alignOffset = size % typeInfo.baseTypeSize;
  1096. if (alignOffset != 0)
  1097. {
  1098. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  1099. size += padding;
  1100. }
  1101. alignOffset = block.blockSize % typeInfo.baseTypeSize;
  1102. if (alignOffset != 0)
  1103. {
  1104. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  1105. block.blockSize += padding;
  1106. }
  1107. param.elementSize = size;
  1108. param.arrayElementStride = size;
  1109. param.cpuMemOffset = block.blockSize;
  1110. param.gpuMemOffset = 0;
  1111. block.blockSize += size * param.arraySize;
  1112. }
  1113. else
  1114. {
  1115. // Pack everything as tightly as possible as long as the data doesn't cross 16 byte boundary
  1116. UINT32 alignOffset = block.blockSize % 4;
  1117. if (alignOffset != 0 && size > (4 - alignOffset))
  1118. {
  1119. UINT32 padding = (4 - alignOffset);
  1120. block.blockSize += padding;
  1121. }
  1122. param.elementSize = size;
  1123. param.arrayElementStride = size;
  1124. param.cpuMemOffset = block.blockSize;
  1125. param.gpuMemOffset = 0;
  1126. block.blockSize += size;
  1127. }
  1128. param.paramBlockSlot = 0;
  1129. param.paramBlockSet = 0;
  1130. }
  1131. // Constant buffer size must always be a multiple of 16
  1132. if (block.blockSize % 4 != 0)
  1133. block.blockSize += (4 - (block.blockSize % 4));
  1134. return block;
  1135. }
  1136. /************************************************************************/
  1137. /* PRIVATE */
  1138. /************************************************************************/
  1139. void D3D11RenderAPI::applyInputLayout()
  1140. {
  1141. if(mActiveVertexDeclaration == nullptr)
  1142. {
  1143. LOGWRN("Cannot apply input layout without a vertex declaration. Set vertex declaration before calling this method.");
  1144. return;
  1145. }
  1146. if(mActiveVertexShader == nullptr)
  1147. {
  1148. LOGWRN("Cannot apply input layout without a vertex shader. Set vertex shader before calling this method.");
  1149. return;
  1150. }
  1151. ID3D11InputLayout* ia = mIAManager->retrieveInputLayout(mActiveVertexShader->getInputDeclaration(), mActiveVertexDeclaration, *mActiveVertexShader);
  1152. mDevice->getImmediateContext()->IASetInputLayout(ia);
  1153. }
  1154. }