Cogs.Core
ContextD3D11.cpp
1#include "ContextD3D11.h"
2#include "GraphicsDeviceD3D11.h"
3#include "FormatsD3D11.h"
4
5#include "Foundation/Logging/Logger.h"
6
7#include <algorithm>
8
9namespace
10{
11 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ContextD3D11");
12
13 struct RenderStats
14 {
15 size_t numVertices;
16 size_t numIndices;
17 size_t numFaces;
18 size_t drawCalls;
19 } renderStats = { 0 };
20}
21
22namespace Cogs
23{
24 namespace Direct3D11
25 {
26 const D3D11_PRIMITIVE_TOPOLOGY Topologies[] = {
27 D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
28 D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
29 D3D11_PRIMITIVE_TOPOLOGY_LINELIST,
30 D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP,
31 D3D11_PRIMITIVE_TOPOLOGY_POINTLIST,
32 D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ,
33 D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ,
34 D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ,
35 D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ,
36 D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST,
37 D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST,
38 D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST,
39 D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST,
40 };
41
42 const D3D11_MAP MapFlags[] = {
43 D3D11_MAP_READ,
44 D3D11_MAP_WRITE,
45 D3D11_MAP_READ_WRITE,
46 D3D11_MAP_WRITE_DISCARD
47 };
48 }
49}
50
51Cogs::ContextD3D11::ContextD3D11() :
52 defaultBlendState(BlendStateHandle::InvalidHandle),
53 defaultDepthStencilState(DepthStencilStateHandle::InvalidHandle),
54 defaultRasterizerState(RasterizerStateHandle::InvalidHandle),
55 currentRenderTarget(RenderTargetHandle::InvalidHandle),
56 currentDepthStencil(DepthStencilHandle::InvalidHandle),
57 currentInputLayout(InputLayoutHandle::InvalidHandle),
58 isCompute(false)
59{
60 state = { 0 };
61}
62
63Cogs::ContextD3D11::~ContextD3D11()
64{
65 if (immediateContext) {
66 immediateContext->ClearState();
67 immediateContext->Flush();
68 }
69}
70
71void Cogs::ContextD3D11::initialize(GraphicsDeviceD3D11 * graphicsDevice, BuffersD3D11 * buffers, TexturesD3D11 * textures, EffectsD3D11 * effects, RenderTargetsD3D11 * renderTargets, SyncObjectsD3D11* sync)
72{
73 this->constantBuffersUpdated = false;
74
75 this->graphicsDevice = graphicsDevice;
76 this->buffers = buffers;
77 this->textures = textures;
78 this->effects = effects;
79 this->renderTargets = renderTargets;
80 this->syncObjects = sync;
81
82 // Ensure all default resources are pinned and not released by user code.
83
84 this->defaultRasterizerState = this->renderTargets->loadRasterizerState(RasterizerState::DefaultState());
85 this->renderTargets->rasterizerStates.pin(this->defaultRasterizerState);
86
87 this->defaultBlendState = this->renderTargets->loadBlendState(BlendState::DefaultState());
88 this->renderTargets->blendStates.pin(this->defaultBlendState);
89
90 this->defaultDepthStencilState = this->renderTargets->loadDepthStencilState(DepthStencilState::DefaultState());
91 this->renderTargets->depthStencilStates.pin(this->defaultDepthStencilState);
92
93 this->defaultSamplerState = this->textures->loadSamplerState(SamplerState::DefaultState());
94 this->textures->samplerStates.pin(this->defaultSamplerState);
95
96 HRESULT hr = immediateContext->QueryInterface(__uuidof(annotationInterface), annotationInterface.internalVoidPointer());
97 if (SUCCEEDED(hr)) {
98 //Currently, NSIGHT 5.0 returns false here when running under graphics debugging. Bug submitted. 2015-10-3 chrisdy.
99 //if (!annotationInterface->GetStatus()) {
100 // annotationInterface.Release();
101 //}
102 }
103}
104
105void Cogs::ContextD3D11::setDevice(ResourcePointer<ID3D11Device>& device, ResourcePointer<ID3D11Device1>& device1)
106{
107 assert(this->device == nullptr && "Device already set");
108 assert(this->device1 == nullptr && "Device1 already set");
109 assert(immediateContext == nullptr && "Immediate context already set");
110 assert(immediateContext1 == nullptr && "Immediate context already set");
111
112 this->device = device;
113 this->device1 = device1;
114 if (this->device1) {
115 this->device1->GetImmediateContext1(this->immediateContext1.internalPointer());
116 }
117 this->device->GetImmediateContext(this->immediateContext.internalPointer());
118
119 if (HRESULT hr = immediateContext->QueryInterface(__uuidof(ID3D11DeviceContext4), immediateContext4.internalVoidPointer()); SUCCEEDED(hr)) {
120 LOG_DEBUG(logger, "Got ID3D11DeviceContext4 interface");
121 }
122
123}
124
125
126void Cogs::ContextD3D11::setDefaults()
127{
128 this->constantBuffersUpdated = false;
129 this->currentEffect = EffectHandle::NoHandle;
130 this->isCompute = false;
131
132 immediateContext->RSSetScissorRects(0, nullptr);
133
134 this->setBlendState(defaultBlendState, nullptr);
135 this->setRasterizerState(defaultRasterizerState);
136 this->setDepthStencilState(defaultDepthStencilState);
137
139
140 // Release all bound resources from last frame.
141 ID3D11ShaderResourceView * shaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { 0 };
142 immediateContext->VSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, shaderResourceViews);
143 immediateContext->GSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, shaderResourceViews);
144 immediateContext->PSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, shaderResourceViews);
145 immediateContext->CSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, shaderResourceViews);
146
147 ID3D11SamplerState * samplerStates[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = { this->textures->samplerStates[defaultSamplerState] };
148 immediateContext->VSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
149 immediateContext->GSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
150 immediateContext->PSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
151 immediateContext->CSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
152
153 ID3D11Buffer * constantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = { 0 };
154 immediateContext->VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, constantBuffers);
155 immediateContext->GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, constantBuffers);
156 immediateContext->PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, constantBuffers);
157
158 state = { 0 };
159
160 constantBuffersUpdated = false;
161}
162
164{
165 if (HandleIsValid(fenceHandle) && immediateContext4) {
166 FenceD3D11& fence = syncObjects->fences[fenceHandle];
167 immediateContext4->Signal(fence.fence, ++fence.value);
168 }
169}
170
171
173{
174 if (!annotationInterface) return;
175
176 static thread_local std::wstring wname;
177
178 if (annotationInterface->GetStatus()) {
179 wname.assign(name.begin(), name.end());
180
181 annotationInterface->BeginEvent(wname.c_str());
182 }
183}
184
186{
187 if (!annotationInterface) return;
188
189 if (annotationInterface->GetStatus()) {
190 annotationInterface->EndEvent();
191 }
192}
193
195{
196 if(!annotationInterface) return;
197
198 static thread_local std::wstring wname;
199
200 if (annotationInterface->GetStatus()) {
201 wname.assign(name.begin(), name.end());
202
203 annotationInterface->SetMarker(wname.c_str());
204 }
205}
206
207void Cogs::ContextD3D11::setVertexBuffers(const VertexBufferHandle * handles, const size_t count, const uint32_t * strides, const uint32_t * offsets)
208{
209 iaState.numVertexBuffers = count;
210
211 for (size_t i = 0; i < count; i++) {
212 auto & buffer = buffers->buffers[BufferHandle(handles[i].handle)];
213
214 iaState.formats[i] = buffer.vertexBuffer.vertexFormat;
215 iaState.currentVertexBuffers[i] = buffer.buffer;
216 iaState.strides[i] = strides[i];
217 iaState.offsets[i] = offsets ? offsets[i] : 0;
218 }
219
220 if (count) {
221 immediateContext->IASetVertexBuffers(0, static_cast<UINT>(count), iaState.currentVertexBuffers, iaState.strides, iaState.offsets);
222 } else {
223 immediateContext->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr);
224 }
225}
226
227void Cogs::ContextD3D11::setVertexBuffers(const VertexBufferHandle * handles, const size_t count)
228{
229 uint32_t strides[kMaxVertexInputSlots];
230 uint32_t offsets[kMaxVertexInputSlots];
231
232 for (size_t i = 0; i < count; i++) {
233 auto & buffer = buffers->buffers[BufferHandle(handles[i].handle)];
234
235 assert(buffer.vertexBuffer.vertexFormat && "Vertex buffer must have been created with format information attached.");
236
237 strides[i] = getSize(*buffer.vertexBuffer.vertexFormat);
238 offsets[i] = 0;
239 }
240
241 setVertexBuffers(handles, count, strides, offsets);
242}
243
244void Cogs::ContextD3D11::setIndexBuffer(IndexBufferHandle indexBufferHandle, uint32_t stride, uint32_t offset)
245{
246 if (HandleIsValid(indexBufferHandle)) {
247 auto & indexBuffer = buffers->buffers[indexBufferHandle];
248
249 iaState.currentIndexBuffer = &indexBuffer;
250
251 assert(indexBuffer.bindFlags & BindFlags::IndexBuffer && "Buffer not bindable as index buffer.");
252
253 auto format = stride == 0 ? iaState.currentIndexBuffer->indexBuffer.indexFormat : (stride == 4 ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT);
254
255 if (format == DXGI_FORMAT_UNKNOWN) {
256 iaState.currentIndexBuffer = nullptr;
257 immediateContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
258 } else {
259 immediateContext->IASetIndexBuffer(indexBuffer.buffer, format, offset);
260 }
261 } else {
262 iaState.currentIndexBuffer = nullptr;
263 immediateContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
264 }
265}
266
267void Cogs::ContextD3D11::setConstantBuffer(const ConstantBufferBindingHandle bufferBinding, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size)
268{
269 auto & effect = effects->effects[currentEffect];
270 if (offset == 0 && size == ~0u) {
271 if (this->isCompute) {
272 const uint32_t csSlot = decode(bufferBinding.handle);
273
274 if (HandleIsValid(bufferHandle)) {
275 auto & buffer = buffers->buffers[bufferHandle];
276
277 if (csSlot != NoBinding11) immediateContext->CSSetConstantBuffers(csSlot, 1, &buffer.buffer);
278
279 constantBuffersUpdated = true;
280
281 for (auto & constantBuffer : effect.shaders[ShaderType::ComputeShader].reflection.constantBuffers) {
282 if (constantBuffer.slot == csSlot) {
283 constantBuffer.manual = true;
284 }
285 }
286 }
287 else {
288 if (csSlot != NoBinding11) immediateContext->CSSetConstantBuffers(csSlot, 0, nullptr);
289 }
290 }
291 else {
292 uint32_t slots[ShaderType::NumShaderTypes];
293 decode(bufferBinding.handle, slots);
294
295 if (HandleIsValid(bufferHandle)) {
296 auto & buffer = buffers->buffers[bufferHandle];
297
298 if (slots[0] != NoBinding11 && bufferHandle != state.vsCBs[slots[0]]) {
299 immediateContext->VSSetConstantBuffers(slots[0], 1, &buffer.buffer);
300 state.vsCBs[slots[0]] = bufferHandle;
301 }
302 if (slots[1] != NoBinding11) {
303 immediateContext->HSSetConstantBuffers(slots[1], 1, &buffer.buffer);
304 }
305 if (slots[2] != NoBinding11) {
306 immediateContext->DSSetConstantBuffers(slots[2], 1, &buffer.buffer);
307 }
308 if (slots[3] != NoBinding11) {
309 immediateContext->GSSetConstantBuffers(slots[3], 1, &buffer.buffer);
310 }
311 if (slots[4] != NoBinding11 && bufferHandle != state.psCBs[slots[4]]) {
312 immediateContext->PSSetConstantBuffers(slots[4], 1, &buffer.buffer);
313 state.psCBs[slots[4]] = bufferHandle;
314 }
315
316 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
317 for (auto & constantBuffer : effect.shaders[i].reflection.constantBuffers) {
318 if (constantBuffer.slot == slots[i]) {
319 constantBuffer.manual = true;
320 }
321 }
322 }
323 }
324 else {
325 if (slots[0] != NoBinding11) {
326 immediateContext->VSSetConstantBuffers(slots[0], 0, nullptr);
327 }
328 if (slots[1] != NoBinding11) {
329 immediateContext->GSSetConstantBuffers(slots[1], 0, nullptr);
330 }
331 if (slots[2] != NoBinding11) {
332 immediateContext->PSSetConstantBuffers(slots[2], 0, nullptr);
333 }
334 }
335 }
336 }
337 else {
338 if (!device1) {
339 LOG_ERROR(logger, "Binding part of a constant buffer requires DX 11.1");
340 return;
341 }
342 assert(immediateContext1);
343
344 if (offset & 255) {
345 LOG_ERROR(logger, "Constant buffer offset must be a multiple of 256 bytes.");
346 return;
347 }
348 UINT firstConstant = offset / 16;
349 UINT numConstant = 4096;
350 if (size != ~0u) {
351 if (size & 255) {
352 LOG_ERROR(logger, "Constant buffer size must be a multiple of 256 bytes.");
353 return;
354 }
355 numConstant = size / 16;
356 if (4096 < numConstant) {
357 LOG_ERROR(logger, "Constant buffer size cannot be larger than 16*4096 bytes.");
358 return;
359 }
360 }
361
362 if (this->isCompute) {
363 const uint32_t csSlot = decode(bufferBinding.handle);
364
365 if (HandleIsValid(bufferHandle)) {
366 auto & buffer = buffers->buffers[bufferHandle];
367
368 if (csSlot != NoBinding11) immediateContext1->CSSetConstantBuffers1(csSlot, 1, &buffer.buffer, &firstConstant, &numConstant);
369
370 constantBuffersUpdated = true;
371
372 for (auto & constantBuffer : effect.shaders[ShaderType::ComputeShader].reflection.constantBuffers) {
373 if (constantBuffer.slot == csSlot) {
374 constantBuffer.manual = true;
375 }
376 }
377 }
378 else {
379 if (csSlot != NoBinding11) immediateContext1->CSSetConstantBuffers1(csSlot, 0, nullptr, nullptr, nullptr);
380 }
381 }
382 else {
383 uint32_t slots[ShaderType::NumShaderTypes];
384 decode(bufferBinding.handle, slots);
385
386 if (HandleIsValid(bufferHandle)) {
387 auto & buffer = buffers->buffers[bufferHandle];
388
389 if (slots[0] != NoBinding11) {
390 immediateContext1->VSSetConstantBuffers1(slots[0], 1, &buffer.buffer, &firstConstant, &numConstant);
391 state.vsCBs[slots[0]] = BufferHandle();
392 }
393 if (slots[1] != NoBinding11) {
394 immediateContext1->HSSetConstantBuffers1(slots[1], 1, &buffer.buffer, &firstConstant, &numConstant);
395 }
396 if (slots[2] != NoBinding11) {
397 immediateContext1->DSSetConstantBuffers1(slots[2], 1, &buffer.buffer, &firstConstant, &numConstant);
398 }
399 if (slots[3] != NoBinding11) {
400 immediateContext1->GSSetConstantBuffers1(slots[3], 1, &buffer.buffer, &firstConstant, &numConstant);
401 }
402 if (slots[4] != NoBinding11) {
403 immediateContext1->PSSetConstantBuffers1(slots[4], 1, &buffer.buffer, &firstConstant, &numConstant);
404 state.psCBs[slots[4]] = BufferHandle();
405 }
406
407 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
408 for (auto & constantBuffer : effect.shaders[i].reflection.constantBuffers) {
409 if (constantBuffer.slot == slots[i]) {
410 constantBuffer.manual = true;
411 }
412 }
413 }
414 }
415 else {
416 if (slots[0] != NoBinding11) {
417 immediateContext1->VSSetConstantBuffers1(slots[0], 0, nullptr, nullptr, nullptr);
418 }
419 if (slots[1] != NoBinding11) {
420 immediateContext1->GSSetConstantBuffers1(slots[1], 0, nullptr, nullptr, nullptr);
421 }
422 if (slots[2] != NoBinding11) {
423 immediateContext1->PSSetConstantBuffers1(slots[2], 0, nullptr, nullptr, nullptr);
424 }
425 }
426 }
427
428 }
429}
430
431void Cogs::ContextD3D11::draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
432{
433 if (state.primitiveType != primitiveType) {
434 state.primitiveType = primitiveType;
435 immediateContext->IASetPrimitiveTopology(Direct3D11::Topologies[primitiveType]);
436 }
437
438 setupConstantBuffers();
439
440 immediateContext->Draw(static_cast<UINT>(numVertexes), static_cast<UINT>(startVertex));
441
442 renderStats.numFaces += numVertexes / 3;
443 renderStats.numVertices += numVertexes;
444 ++renderStats.drawCalls;
445
446 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes, false); }
447}
448
449void Cogs::ContextD3D11::drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex)
450{
451 if (state.primitiveType != primitiveType) {
452 state.primitiveType = primitiveType;
453 immediateContext->IASetPrimitiveTopology(Direct3D11::Topologies[primitiveType]);
454 }
455
456 setupConstantBuffers();
457
458 const UINT start = static_cast<UINT>(startIndex);
459 const UINT count = numIndexes == 0 ? static_cast<UINT>(iaState.currentIndexBuffer->indexBuffer.count) : static_cast<UINT>(numIndexes);
460
461 immediateContext->DrawIndexed(count, start, static_cast<UINT>(startVertex));
462
463 renderStats.numIndices += numIndexes;
464 renderStats.numFaces += numIndexes / 3;
465 renderStats.numVertices += numIndexes;
466 ++renderStats.drawCalls;
467
468 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(count, true); }
469}
470
472{
473 if (handle == RasterizerStateHandle::NoHandle) {
474 immediateContext->RSSetState(this->renderTargets->rasterizerStates[defaultRasterizerState]);
475 } else {
476 assert(this->renderTargets->rasterizerStates.hasResource(handle) && "Invalid rasterizer state handle.");
477 immediateContext->RSSetState(this->renderTargets->rasterizerStates[handle]);
478 }
479}
480
481void Cogs::ContextD3D11::setBlendState(const BlendStateHandle handle, const float* constant)
482{
483 if (handle == BlendStateHandle::NoHandle) {
484 immediateContext->OMSetBlendState(this->renderTargets->blendStates[defaultBlendState], 0, 0xffffffff);
485 } else {
486 assert(this->renderTargets->blendStates.hasResource(handle) && "Invalid blend state handle.");
487 immediateContext->OMSetBlendState(this->renderTargets->blendStates[handle], constant, 0xffffffff);
488 }
489}
490
492{
493 if (handle == DepthStencilStateHandle::NoHandle) {
494 immediateContext->OMSetDepthStencilState(this->renderTargets->depthStencilStates[defaultDepthStencilState], 1);
495 } else {
496 assert(this->renderTargets->depthStencilStates.hasResource(handle) && "Invalid depth stencil state handle.");
497 immediateContext->OMSetDepthStencilState(this->renderTargets->depthStencilStates[handle], 1);
498 }
499}
500
502{
503 assert(!inRenderPass);
504 setRenderTarget(info.renderTargetHandle, info.depthStencilHandle);
505 {
506 auto & renderTarget = renderTargets->renderTargets[currentRenderTarget];
507 for (size_t i = 0; i < renderTarget.numViews; ++i) {
508 if(info.loadOp[i] == LoadOp::Clear){
509 immediateContext->ClearRenderTargetView(renderTarget.views[i], info.clearValue[i]);
510 }
511 }
512 }
513 if(info.depthLoadOp == LoadOp::Clear){
514 clearDepth(info.depthClearValue);
515 }
516 inRenderPass = true;
517 renderPassInfo = info;
518}
519
521{
522 assert(inRenderPass);
523 if(HandleIsValid(renderPassInfo.renderTargetHandle)){
524 RenderTargetD3D11 &target = renderTargets->renderTargets[renderPassInfo.renderTargetHandle];
525 for(size_t i=0; i<target.numViews; i++){
526 if(HandleIsValid(renderPassInfo.resolveHandle[i])){
527 resolveResource(target.texture[i], textures->textureViews[renderPassInfo.resolveHandle[i]].texture);
528 }
529 }
530 }
531 inRenderPass = false;
532 renderPassInfo = {};
533}
534
536{
537 if (handle == RenderTargetHandle::NoHandle && depthStencilHandle == DepthStencilHandle::NoHandle) {
538 SwapChainD3D11* swapChain = graphicsDevice->getDefaultSwapChain();
539
540 currentRenderTarget = swapChain->getRenderTarget();
541 currentDepthStencil = swapChain->getDepthStencil();
542 }
543 else {
544 currentRenderTarget = handle;
545 currentDepthStencil = depthStencilHandle;
546 }
547
548 resetSRVBindings();
549
550 updateRenderTargets();
551}
552
553void Cogs::ContextD3D11::endFrame()
554{
555 renderStats = { 0 };
556}
557
558void Cogs::ContextD3D11::setViewport(const float x, const float y, const float width, const float height)
559{
560 D3D11_VIEWPORT viewport;
561 viewport.TopLeftX = x;
562 viewport.TopLeftY = y;
563 viewport.Width = width;
564 viewport.Height = height;
565 viewport.MinDepth = 0.0f;
566 viewport.MaxDepth = 1.0f;
567
568 immediateContext->RSSetViewports(1, &viewport);
569}
570
571void Cogs::ContextD3D11::setScissor(const int x, const int y, const int z, const int w)
572{
573 D3D11_RECT scissor{ x, y, z, w };
574
575 immediateContext->RSSetScissorRects(1, &scissor);
576}
577
579{
580 clearRenderTarget(&value, 1);
581}
582
583void Cogs::ContextD3D11::clearRenderTarget(const float ** values, const int numValues)
584{
585 assert(HandleIsValid(currentRenderTarget) && "No valid render target set.");
586
587 auto & renderTarget = renderTargets->renderTargets[currentRenderTarget];
588
589 for (size_t i = 0; i < renderTarget.numViews; ++i) {
590 immediateContext->ClearRenderTargetView(renderTarget.views[i], numValues != 1 ? values[i] : values[0]);
591 }
592}
593
594void Cogs::ContextD3D11::clearDepth(const float depth)
595{
596 assert(HandleIsValid(currentDepthStencil) && "No valid depth stencil target set.");
597
598 immediateContext->ClearDepthStencilView(renderTargets->depthStencilViews[currentDepthStencil], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, depth, 0);
599}
600
602{
603 if (effectHandle == currentEffect) return;
604
605 assert(HandleIsValid(effectHandle) && "Effect handle not valid.");
606
607 if (HandleIsValid(currentEffect)) {
608 // Reset previous shader resource and unordered access view bindings.
609 ID3D11UnorderedAccessView * UAVs[D3D11_PS_CS_UAV_REGISTER_COUNT] = { 0 };
610 immediateContext->CSSetUnorderedAccessViews(0, D3D11_PS_CS_UAV_REGISTER_COUNT, UAVs, nullptr);
611
612 for (int i = 0; i < D3D11_PS_CS_UAV_REGISTER_COUNT; ++i) {
613 uavs[i] = nullptr;
614 uavCounts[i] = ~0u;
615 uavDirty = false;
616 }
617 minUavSlot = ~0u;
618 maxUavSlot = 0;
619
620 ID3D11SamplerState * samplerStates[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = { this->textures->samplerStates[defaultSamplerState] };
621 immediateContext->VSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
622 immediateContext->GSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
623 immediateContext->PSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
624 immediateContext->CSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
625
626 ID3D11Buffer * constantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = { 0 };
627 if (state.dirtyCB[ShaderType::VertexShader]) {
628 immediateContext->VSSetConstantBuffers(0, state.dirtyCB[ShaderType::VertexShader], constantBuffers);
629 }
630 if (state.dirtyCB[ShaderType::GeometryShader]) {
631 immediateContext->GSSetConstantBuffers(0, state.dirtyCB[ShaderType::GeometryShader], constantBuffers);
632 }
633 if (state.dirtyCB[ShaderType::PixelShader]) {
634 immediateContext->PSSetConstantBuffers(0, state.dirtyCB[ShaderType::PixelShader], constantBuffers);
635 }
636 if (state.dirtyCB[ShaderType::ComputeShader]) {
637 immediateContext->CSSetConstantBuffers(0, state.dirtyCB[ShaderType::ComputeShader], constantBuffers);
638 }
639
640 resetSRVBindings();
641
642 state = { 0 };
643 }
644
645 currentEffect = effectHandle;
646 constantBuffersUpdated = false;
647 currentInputLayout = InputLayoutHandle::NoHandle;
648
649 auto & effect = effects->effects[currentEffect];
650
651 ContextCommon::setCurrentEffect(&effect);
652
653 bool wasCompute = isCompute;
654 if (effect.computeShader.shader) {
655 immediateContext->CSSetShader(effect.computeShader.shader.get<ID3D11ComputeShader>(), nullptr, 0);
656 isCompute = true;
657 } else {
658 immediateContext->VSSetShader(effect.vertexShader.shader.get<ID3D11VertexShader>(), nullptr, 0);
659 immediateContext->HSSetShader(effect.hullShader.shader.get<ID3D11HullShader>(), nullptr, 0);
660 immediateContext->DSSetShader(effect.domainShader.shader.get<ID3D11DomainShader>(), nullptr, 0);
661 immediateContext->GSSetShader(effect.geometryShader.shader.get<ID3D11GeometryShader>(), nullptr, 0);
662 immediateContext->PSSetShader(effect.pixelShader.shader.get<ID3D11PixelShader>(), nullptr, 0);
663 isCompute = false;
664 }
665 if (wasCompute != isCompute) {
666 updateRenderTargets();
667 }
668}
669
671{
672 if (inputLayoutHandle != currentInputLayout) {
673 if (HandleIsValid(inputLayoutHandle)) {
674 immediateContext->IASetInputLayout(buffers->inputLayouts[inputLayoutHandle].resource);
675 }
676 else {
677 immediateContext->IASetInputLayout(nullptr);
678 }
679
680 if (inputLayoutHandle) {
681 const auto & inputLayout = buffers->inputLayouts[inputLayoutHandle];
682
683 iaState.numVertexBuffers = inputLayout.numFormats;
684 for (size_t i = 0; i < inputLayout.numFormats; ++i) {
685 iaState.formats[i] = inputLayout.formats[i];
686 }
687 }
688
689 currentInputLayout = inputLayoutHandle;
690 }
691}
692
694{
695 auto & source = textures->textures[sourceTexture];
696 auto & destination = textures->textures[destinationTexture];
697
698 auto formatD3D = Direct3D11::Formats[(int)source.format];
699
700 immediateContext->ResolveSubresource(destination.resource(), 0, source.resource(), 0, formatD3D);
701}
702
703void Cogs::ContextD3D11::drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
704{
705 if (state.primitiveType != primitiveType) {
706 state.primitiveType = primitiveType;
707 immediateContext->IASetPrimitiveTopology(Direct3D11::Topologies[primitiveType]);
708 }
709
710 this->setupConstantBuffers();
711
712 immediateContext->DrawInstanced(static_cast<UINT>(numVertexes), static_cast<UINT>(numInstances), static_cast<UINT>(startVertex), static_cast<UINT>(startInstance));
713
714 renderStats.numFaces += numVertexes / 3 * numInstances;
715 renderStats.numVertices += numVertexes * numInstances;
716
717 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes * numInstances, false); }
718}
719
720void Cogs::ContextD3D11::drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
721{
722 if (state.primitiveType != primitiveType) {
723 state.primitiveType = primitiveType;
724 immediateContext->IASetPrimitiveTopology(Direct3D11::Topologies[primitiveType]);
725 }
726
727 this->setupConstantBuffers();
728
729 UINT indexCount = (numIndexes == 0) ? iaState.currentIndexBuffer->indexBuffer.count : static_cast<UINT>(numIndexes);
730
731 immediateContext->DrawIndexedInstanced(indexCount, static_cast<UINT>(numInstances), static_cast<UINT>(startIndex), 0, static_cast<UINT>(startInstance));
732
733 renderStats.numFaces += numIndexes / 3 * numInstances;
734 renderStats.numVertices += numIndexes * numInstances;
735
736 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(indexCount * numInstances, true); }
737}
738
739void Cogs::ContextD3D11::readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer)
740{
741 if (!HandleIsValid(bufferHandle)) return;
742
743 auto & depthStencilView = renderTargets->depthStencilViews[currentDepthStencil];
744
746 depthStencilView->GetResource((ID3D11Resource **)&depthBuffer);
747
748 D3D11_TEXTURE2D_DESC depthBufferDesc;
749 depthBuffer->GetDesc(&depthBufferDesc);
750
751 D3D11_TEXTURE2D_DESC fpTextureDesc{};
752 fpTextureDesc.Width = depthBufferDesc.Width;
753 fpTextureDesc.Height = depthBufferDesc.Height;
754 fpTextureDesc.ArraySize = 1;
755 fpTextureDesc.MipLevels = 1;
756 fpTextureDesc.Format = DXGI_FORMAT_R32_FLOAT;
757 fpTextureDesc.SampleDesc.Count = depthBufferDesc.SampleDesc.Count;
758 fpTextureDesc.SampleDesc.Quality = depthBufferDesc.SampleDesc.Quality;
759 fpTextureDesc.Usage = D3D11_USAGE_DEFAULT;
760 fpTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
761 fpTextureDesc.CPUAccessFlags = 0;
762 fpTextureDesc.MiscFlags = 0;
763
765 HRESULT hr = device->CreateTexture2D(&fpTextureDesc, nullptr, fpDepthTexture.internalPointer());
766 if (FAILED(hr)) {
767 LOG_ERROR(logger, "Failed to create depth readback texture (%s): %s", getString(fpTextureDesc), direct3D11ReturnCodeAsString(hr));
768 return;
769 }
770 else if ((graphicsDevice->getSettings().flags & GraphicsDeviceFlags::EnableTraceLogging) == GraphicsDeviceFlags::EnableTraceLogging) {
771 LOG_TRACE(logger, "Created resource %p: %s", fpDepthTexture.get<void>(), getString(fpTextureDesc));
772 }
773
774 // Copy the depth buffer from its internal representation to a floating point representation since
775 // we are not allowed to resolve directly from e.g D32_FLOAT format.
776 immediateContext->CopyResource(fpDepthTexture, depthBuffer);
777
778 const bool isMultisampled = depthBufferDesc.SampleDesc.Count > 1;
779 ResourcePointer<ID3D11Texture2D> resolvedDepthTexture;
780
781 if (isMultisampled) {
782 D3D11_TEXTURE2D_DESC resolveTextureDesc = {};
783 resolveTextureDesc.Width = depthBufferDesc.Width;
784 resolveTextureDesc.Height = depthBufferDesc.Height;
785 resolveTextureDesc.ArraySize = 1;
786 resolveTextureDesc.MipLevels = 1;
787 resolveTextureDesc.Format = DXGI_FORMAT_R32_FLOAT;
788 resolveTextureDesc.SampleDesc.Count = 1;
789 resolveTextureDesc.SampleDesc.Quality = 0;
790 resolveTextureDesc.Usage = D3D11_USAGE_DEFAULT;
791 resolveTextureDesc.BindFlags = 0;
792 resolveTextureDesc.CPUAccessFlags = 0;
793 resolveTextureDesc.MiscFlags = 0;
794
795 hr = device->CreateTexture2D(&resolveTextureDesc, nullptr, resolvedDepthTexture.internalPointer());
796 if (FAILED(hr)) {
797 LOG_ERROR(logger, "Failed to create depth readback resolve texture (%s): %s", getString(resolveTextureDesc), direct3D11ReturnCodeAsString(hr));
798 return;
799 }
800 else if ((graphicsDevice->getSettings().flags & GraphicsDeviceFlags::EnableTraceLogging) == GraphicsDeviceFlags::EnableTraceLogging) {
801 LOG_TRACE(logger, "Created resource %p: %s", resolvedDepthTexture.get<void>(), getString(resolveTextureDesc));
802 }
803
804 immediateContext->ResolveSubresource(resolvedDepthTexture, 0, fpDepthTexture, 0, resolveTextureDesc.Format);
805 }
806
807 auto & buffer = buffers->buffers[bufferHandle];
808
809 if (!buffer.aliasedTexture || buffer.aliasedWidth != width || buffer.aliasedHeight != height) {
810 D3D11_TEXTURE2D_DESC readTextureDesc{};
811 readTextureDesc.Width = width;
812 readTextureDesc.Height = height;
813 readTextureDesc.ArraySize = 1;
814 readTextureDesc.MipLevels = 1;
815 readTextureDesc.Format = DXGI_FORMAT_R32_TYPELESS;
816 readTextureDesc.SampleDesc.Count = 1;
817 readTextureDesc.SampleDesc.Quality = 0;
818 readTextureDesc.Usage = D3D11_USAGE_STAGING;
819 readTextureDesc.BindFlags = 0;
820 readTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
821 readTextureDesc.MiscFlags = 0;
822
823 hr = device->CreateTexture2D(&readTextureDesc, nullptr, buffer.aliasedTexture.internalPointer());
824 if (FAILED(hr)) {
825 LOG_ERROR(logger, "Failed to create depth readback staging texture (%s): %s", getString(readTextureDesc), direct3D11ReturnCodeAsString(hr));
826 return;
827 }
828 else if ((graphicsDevice->getSettings().flags & GraphicsDeviceFlags::EnableTraceLogging) == GraphicsDeviceFlags::EnableTraceLogging) {
829 LOG_TRACE(logger, "Created resource %p: %s", buffer.aliasedTexture.get<void>(), getString(readTextureDesc));
830 }
831 }
832
833 D3D11_BOX renderBox;
834 renderBox.left = x;
835 renderBox.right = x + width;
836 renderBox.top = y;
837 renderBox.bottom = y + height;
838 renderBox.front = 0;
839 renderBox.back = 1;
840
841 immediateContext->CopySubresourceRegion(buffer.aliasedTexture, 0, 0, 0, 0, isMultisampled ? resolvedDepthTexture : fpDepthTexture, 0, &renderBox);
842}
843
844void Cogs::ContextD3D11::readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer)
845{
846 auto & renderTarget = renderTargets->renderTargets[currentRenderTarget];
847
849 renderTarget.views[0]->GetResource((ID3D11Resource **)&renderTexture);
850
851 D3D11_TEXTURE2D_DESC renderBufferDesc;
852 renderTexture->GetDesc(&renderBufferDesc);
853
854 const bool isMultisampled = renderBufferDesc.SampleDesc.Count > 1;
855 ResourcePointer<ID3D11Texture2D> resolvedRenderTexture;
856
857 if (isMultisampled) {
858 D3D11_TEXTURE2D_DESC resolveTextureDesc{};
859 resolveTextureDesc.Width = renderBufferDesc.Width;
860 resolveTextureDesc.Height = renderBufferDesc.Height;
861 resolveTextureDesc.ArraySize = 1;
862 resolveTextureDesc.MipLevels = 1;
863 resolveTextureDesc.Format = renderBufferDesc.Format;
864 resolveTextureDesc.SampleDesc.Count = 1;
865 resolveTextureDesc.SampleDesc.Quality = 0;
866 resolveTextureDesc.Usage = D3D11_USAGE_DEFAULT;
867 resolveTextureDesc.BindFlags = 0;
868 resolveTextureDesc.CPUAccessFlags = 0;
869 resolveTextureDesc.MiscFlags = 0;
870
871 HRESULT hr = device->CreateTexture2D(&resolveTextureDesc, nullptr, resolvedRenderTexture.internalPointer());
872 if (FAILED(hr)) {
873 LOG_ERROR(logger, "Failed to create readback resolve texture (%s): %s", getString(resolveTextureDesc), direct3D11ReturnCodeAsString(hr));
874 return;
875 }
876 else if ((graphicsDevice->getSettings().flags & GraphicsDeviceFlags::EnableTraceLogging) == GraphicsDeviceFlags::EnableTraceLogging) {
877 LOG_TRACE(logger, "Created resource %p: %s", resolvedRenderTexture.get<void>(), getString(resolveTextureDesc));
878 }
879 immediateContext->ResolveSubresource(resolvedRenderTexture, 0, renderTexture, 0, renderBufferDesc.Format);
880 }
881
882 BufferD3D11 & buffer = buffers->buffers[bufferHandle];
883
884 if (!buffer.aliasedTexture || buffer.aliasedWidth != width || buffer.aliasedHeight != height) {
885 D3D11_TEXTURE2D_DESC renderTextureDesc{};
886 renderTextureDesc.Width = width;
887 renderTextureDesc.Height = height;
888 renderTextureDesc.ArraySize = 1;
889 renderTextureDesc.MipLevels = 1;
890 renderTextureDesc.Format = renderBufferDesc.Format;
891 renderTextureDesc.SampleDesc.Count = 1;
892 renderTextureDesc.SampleDesc.Quality = 0;
893 renderTextureDesc.Usage = D3D11_USAGE_STAGING;
894 renderTextureDesc.BindFlags = 0;
895 renderTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
896 renderTextureDesc.MiscFlags = 0;
897
898 HRESULT hr = device->CreateTexture2D(&renderTextureDesc, nullptr, buffer.aliasedTexture.internalPointer());
899 if (FAILED(hr)) {
900 LOG_ERROR(logger, "Failed to create readback staging texture (%s): %s", getString(renderTextureDesc), direct3D11ReturnCodeAsString(hr));
901 return;
902 }
903 else if ((graphicsDevice->getSettings().flags & GraphicsDeviceFlags::EnableTraceLogging) == GraphicsDeviceFlags::EnableTraceLogging) {
904 LOG_TRACE(logger, "Created resource %p: %s", buffer.aliasedTexture.get<void>(), getString(renderTextureDesc));
905 }
906 buffer.aliasedWidth = width;
907 buffer.aliasedHeight = height;
908 }
909
910 D3D11_BOX renderBox;
911 renderBox.left = x;
912 renderBox.right = x + width;
913 renderBox.top = y;
914 renderBox.bottom = y + height;
915 renderBox.front = 0;
916 renderBox.back = 1;
917
918 immediateContext->CopySubresourceRegion(buffer.aliasedTexture, 0, 0, 0, 0, isMultisampled ? resolvedRenderTexture : renderTexture, 0, &renderBox);
919}
920
921void * Cogs::ContextD3D11::map(BufferHandle bufferHandle, MapMode::EMapMode accessMode, uint32_t * stride)
922{
923 auto & buffer = this->buffers->buffers[bufferHandle];
924
925 D3D11_MAPPED_SUBRESOURCE resource{};
926
927 if (buffer.aliasedTexture && accessMode == MapMode::Read) {
928 HRESULT hr = immediateContext->Map(buffer.aliasedTexture, 0, Direct3D11::MapFlags[accessMode], 0, &resource);
929 buffer.aliasMapped = true;
930 if (stride) {
931 *stride = resource.RowPitch;
932 }
933 if (FAILED(hr)) {
934 LOG_ERROR(logger, "Failed to map alias texture resource %p: %s", buffer.aliasedTexture.get<void>(), direct3D11ReturnCodeAsString(hr));
935 return nullptr;
936 }
937 }
938 else {
939 HRESULT hr = immediateContext->Map(buffer.buffer, 0, Direct3D11::MapFlags[accessMode], 0, &resource);
940 if (FAILED(hr)) {
941 LOG_ERROR(logger, "Failed to map buffer resource %p: %s", buffer.buffer.get<void>(), direct3D11ReturnCodeAsString(hr));
942 return nullptr;
943 }
944 }
945
946 return resource.pData;
947}
948
950{
951 auto & buffer = this->buffers->buffers[bufferHandle];
952
953 if (buffer.aliasMapped) {
954 immediateContext->Unmap(buffer.aliasedTexture, 0);
955 } else {
956 immediateContext->Unmap(buffer.buffer, 0);
957 }
958}
959
960void * Cogs::ContextD3D11::map(TextureHandle textureHandle, MapMode::EMapMode accessMode, uint32_t * rowPitch, uint32_t * depthPitch)
961{
962 auto & texture = textures->textures[textureHandle];
963
964 D3D11_MAPPED_SUBRESOURCE resource{};
965 HRESULT hr = immediateContext->Map(texture.resource(), 0, Direct3D11::MapFlags[accessMode], 0, &resource);
966 if (FAILED(hr)) {
967 LOG_ERROR(logger, "Failed to map texture resource %p: %s", texture.resource(), direct3D11ReturnCodeAsString(hr));
968 return nullptr;
969 }
970 if (rowPitch) *rowPitch = resource.RowPitch;
971 if (depthPitch) *depthPitch = resource.DepthPitch;
972 return resource.pData;
973}
974
976{
977 auto & texture = textures->textures[textureHandle];
978
979 immediateContext->Unmap(texture.resource(), 0);
980}
981
982
983void Cogs::ContextD3D11::updateSubTexture(TextureHandle textureHandle, const size_t level, const void * data)
984{
985 assert(HandleIsValid(textureHandle) && "Texture handle must be a valid texture.");
986
987 auto & texture = this->textures->textures[textureHandle];
988
989 const uint32_t width = Cogs::getMipSize(texture.width, static_cast<uint32_t>(level));
990 const uint32_t height = Cogs::getMipSize(texture.height, static_cast<uint32_t>(level));
991
992 D3D11_BOX rectangle;
993 rectangle.left = 0;
994 rectangle.right = width;
995 rectangle.top = 0;
996 rectangle.bottom = height;
997 rectangle.front = 0;
998 rectangle.back = 1;
999
1000 // Copy the image data into the given mipmap level in the texture.
1001 immediateContext->UpdateSubresource(texture.resource(), static_cast<UINT>(level), &rectangle, data, width * static_cast<uint32_t>(getBlockSize(texture.format)), 1);
1002 if(uploadStatisticsEnabled){
1003 TextureExtent extent = getBlockExtent(texture.format);
1004 size_t size = width * height * getBlockSize(texture.format);
1005 uploadStatisticsTextureUpload(size);
1006 }
1007}
1008
1009void Cogs::ContextD3D11::updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void * data)
1010{
1011 assert(HandleIsValid(bufferHandle) && "Buffer handle must point to a valid buffer.");
1012
1013 auto & buffer = this->buffers->buffers[bufferHandle];
1014
1015 assert(buffer.size >= offset + size && "Buffer size not sufficient to hold data.");
1016
1017 D3D11_BOX rectangle;
1018 rectangle.left = static_cast<UINT>(offset);
1019 rectangle.right = static_cast<UINT>(offset + size);
1020 rectangle.top = 0;
1021 rectangle.bottom = 1;
1022 rectangle.front = 0;
1023 rectangle.back = 1;
1024
1025 immediateContext->UpdateSubresource(buffer.buffer, 0u, &rectangle, data, 0, 0);
1026 if(uploadStatisticsEnabled) uploadStatisticsBufferUpload(size);
1027}
1028
1029void Cogs::ContextD3D11::copyResource(BufferHandle destinationHandle, BufferHandle sourceHandle)
1030{
1031 auto & destination = buffers->buffers[destinationHandle];
1032 auto & source = buffers->buffers[sourceHandle];
1033
1034 immediateContext->CopyResource(destination.buffer, source.buffer);
1035}
1036
1037void Cogs::ContextD3D11::copyResource(TextureHandle destinationHandle, TextureHandle sourceHandle)
1038{
1039 auto & destination = textures->textures[destinationHandle];
1040 auto & source = textures->textures[sourceHandle];
1041
1042 immediateContext->CopyResource(destination.resource(), source.resource());
1043}
1044
1045void Cogs::ContextD3D11::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle sourceHandle, unsigned srcSub)
1046{
1047 auto & destination = textures->textures[dstHandle];
1048 auto & source = textures->textures[sourceHandle];
1049 immediateContext->CopySubresourceRegion(destination.resource(), dstSub,
1050 dstX, dstY, dstZ,
1051 source.resource(), srcSub, NULL);
1052}
1053
1054void Cogs::ContextD3D11::clearResource(BufferHandle destinationHandle, uint32_t *Values)
1055{
1056 auto & destination = buffers->buffers[destinationHandle];
1057 immediateContext->ClearUnorderedAccessViewUint(destination.uav, Values);
1058}
1059
1060void Cogs::ContextD3D11::clearResource(BufferHandle destinationHandle, float *Values)
1061{
1062 auto & destination = buffers->buffers[destinationHandle];
1063 immediateContext->ClearUnorderedAccessViewFloat(destination.uav, Values);
1064}
1065
1066void Cogs::ContextD3D11::setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
1067{
1068 if (isCompute) {
1069 const uint32_t csSlot = decode(textureBindingHandle.handle);
1070
1071 if (HandleIsValid(textureHandle)) {
1072 auto & texture = textures->textures[textureHandle];
1073
1074 if (texture.unorderedAccessView) {
1075 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &texture.unorderedAccessView, nullptr);
1076 } else {
1077 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &texture.shaderResourceView);
1078 }
1079 } else {
1080 ID3D11UnorderedAccessView * view = nullptr;
1081 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &view, nullptr);
1082 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1083 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &shaderResourceView);
1084 }
1085 } else {
1086 uint32_t slots[ShaderType::NumShaderTypes];
1087 decode(textureBindingHandle.handle, slots);
1088
1089 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1090 if (HandleIsValid(textureHandle)) {
1091 shaderResourceView = textures->textures[textureHandle].shaderResourceView;
1092 }
1093 setShaderResources(slots, &shaderResourceView);
1094
1095 }
1096}
1097void Cogs::ContextD3D11::setShaderResources(uint32_t * slots, ID3D11ShaderResourceView *const *ppShaderResourceViews) {
1098 if (slots[0] != NoBinding11) immediateContext->VSSetShaderResources(slots[0], 1, ppShaderResourceViews);
1099 if (slots[1] != NoBinding11) immediateContext->HSSetShaderResources(slots[1], 1, ppShaderResourceViews);
1100 if (slots[2] != NoBinding11) immediateContext->DSSetShaderResources(slots[2], 1, ppShaderResourceViews);
1101 if (slots[3] != NoBinding11) immediateContext->GSSetShaderResources(slots[3], 1, ppShaderResourceViews);
1102 if (slots[4] != NoBinding11) immediateContext->PSSetShaderResources(slots[4], 1, ppShaderResourceViews);
1103
1104 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
1105 if (slots[i] != NoBinding11) {
1106 state.dirtySRV[i] = std::max(state.dirtySRV[i], slots[i] + 1);
1107 }
1108 }
1109}
1110
1111void Cogs::ContextD3D11::setTexture(const TextureBindingHandle textureBindingHandle, TextureViewHandle textureViewHandle)
1112{
1113 auto & view = textures->textureViews[textureViewHandle];
1114 auto & textureHandle = view.texture;
1115
1116 if (isCompute) {
1117 const uint32_t csSlot = decode(textureBindingHandle.handle);
1118
1119 if (HandleIsValid(textureHandle)) {
1120 auto & texture = textures->textures[textureHandle];
1121
1122 if (texture.unorderedAccessView) {
1123 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &texture.unorderedAccessView, nullptr);
1124 } else {
1125 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &view.shaderResourceView);
1126 }
1127 } else {
1128 ID3D11UnorderedAccessView * unorderedAccessView = nullptr;
1129 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &unorderedAccessView, nullptr);
1130 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1131 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &shaderResourceView);
1132 }
1133 } else {
1134 uint32_t slots[ShaderType::NumShaderTypes];
1135 decode(textureBindingHandle.handle, slots);
1136
1137 ID3D11ShaderResourceView * shaderResourceView = view.shaderResourceView;
1138 setShaderResources(slots, &shaderResourceView);
1139 }
1140}
1141
1142void Cogs::ContextD3D11::setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle)
1143{
1144 if (isCompute) {
1145 const uint32_t csSlot = decode(samplerStateBindingHandle.handle);
1146
1147 if (HandleIsValid(samplerStateHandle)) {
1148 auto & samplerState = textures->samplerStates[samplerStateHandle];
1149
1150 if (csSlot != NoBinding11) immediateContext->CSSetSamplers(csSlot, 1, &samplerState);
1151 } else {
1152 ID3D11SamplerState * samplerState = nullptr;
1153 if (csSlot != NoBinding11) immediateContext->CSSetSamplers(csSlot, 1, &samplerState);
1154 }
1155 } else {
1156 uint32_t slots[ShaderType::NumShaderTypes];
1157 decode(samplerStateBindingHandle.handle, slots);
1158
1159 auto & samplerState = textures->samplerStates[HandleIsValid(samplerStateHandle) ? samplerStateHandle : defaultSamplerState];
1160
1161 if (slots[0] != NoBinding11) immediateContext->VSSetSamplers(slots[0], 1, &samplerState);
1162 if (slots[1] != NoBinding11) immediateContext->HSSetSamplers(slots[1], 1, &samplerState);
1163 if (slots[2] != NoBinding11) immediateContext->DSSetSamplers(slots[2], 1, &samplerState);
1164 if (slots[3] != NoBinding11) immediateContext->GSSetSamplers(slots[3], 1, &samplerState);
1165 if (slots[4] != NoBinding11) immediateContext->PSSetSamplers(slots[4], 1, &samplerState);
1166 }
1167}
1168
1169void Cogs::ContextD3D11::setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle)
1170{
1171 auto & buffer = buffers->buffers[bufferHandle];
1172 auto & binding = effects->bufferBindings[bufferBindingHandle];
1173
1174 if (isCompute) {
1175 //TODO: Implement CS Support. 2015-08-11, oyshole.
1176 const uint32_t csSlot = static_cast<uint32_t>(binding.uavBindings);
1177 if (csSlot != NoBinding11) {
1178 uavs[csSlot] = buffer.uav;
1179 uavCounts[csSlot] = buffer.uavCount;
1180 minUavSlot = std::min(minUavSlot, csSlot);
1181 maxUavSlot = std::max(maxUavSlot, csSlot);
1182 uavDirty = true;
1183
1184 updateRenderTargets();
1185
1186 uavCounts[csSlot] = ~0u;
1187 buffer.uavCount = ~0u;
1188 }
1189
1190 } else {
1191 {
1192 uint32_t slots[ShaderType::NumShaderTypes];
1193 decode(binding.uavBindings, slots);
1194
1195 uint32_t psSlot = slots[ShaderType::PixelShader];
1196
1197 if (psSlot != NoBinding11) {
1198 uavs[psSlot] = buffer.uav;
1199 uavCounts[psSlot] = buffer.uavCount;
1200 minUavSlot = std::min(minUavSlot, psSlot);
1201 maxUavSlot = std::max(maxUavSlot, psSlot);
1202 uavDirty = true;
1203
1204 updateRenderTargets();
1205
1206 uavCounts[psSlot] = ~0u;
1207 buffer.uavCount = ~0u;
1208 }
1209 }
1210
1211 {
1212 uint32_t slots[ShaderType::NumShaderTypes];
1213 decode(binding.srvBindings, slots);
1214
1215 setShaderResources(slots, &buffer.srv);
1216 }
1217 }
1218}
1219
1220void Cogs::ContextD3D11::setBufferCounter(BufferHandle bufferHandle, uint32_t value)
1221{
1222 auto & buffer = buffers->buffers[bufferHandle];
1223
1224 buffer.uavCount = value;
1225}
1226
1227void Cogs::ContextD3D11::setBufferCounter(BufferHandle /*bufferHandle*/, BufferHandle /*sourceBufferHandle*/)
1228{
1229 // Noop
1230}
1231
1232void Cogs::ContextD3D11::getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
1233{
1234 auto & buffer = buffers->buffers[bufferHandle];
1235 auto & dstBuffer = buffers->buffers[destinationBufferHandle];
1236
1237 immediateContext->CopyStructureCount(dstBuffer.buffer, 0, buffer.uav);
1238}
1239
1241{
1242 auto dstBuffer = buffers->loadBuffer(nullptr, 4, Usage::Dynamic, AccessMode::Read, BindFlags::None);
1243
1244 getBufferCounter(bufferHandle, dstBuffer);
1245
1246 MappedBuffer<uint32_t> mapped(this, dstBuffer);
1247
1248 return mapped ? *mapped : 0;
1249}
1250
1251void Cogs::ContextD3D11::resetSRVBindings()
1252{
1253 ID3D11ShaderResourceView * resourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { 0 };
1254 if (state.dirtySRV[ShaderType::VertexShader]) immediateContext->VSSetShaderResources(0, state.dirtySRV[ShaderType::VertexShader], resourceViews);
1255 if (state.dirtySRV[ShaderType::GeometryShader]) immediateContext->GSSetShaderResources(0, state.dirtySRV[ShaderType::GeometryShader], resourceViews);
1256 if (state.dirtySRV[ShaderType::PixelShader]) immediateContext->PSSetShaderResources(0, state.dirtySRV[ShaderType::PixelShader], resourceViews);
1257 if (state.dirtySRV[ShaderType::ComputeShader]) immediateContext->CSSetShaderResources(0, state.dirtySRV[ShaderType::ComputeShader], resourceViews);
1258
1259 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
1260 state.dirtySRV[i] = 0;
1261 }
1262}
1263
1264void Cogs::ContextD3D11::updateRenderTargets()
1265{
1266 ID3D11RenderTargetView * views[kMaxRenderTargets11];
1267
1268 if (isCompute) {
1269 if ((minUavSlot <= maxUavSlot) && uavDirty) {
1270 immediateContext->CSSetUnorderedAccessViews(minUavSlot,
1271 maxUavSlot - minUavSlot + 1,
1272 uavs + minUavSlot,
1273 uavCounts + minUavSlot);
1274
1275 uavDirty = false;
1276 }
1277 } else {
1278 uint32_t numViews = 0;
1279 if (HandleIsValid(currentRenderTarget)) {
1280 RenderTargetD3D11& renderTarget = renderTargets->renderTargets[currentRenderTarget];
1281 numViews = static_cast<uint32_t>(renderTarget.numViews);
1282 for (uint32_t i = 0; i < renderTarget.numViews; ++i) {
1283 views[i] = renderTarget.views[i];
1284 }
1285 }
1286
1287 ID3D11DepthStencilView * depthStencilView = nullptr;
1288 if (HandleIsValid(currentDepthStencil)) {
1289 depthStencilView = renderTargets->depthStencilViews[currentDepthStencil];
1290 }
1291
1292 if ((minUavSlot <= maxUavSlot) && uavDirty) {
1293 immediateContext->OMSetRenderTargetsAndUnorderedAccessViews(static_cast<UINT>(numViews),
1294 views,
1295 depthStencilView,
1296 minUavSlot,
1297 maxUavSlot - minUavSlot + 1,
1298 uavs + minUavSlot,
1299 uavCounts + minUavSlot);
1300
1301 uavDirty = false;
1302 } else {
1303 immediateContext->OMSetRenderTargets(numViews, views, depthStencilView);
1304 }
1305 }
1306}
1307
1308void Cogs::ContextD3D11::setupConstantBuffers()
1309{
1310 ContextCommon::updateConstantBuffers();
1311
1312 auto & effect = effects->effects[currentEffect];
1313
1314 for (auto & constantBuffer : effect.vertexShader.reflection.constantBuffers) {
1315 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.vsCBs[constantBuffer.slot]) {
1316 immediateContext->VSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1317 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
1318 }
1319 }
1320
1321 for (auto & constantBuffer : effect.hullShader.reflection.constantBuffers) {
1322 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1323 immediateContext->HSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1324 }
1325 }
1326
1327 for (auto & constantBuffer : effect.domainShader.reflection.constantBuffers) {
1328 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1329 immediateContext->DSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1330 }
1331 }
1332
1333 for (auto & constantBuffer : effect.geometryShader.reflection.constantBuffers) {
1334 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1335 immediateContext->GSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1336 }
1337 }
1338
1339 for (auto & constantBuffer : effect.pixelShader.reflection.constantBuffers) {
1340 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.psCBs[constantBuffer.slot]) {
1341 immediateContext->PSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1342 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1343 }
1344 }
1345
1346 for (auto & constantBuffer : effect.computeShader.reflection.constantBuffers) {
1347 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1348 immediateContext->CSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1349 }
1350 }
1351
1352 constantBuffersUpdated = true;
1353}
1354
1355void Cogs::ContextD3D11::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
1356{
1357 this->setupConstantBuffers();
1358
1359 immediateContext->Dispatch(threadGroupsX, threadGroupsY, threadGroupsZ);
1360}
Log implementation class.
Definition: LogManager.h:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr iterator begin() noexcept
Iterator to the beginning of the string.
Definition: StringView.h:100
constexpr iterator end() noexcept
Iterator to the end of the string.
Definition: StringView.h:103
virtual const DepthStencilHandle & getDepthStencil() const override
Returns the depth stencil managed by this swap chain.
virtual const RenderTargetHandle & getRenderTarget() const override
Returns the render target managed by this swap chain.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
const DXGI_FORMAT Formats[]
Must match up to Format definition.
Definition: FormatsD3D11.cpp:6
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ Direct3D11
Graphics device using the Direct3D 11 API.
@ EnableTraceLogging
Enables trace logging.
@ Read
The buffer can be mapped and read from by the CPU after creation.
Definition: Flags.h:48
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
Definition: Flags.h:70
@ None
The buffer will not be bound to the graphics pipeline. Suitable for staging resources.
Definition: Flags.h:66
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
Definition: BlendState.h:55
void updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void *data) override
Update a region of data in a buffer.
void pushCommandGroupAnnotation(const StringView &name) override
Begin to tag a sequence of commands as a group in graphics debugger.
void resolveResource(TextureHandle sourceTexture, TextureHandle destination)
Resolves the given source resource target into the given destination texture.
void setBufferCounter(BufferHandle bufferHandle, uint32_t value)
Set the associated counter of a buffer.
void draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
Draws non-indexed, non-instanced primitives.
void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
void setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle)
Sets the sampler state binding given to the given sampler state.
void setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle)
Sets a buffer to bind to the given binding.
void setBlendState(const BlendStateHandle handle, const float *constant) override
Set the current blend state.
void readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer)
Reads data from the current depth target into the given bufferHandle.
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
Sets the texture given to the binding given by textureBindingHandle.
void drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
Draws indexed, instanced primitives.
void setRasterizerState(const RasterizerStateHandle handle)
Set the current rasterizer state.
void updateSubTexture(TextureHandle textureHandle, const size_t level, const void *data)
Update the data of a level in the given texture.
void setEffect(EffectHandle handle)
Set the current effect.
void popCommandGroupAnnotation() override
End to tag a sequence of commands as a group in graphics debugger.
void setDepthStencilState(const DepthStencilStateHandle handle)
Set the current depth stencil state.
void endRenderPass() override
End a render pass.
void setInputLayout(const InputLayoutHandle inputLayoutHandle)
Sets the current input layout.
void getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
Get the associated counter of a buffer.
void unmap(BufferHandle bufferHandle)
Unmaps the given buffer, applying any synchronization necessary to reflect changes in the mapped memo...
void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0)
Draws indexed, non-instanced primitives.
void * map(BufferHandle bufferHandle, MapMode::EMapMode accessMode, uint32_t *stride)
Maps the given buffer so it can be accessed.
void signal(FenceHandle fenceHandle) override
Insert a fence in the command stream that will signal when all commands before the fence are complete...
void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets)
Sets the current vertex buffers.
void setScissor(const int x, const int y, const int width, const int height)
Sets the current scissor rectangle.
void dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
Dispatch computing work on the graphics device using the desired thread group count.
void clearDepth(const float depth=1.0f)
Clear the currently set depth/stencil target to the given depth.
void beginRenderPass(const RenderPassInfo &info) override
Begin a render pass.
void setViewport(const float x, const float y, const float width, const float height)
Sets the current viewport to the given location and dimensions.
void setIndexBuffer(IndexBufferHandle indexBufferHandle, uint32_t stride, uint32_t offset)
Sets the current index buffer.
void drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
Draws non-indexed, instanced primitives.
void clearRenderTarget(const float *value)
Clear the currently set render target to the given value (4 component floating point RGBA).
void readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer)
Reads data from the current render target into the given bufferHandle.
void setAnnotationMarker(const StringView &name) override
Add a tag in the sequence of commands in graphics debugger.
void setConstantBuffer(const ConstantBufferBindingHandle bufferBinding, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size)
Sets a constant buffer to the given constant buffer binding.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
Handle template class used to provide opaque, non-converting handles.
Definition: Common.h:22
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
handle_type handle
Internal resource handle.
Definition: Common.h:74
EMapMode
Mapping mode enumeration.
Definition: Flags.h:93
Provides RAII style mapping of a buffer resource.
Definition: IBuffers.h:160
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
Definition: SamplerState.h:85
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30