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 primitiveType, const size_t startVertex, const size_t numVertexes)
432{
433 if (state.primitiveType != primitiveType) {
434 state.primitiveType = primitiveType;
435 immediateContext->IASetPrimitiveTopology(Direct3D11::Topologies[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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)
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)
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 const Cogs::FormatInfo *textureFormat = Cogs::getFormatInfo(texture.format);
1001 size_t bytesPerRow = textureFormat->blockSize * ((width + textureFormat->blockExtent.width - 1) / textureFormat->blockExtent.width);
1002
1003 // Copy the image data into the given mipmap level in the texture.
1004 immediateContext->UpdateSubresource(texture.resource(), static_cast<UINT>(level), &rectangle, data, static_cast<UINT>(bytesPerRow), 1);
1005 if(uploadStatisticsEnabled){
1006 TextureExtent extent = getBlockExtent(texture.format);
1007 size_t size = width * height * getBlockSize(texture.format);
1008 uploadStatisticsTextureUpload(size);
1009 }
1010}
1011
1012void Cogs::ContextD3D11::updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void * data)
1013{
1014 assert(HandleIsValid(bufferHandle) && "Buffer handle must point to a valid buffer.");
1015
1016 auto & buffer = this->buffers->buffers[bufferHandle];
1017
1018 assert(buffer.size >= offset + size && "Buffer size not sufficient to hold data.");
1019
1020 D3D11_BOX rectangle;
1021 rectangle.left = static_cast<UINT>(offset);
1022 rectangle.right = static_cast<UINT>(offset + size);
1023 rectangle.top = 0;
1024 rectangle.bottom = 1;
1025 rectangle.front = 0;
1026 rectangle.back = 1;
1027
1028 immediateContext->UpdateSubresource(buffer.buffer, 0u, &rectangle, data, 0, 0);
1029 if(uploadStatisticsEnabled) uploadStatisticsBufferUpload(size);
1030}
1031
1032void Cogs::ContextD3D11::copyResource(BufferHandle destinationHandle, BufferHandle sourceHandle)
1033{
1034 auto & destination = buffers->buffers[destinationHandle];
1035 auto & source = buffers->buffers[sourceHandle];
1036
1037 immediateContext->CopyResource(destination.buffer, source.buffer);
1038}
1039
1040void Cogs::ContextD3D11::copyResource(TextureHandle destinationHandle, TextureHandle sourceHandle)
1041{
1042 auto & destination = textures->textures[destinationHandle];
1043 auto & source = textures->textures[sourceHandle];
1044
1045 immediateContext->CopyResource(destination.resource(), source.resource());
1046}
1047
1048void Cogs::ContextD3D11::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle sourceHandle, unsigned srcSub)
1049{
1050 auto & destination = textures->textures[dstHandle];
1051 auto & source = textures->textures[sourceHandle];
1052 immediateContext->CopySubresourceRegion(destination.resource(), dstSub,
1053 dstX, dstY, dstZ,
1054 source.resource(), srcSub, NULL);
1055}
1056
1057void Cogs::ContextD3D11::clearResource(BufferHandle destinationHandle, uint32_t *Values)
1058{
1059 auto & destination = buffers->buffers[destinationHandle];
1060 immediateContext->ClearUnorderedAccessViewUint(destination.uav, Values);
1061}
1062
1063void Cogs::ContextD3D11::clearResource(BufferHandle destinationHandle, float *Values)
1064{
1065 auto & destination = buffers->buffers[destinationHandle];
1066 immediateContext->ClearUnorderedAccessViewFloat(destination.uav, Values);
1067}
1068
1069void Cogs::ContextD3D11::setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
1070{
1071 if (isCompute) {
1072 const uint32_t csSlot = decode(textureBindingHandle.handle);
1073
1074 if (HandleIsValid(textureHandle)) {
1075 auto & texture = textures->textures[textureHandle];
1076
1077 if (texture.unorderedAccessView) {
1078 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &texture.unorderedAccessView, nullptr);
1079 } else {
1080 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &texture.shaderResourceView);
1081 }
1082 } else {
1083 ID3D11UnorderedAccessView * view = nullptr;
1084 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &view, nullptr);
1085 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1086 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &shaderResourceView);
1087 }
1088 } else {
1089 uint32_t slots[ShaderType::NumShaderTypes];
1090 decode(textureBindingHandle.handle, slots);
1091
1092 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1093 if (HandleIsValid(textureHandle)) {
1094 shaderResourceView = textures->textures[textureHandle].shaderResourceView;
1095 }
1096 setShaderResources(slots, &shaderResourceView);
1097
1098 }
1099}
1100void Cogs::ContextD3D11::setShaderResources(uint32_t * slots, ID3D11ShaderResourceView *const *ppShaderResourceViews) {
1101 if (slots[0] != NoBinding11) immediateContext->VSSetShaderResources(slots[0], 1, ppShaderResourceViews);
1102 if (slots[1] != NoBinding11) immediateContext->HSSetShaderResources(slots[1], 1, ppShaderResourceViews);
1103 if (slots[2] != NoBinding11) immediateContext->DSSetShaderResources(slots[2], 1, ppShaderResourceViews);
1104 if (slots[3] != NoBinding11) immediateContext->GSSetShaderResources(slots[3], 1, ppShaderResourceViews);
1105 if (slots[4] != NoBinding11) immediateContext->PSSetShaderResources(slots[4], 1, ppShaderResourceViews);
1106
1107 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
1108 if (slots[i] != NoBinding11) {
1109 state.dirtySRV[i] = std::max(state.dirtySRV[i], slots[i] + 1);
1110 }
1111 }
1112}
1113
1114void Cogs::ContextD3D11::setTexture(const TextureBindingHandle textureBindingHandle, TextureViewHandle textureViewHandle)
1115{
1116 auto & view = textures->textureViews[textureViewHandle];
1117 auto & textureHandle = view.texture;
1118
1119 if (isCompute) {
1120 const uint32_t csSlot = decode(textureBindingHandle.handle);
1121
1122 if (HandleIsValid(textureHandle)) {
1123 auto & texture = textures->textures[textureHandle];
1124
1125 if (texture.unorderedAccessView) {
1126 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &texture.unorderedAccessView, nullptr);
1127 } else {
1128 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &view.shaderResourceView);
1129 }
1130 } else {
1131 ID3D11UnorderedAccessView * unorderedAccessView = nullptr;
1132 if (csSlot != NoBinding11) immediateContext->CSSetUnorderedAccessViews(csSlot, 1, &unorderedAccessView, nullptr);
1133 ID3D11ShaderResourceView * shaderResourceView = nullptr;
1134 if (csSlot != NoBinding11) immediateContext->CSSetShaderResources(csSlot, 1, &shaderResourceView);
1135 }
1136 } else {
1137 uint32_t slots[ShaderType::NumShaderTypes];
1138 decode(textureBindingHandle.handle, slots);
1139
1140 ID3D11ShaderResourceView * shaderResourceView = view.shaderResourceView;
1141 setShaderResources(slots, &shaderResourceView);
1142 }
1143}
1144
1145void Cogs::ContextD3D11::setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle)
1146{
1147 if (isCompute) {
1148 const uint32_t csSlot = decode(samplerStateBindingHandle.handle);
1149
1150 if (HandleIsValid(samplerStateHandle)) {
1151 auto & samplerState = textures->samplerStates[samplerStateHandle];
1152
1153 if (csSlot != NoBinding11) immediateContext->CSSetSamplers(csSlot, 1, &samplerState);
1154 } else {
1155 ID3D11SamplerState * samplerState = nullptr;
1156 if (csSlot != NoBinding11) immediateContext->CSSetSamplers(csSlot, 1, &samplerState);
1157 }
1158 } else {
1159 uint32_t slots[ShaderType::NumShaderTypes];
1160 decode(samplerStateBindingHandle.handle, slots);
1161
1162 auto & samplerState = textures->samplerStates[HandleIsValid(samplerStateHandle) ? samplerStateHandle : defaultSamplerState];
1163
1164 if (slots[0] != NoBinding11) immediateContext->VSSetSamplers(slots[0], 1, &samplerState);
1165 if (slots[1] != NoBinding11) immediateContext->HSSetSamplers(slots[1], 1, &samplerState);
1166 if (slots[2] != NoBinding11) immediateContext->DSSetSamplers(slots[2], 1, &samplerState);
1167 if (slots[3] != NoBinding11) immediateContext->GSSetSamplers(slots[3], 1, &samplerState);
1168 if (slots[4] != NoBinding11) immediateContext->PSSetSamplers(slots[4], 1, &samplerState);
1169 }
1170}
1171
1172void Cogs::ContextD3D11::setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle)
1173{
1174 auto & buffer = buffers->buffers[bufferHandle];
1175 auto & binding = effects->bufferBindings[bufferBindingHandle];
1176
1177 if (isCompute) {
1178 //TODO: Implement CS Support. 2015-08-11, oyshole.
1179 const uint32_t csSlot = static_cast<uint32_t>(binding.uavBindings);
1180 if (csSlot != NoBinding11) {
1181 uavs[csSlot] = buffer.uav;
1182 uavCounts[csSlot] = buffer.uavCount;
1183 minUavSlot = std::min(minUavSlot, csSlot);
1184 maxUavSlot = std::max(maxUavSlot, csSlot);
1185 uavDirty = true;
1186
1187 updateRenderTargets();
1188
1189 uavCounts[csSlot] = ~0u;
1190 buffer.uavCount = ~0u;
1191 }
1192
1193 } else {
1194 {
1195 uint32_t slots[ShaderType::NumShaderTypes];
1196 decode(binding.uavBindings, slots);
1197
1198 uint32_t psSlot = slots[ShaderType::PixelShader];
1199
1200 if (psSlot != NoBinding11) {
1201 uavs[psSlot] = buffer.uav;
1202 uavCounts[psSlot] = buffer.uavCount;
1203 minUavSlot = std::min(minUavSlot, psSlot);
1204 maxUavSlot = std::max(maxUavSlot, psSlot);
1205 uavDirty = true;
1206
1207 updateRenderTargets();
1208
1209 uavCounts[psSlot] = ~0u;
1210 buffer.uavCount = ~0u;
1211 }
1212 }
1213
1214 {
1215 uint32_t slots[ShaderType::NumShaderTypes];
1216 decode(binding.srvBindings, slots);
1217
1218 setShaderResources(slots, &buffer.srv);
1219 }
1220 }
1221}
1222
1223void Cogs::ContextD3D11::setBufferCounter(BufferHandle bufferHandle, uint32_t value)
1224{
1225 auto & buffer = buffers->buffers[bufferHandle];
1226
1227 buffer.uavCount = value;
1228}
1229
1230void Cogs::ContextD3D11::setBufferCounter(BufferHandle /*bufferHandle*/, BufferHandle /*sourceBufferHandle*/)
1231{
1232 // Noop
1233}
1234
1235void Cogs::ContextD3D11::getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
1236{
1237 auto & buffer = buffers->buffers[bufferHandle];
1238 auto & dstBuffer = buffers->buffers[destinationBufferHandle];
1239
1240 immediateContext->CopyStructureCount(dstBuffer.buffer, 0, buffer.uav);
1241}
1242
1244{
1245 auto dstBuffer = buffers->loadBuffer(nullptr, 4, Usage::Dynamic, AccessMode::Read, BindFlags::None);
1246
1247 getBufferCounter(bufferHandle, dstBuffer);
1248
1249 MappedBuffer<uint32_t> mapped(this, dstBuffer);
1250
1251 return mapped ? *mapped : 0;
1252}
1253
1254void Cogs::ContextD3D11::resetSRVBindings()
1255{
1256 ID3D11ShaderResourceView * resourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { 0 };
1257 if (state.dirtySRV[ShaderType::VertexShader]) immediateContext->VSSetShaderResources(0, state.dirtySRV[ShaderType::VertexShader], resourceViews);
1258 if (state.dirtySRV[ShaderType::GeometryShader]) immediateContext->GSSetShaderResources(0, state.dirtySRV[ShaderType::GeometryShader], resourceViews);
1259 if (state.dirtySRV[ShaderType::PixelShader]) immediateContext->PSSetShaderResources(0, state.dirtySRV[ShaderType::PixelShader], resourceViews);
1260 if (state.dirtySRV[ShaderType::ComputeShader]) immediateContext->CSSetShaderResources(0, state.dirtySRV[ShaderType::ComputeShader], resourceViews);
1261
1262 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
1263 state.dirtySRV[i] = 0;
1264 }
1265}
1266
1267void Cogs::ContextD3D11::updateRenderTargets()
1268{
1269 ID3D11RenderTargetView * views[kMaxRenderTargets11];
1270
1271 if (isCompute) {
1272 if ((minUavSlot <= maxUavSlot) && uavDirty) {
1273 immediateContext->CSSetUnorderedAccessViews(minUavSlot,
1274 maxUavSlot - minUavSlot + 1,
1275 uavs + minUavSlot,
1276 uavCounts + minUavSlot);
1277
1278 uavDirty = false;
1279 }
1280 } else {
1281 uint32_t numViews = 0;
1282 if (HandleIsValid(currentRenderTarget)) {
1283 RenderTargetD3D11& renderTarget = renderTargets->renderTargets[currentRenderTarget];
1284 numViews = static_cast<uint32_t>(renderTarget.numViews);
1285 for (uint32_t i = 0; i < renderTarget.numViews; ++i) {
1286 views[i] = renderTarget.views[i];
1287 }
1288 }
1289
1290 ID3D11DepthStencilView * depthStencilView = nullptr;
1291 if (HandleIsValid(currentDepthStencil)) {
1292 depthStencilView = renderTargets->depthStencilViews[currentDepthStencil];
1293 }
1294
1295 if ((minUavSlot <= maxUavSlot) && uavDirty) {
1296 immediateContext->OMSetRenderTargetsAndUnorderedAccessViews(static_cast<UINT>(numViews),
1297 views,
1298 depthStencilView,
1299 minUavSlot,
1300 maxUavSlot - minUavSlot + 1,
1301 uavs + minUavSlot,
1302 uavCounts + minUavSlot);
1303
1304 uavDirty = false;
1305 } else {
1306 immediateContext->OMSetRenderTargets(numViews, views, depthStencilView);
1307 }
1308 }
1309}
1310
1311void Cogs::ContextD3D11::setupConstantBuffers()
1312{
1313 ContextCommon::updateConstantBuffers();
1314
1315 auto & effect = effects->effects[currentEffect];
1316
1317 for (auto & constantBuffer : effect.vertexShader.reflection.constantBuffers) {
1318 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.vsCBs[constantBuffer.slot]) {
1319 immediateContext->VSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1320 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
1321 }
1322 }
1323
1324 for (auto & constantBuffer : effect.hullShader.reflection.constantBuffers) {
1325 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1326 immediateContext->HSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1327 }
1328 }
1329
1330 for (auto & constantBuffer : effect.domainShader.reflection.constantBuffers) {
1331 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1332 immediateContext->DSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1333 }
1334 }
1335
1336 for (auto & constantBuffer : effect.geometryShader.reflection.constantBuffers) {
1337 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1338 immediateContext->GSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1339 }
1340 }
1341
1342 for (auto & constantBuffer : effect.pixelShader.reflection.constantBuffers) {
1343 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.psCBs[constantBuffer.slot]) {
1344 immediateContext->PSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1345 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1346 }
1347 }
1348
1349 for (auto & constantBuffer : effect.computeShader.reflection.constantBuffers) {
1350 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual) {
1351 immediateContext->CSSetConstantBuffers(constantBuffer.slot, 1, &buffers->buffers[constantBuffer.buffer].buffer);
1352 }
1353 }
1354
1355 constantBuffersUpdated = true;
1356}
1357
1358void Cogs::ContextD3D11::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
1359{
1360 this->setupConstantBuffers();
1361
1362 immediateContext->Dispatch(threadGroupsX, threadGroupsY, threadGroupsZ);
1363}
Log implementation class.
Definition: LogManager.h:140
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:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ Direct3D11
Graphics device using the Direct3D 11 API.
Framebuffer
Framebuffers to select from when doing framebuffer operations.
Definition: Common.h:147
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
Definition: Common.h:112
@ 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 readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer framebuffer)
Reads data from the current depth target into the given bufferHandle.
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 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 drawInstancedIndexed(PrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
Draws indexed, instanced primitives.
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
Sets the texture given to the binding given by textureBindingHandle.
void setRasterizerState(const RasterizerStateHandle handle)
Set the current rasterizer state.
void draw(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
Draws non-indexed, non-instanced primitives.
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 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 drawInstanced(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
Draws non-indexed, instanced primitives.
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 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 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.
uint8_t blockSize
Bytesize of one block of data.
Definition: DataFormat.h:257
TextureExtent blockExtent
Number of data items in a block.
Definition: DataFormat.h:258
Handle template class used to provide opaque, non-converting handles.
Definition: Common.h:23
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
handle_type handle
Internal resource handle.
Definition: Common.h:75
EMapMode
Mapping mode enumeration.
Definition: Flags.h:93
Provides RAII style mapping of a buffer resource.
Definition: IBuffers.h:160
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