Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/d3d11_pipeline.cpp
4214 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "d3d11_pipeline.h"
5
#include "d3d11_device.h"
6
#include "d3d11_texture.h"
7
#include "d3d_common.h"
8
9
#include "common/assert.h"
10
#include "common/error.h"
11
#include "common/hash_combine.h"
12
13
#include "fmt/format.h"
14
15
#include <array>
16
#include <malloc.h>
17
18
D3D11Shader::D3D11Shader(GPUShaderStage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader,
19
std::vector<u8> bytecode)
20
: GPUShader(stage), m_shader(std::move(shader)), m_bytecode(std::move(bytecode))
21
{
22
}
23
24
D3D11Shader::~D3D11Shader() = default;
25
26
ID3D11VertexShader* D3D11Shader::GetVertexShader() const
27
{
28
DebugAssert(m_stage == GPUShaderStage::Vertex);
29
return static_cast<ID3D11VertexShader*>(m_shader.Get());
30
}
31
32
ID3D11PixelShader* D3D11Shader::GetPixelShader() const
33
{
34
DebugAssert(m_stage == GPUShaderStage::Fragment);
35
return static_cast<ID3D11PixelShader*>(m_shader.Get());
36
}
37
38
ID3D11GeometryShader* D3D11Shader::GetGeometryShader() const
39
{
40
DebugAssert(m_stage == GPUShaderStage::Geometry);
41
return static_cast<ID3D11GeometryShader*>(m_shader.Get());
42
}
43
44
ID3D11ComputeShader* D3D11Shader::GetComputeShader() const
45
{
46
DebugAssert(m_stage == GPUShaderStage::Compute);
47
return static_cast<ID3D11ComputeShader*>(m_shader.Get());
48
}
49
50
#ifdef ENABLE_GPU_OBJECT_NAMES
51
52
void D3D11Shader::SetDebugName(std::string_view name)
53
{
54
SetD3DDebugObjectName(m_shader.Get(), name);
55
}
56
57
#endif
58
59
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromBinary(GPUShaderStage stage, std::span<const u8> data,
60
Error* error)
61
{
62
ComPtr<ID3D11DeviceChild> shader;
63
std::vector<u8> bytecode;
64
HRESULT hr;
65
switch (stage)
66
{
67
case GPUShaderStage::Vertex:
68
hr = m_device->CreateVertexShader(data.data(), data.size(), nullptr,
69
reinterpret_cast<ID3D11VertexShader**>(shader.GetAddressOf()));
70
bytecode.resize(data.size());
71
std::memcpy(bytecode.data(), data.data(), data.size());
72
break;
73
74
case GPUShaderStage::Fragment:
75
hr = m_device->CreatePixelShader(data.data(), data.size(), nullptr,
76
reinterpret_cast<ID3D11PixelShader**>(shader.GetAddressOf()));
77
break;
78
79
case GPUShaderStage::Geometry:
80
hr = m_device->CreateGeometryShader(data.data(), data.size(), nullptr,
81
reinterpret_cast<ID3D11GeometryShader**>(shader.GetAddressOf()));
82
break;
83
84
case GPUShaderStage::Compute:
85
hr = m_device->CreateComputeShader(data.data(), data.size(), nullptr,
86
reinterpret_cast<ID3D11ComputeShader**>(shader.GetAddressOf()));
87
break;
88
89
default:
90
UnreachableCode();
91
hr = S_FALSE;
92
break;
93
}
94
95
if (FAILED(hr) || !shader)
96
{
97
Error::SetHResult(error, "Create[Typed]Shader() failed: ", hr);
98
return {};
99
}
100
101
return std::unique_ptr<GPUShader>(new D3D11Shader(stage, std::move(shader), std::move(bytecode)));
102
}
103
104
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
105
std::string_view source, const char* entry_point,
106
DynamicHeapArray<u8>* out_binary, Error* error)
107
{
108
const u32 shader_model = D3DCommon::GetShaderModelForFeatureLevelNumber(m_render_api_version);
109
if (language != GPUShaderLanguage::HLSL)
110
{
111
return TranspileAndCreateShaderFromSource(stage, language, source, entry_point, GPUShaderLanguage::HLSL,
112
shader_model, out_binary, error);
113
}
114
115
std::optional<DynamicHeapArray<u8>> bytecode =
116
D3DCommon::CompileShader(shader_model, m_debug_device, stage, source, entry_point, error);
117
if (!bytecode.has_value())
118
return {};
119
120
std::unique_ptr<GPUShader> ret = CreateShaderFromBinary(stage, bytecode.value(), error);
121
if (ret && out_binary)
122
*out_binary = std::move(bytecode.value());
123
124
return ret;
125
}
126
127
D3D11Pipeline::D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds,
128
ComPtr<ID3D11BlendState> bs, ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs,
129
ComPtr<ID3D11GeometryShader> gs, ComPtr<ID3D11DeviceChild> ps_or_cs,
130
D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor)
131
: m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)),
132
m_gs(std::move(gs)), m_ps_or_cs(std::move(ps_or_cs)), m_topology(topology), m_vertex_stride(vertex_stride),
133
m_blend_factor(blend_factor), m_blend_factor_float(GPUDevice::RGBA8ToFloat(blend_factor))
134
{
135
}
136
137
D3D11Pipeline::~D3D11Pipeline()
138
{
139
D3D11Device::GetInstance().UnbindPipeline(this);
140
}
141
142
#ifdef ENABLE_GPU_OBJECT_NAMES
143
144
void D3D11Pipeline::SetDebugName(std::string_view name)
145
{
146
// can't label this directly
147
}
148
149
#endif
150
151
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs,
152
Error* error)
153
{
154
ComPtr<ID3D11RasterizerState> drs;
155
156
const auto it = m_rasterization_states.find(rs.key);
157
if (it != m_rasterization_states.end())
158
{
159
drs = it->second;
160
return drs;
161
}
162
163
static constexpr std::array<D3D11_CULL_MODE, static_cast<u32>(GPUPipeline::CullMode::MaxCount)> cull_mapping = {{
164
D3D11_CULL_NONE, // None
165
D3D11_CULL_FRONT, // Front
166
D3D11_CULL_BACK, // Back
167
}};
168
169
D3D11_RASTERIZER_DESC desc = {};
170
desc.FillMode = D3D11_FILL_SOLID;
171
desc.CullMode = cull_mapping[static_cast<u8>(rs.cull_mode.GetValue())];
172
desc.ScissorEnable = TRUE;
173
// desc.MultisampleEnable ???
174
175
HRESULT hr = m_device->CreateRasterizerState(&desc, drs.GetAddressOf());
176
if (FAILED(hr)) [[unlikely]]
177
Error::SetHResult(error, "CreateRasterizerState() failed: ", hr);
178
else
179
m_rasterization_states.emplace(rs.key, drs);
180
181
return drs;
182
}
183
184
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds, Error* error)
185
{
186
ComPtr<ID3D11DepthStencilState> dds;
187
188
const auto it = m_depth_states.find(ds.key);
189
if (it != m_depth_states.end())
190
{
191
dds = it->second;
192
return dds;
193
}
194
195
static constexpr std::array<D3D11_COMPARISON_FUNC, static_cast<u32>(GPUPipeline::DepthFunc::MaxCount)> func_mapping =
196
{{
197
D3D11_COMPARISON_NEVER, // Never
198
D3D11_COMPARISON_ALWAYS, // Always
199
D3D11_COMPARISON_LESS, // Less
200
D3D11_COMPARISON_LESS_EQUAL, // LessEqual
201
D3D11_COMPARISON_GREATER, // Greater
202
D3D11_COMPARISON_GREATER_EQUAL, // GreaterEqual
203
D3D11_COMPARISON_EQUAL, // Equal
204
}};
205
206
D3D11_DEPTH_STENCIL_DESC desc = {};
207
desc.DepthEnable = ds.depth_test != GPUPipeline::DepthFunc::Always || ds.depth_write;
208
desc.DepthFunc = func_mapping[static_cast<u8>(ds.depth_test.GetValue())];
209
desc.DepthWriteMask = ds.depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
210
211
HRESULT hr = m_device->CreateDepthStencilState(&desc, dds.GetAddressOf());
212
if (FAILED(hr)) [[unlikely]]
213
Error::SetHResult(error, "CreateDepthStencilState() failed: ", hr);
214
else
215
m_depth_states.emplace(ds.key, dds);
216
217
return dds;
218
}
219
220
size_t D3D11Device::BlendStateMapHash::operator()(const BlendStateMapKey& key) const
221
{
222
size_t h = std::hash<u64>()(key.first);
223
hash_combine(h, key.second);
224
return h;
225
}
226
227
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs, u32 num_rts,
228
Error* error)
229
{
230
ComPtr<ID3D11BlendState> dbs;
231
232
const std::pair<u64, u32> key(bs.key, num_rts);
233
const auto it = m_blend_states.find(key);
234
if (it != m_blend_states.end())
235
{
236
dbs = it->second;
237
return dbs;
238
}
239
240
static constexpr std::array<D3D11_BLEND, static_cast<u32>(GPUPipeline::BlendFunc::MaxCount)> blend_mapping = {{
241
D3D11_BLEND_ZERO, // Zero
242
D3D11_BLEND_ONE, // One
243
D3D11_BLEND_SRC_COLOR, // SrcColor
244
D3D11_BLEND_INV_SRC_COLOR, // InvSrcColor
245
D3D11_BLEND_DEST_COLOR, // DstColor
246
D3D11_BLEND_INV_DEST_COLOR, // InvDstColor
247
D3D11_BLEND_SRC_ALPHA, // SrcAlpha
248
D3D11_BLEND_INV_SRC_ALPHA, // InvSrcAlpha
249
D3D11_BLEND_SRC1_ALPHA, // SrcAlpha1
250
D3D11_BLEND_INV_SRC1_ALPHA, // InvSrcAlpha1
251
D3D11_BLEND_DEST_ALPHA, // DstAlpha
252
D3D11_BLEND_INV_DEST_ALPHA, // InvDstAlpha
253
D3D11_BLEND_BLEND_FACTOR, // ConstantColor
254
D3D11_BLEND_INV_BLEND_FACTOR, // InvConstantColor
255
}};
256
257
static constexpr std::array<D3D11_BLEND_OP, static_cast<u32>(GPUPipeline::BlendOp::MaxCount)> op_mapping = {{
258
D3D11_BLEND_OP_ADD, // Add
259
D3D11_BLEND_OP_SUBTRACT, // Subtract
260
D3D11_BLEND_OP_REV_SUBTRACT, // ReverseSubtract
261
D3D11_BLEND_OP_MIN, // Min
262
D3D11_BLEND_OP_MAX, // Max
263
}};
264
265
D3D11_BLEND_DESC blend_desc = {};
266
for (u32 i = 0; i < num_rts; i++)
267
{
268
D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[i];
269
tgt_desc.BlendEnable = bs.enable;
270
tgt_desc.RenderTargetWriteMask = bs.write_mask;
271
if (bs.enable)
272
{
273
tgt_desc.SrcBlend = blend_mapping[static_cast<u8>(bs.src_blend.GetValue())];
274
tgt_desc.DestBlend = blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())];
275
tgt_desc.BlendOp = op_mapping[static_cast<u8>(bs.blend_op.GetValue())];
276
tgt_desc.SrcBlendAlpha = blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())];
277
tgt_desc.DestBlendAlpha = blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())];
278
tgt_desc.BlendOpAlpha = op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())];
279
}
280
}
281
282
HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf());
283
if (FAILED(hr)) [[unlikely]]
284
Error::SetHResult(error, "CreateBlendState() failed: ", hr);
285
else
286
m_blend_states.emplace(key, dbs);
287
288
return dbs;
289
}
290
291
D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipeline::InputLayout& il,
292
const D3D11Shader* vs, Error* error)
293
{
294
ComPtr<ID3D11InputLayout> dil;
295
const auto it = m_input_layouts.find(il);
296
if (it != m_input_layouts.end())
297
{
298
dil = it->second;
299
return dil;
300
}
301
302
static constexpr u32 MAX_COMPONENTS = 4;
303
static constexpr const DXGI_FORMAT
304
format_mapping[static_cast<u8>(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = {
305
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
306
DXGI_FORMAT_R32G32B32A32_FLOAT}, // Float
307
{DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UINT}, // UInt8
308
{DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_SINT}, // SInt8
309
{DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM}, // UNorm8
310
{DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UINT}, // UInt16
311
{DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_SINT}, // SInt16
312
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UNORM}, // UNorm16
313
{DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_UINT}, // UInt32
314
{DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_SINT}, // SInt32
315
};
316
317
D3D11_INPUT_ELEMENT_DESC* elems =
318
static_cast<D3D11_INPUT_ELEMENT_DESC*>(alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * il.vertex_attributes.size()));
319
for (size_t i = 0; i < il.vertex_attributes.size(); i++)
320
{
321
const GPUPipeline::VertexAttribute& va = il.vertex_attributes[i];
322
Assert(va.components > 0 && va.components <= MAX_COMPONENTS);
323
324
D3D11_INPUT_ELEMENT_DESC& elem = elems[i];
325
elem.SemanticName = "ATTR";
326
elem.SemanticIndex = va.index;
327
elem.Format = format_mapping[static_cast<u8>(va.type.GetValue())][va.components - 1];
328
elem.InputSlot = 0;
329
elem.AlignedByteOffset = va.offset;
330
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
331
elem.InstanceDataStepRate = 0;
332
}
333
334
HRESULT hr = m_device->CreateInputLayout(elems, static_cast<UINT>(il.vertex_attributes.size()),
335
vs->GetBytecode().data(), vs->GetBytecode().size(), dil.GetAddressOf());
336
if (FAILED(hr)) [[unlikely]]
337
Error::SetHResult(error, "CreateInputLayout() failed: ", hr);
338
else
339
m_input_layouts.emplace(il, dil);
340
341
return dil;
342
}
343
344
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
345
{
346
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization, error);
347
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth, error);
348
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend, config.GetRenderTargetCount(), error);
349
if (!rs || !ds || !bs)
350
return {};
351
352
ComPtr<ID3D11InputLayout> il;
353
u32 vertex_stride = 0;
354
if (!config.input_layout.vertex_attributes.empty())
355
{
356
il = GetInputLayout(config.input_layout, static_cast<const D3D11Shader*>(config.vertex_shader), error);
357
vertex_stride = config.input_layout.vertex_stride;
358
if (!il)
359
return {};
360
}
361
362
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, static_cast<u32>(GPUPipeline::Primitive::MaxCount)> primitives =
363
{{
364
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, // Points
365
D3D11_PRIMITIVE_TOPOLOGY_LINELIST, // Lines
366
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Triangles
367
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TriangleStrips
368
}};
369
370
return std::unique_ptr<GPUPipeline>(new D3D11Pipeline(
371
std::move(rs), std::move(ds), std::move(bs), std::move(il),
372
static_cast<const D3D11Shader*>(config.vertex_shader)->GetVertexShader(),
373
config.geometry_shader ? static_cast<const D3D11Shader*>(config.geometry_shader)->GetGeometryShader() : nullptr,
374
static_cast<const D3D11Shader*>(config.fragment_shader)->GetPixelShader(),
375
primitives[static_cast<u8>(config.primitive)], vertex_stride, config.blend.constant));
376
}
377
378
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::ComputeConfig& config, Error* error)
379
{
380
if (!config.compute_shader) [[unlikely]]
381
{
382
Error::SetStringView(error, "Missing compute shader.");
383
return {};
384
}
385
386
return std::unique_ptr<GPUPipeline>(
387
new D3D11Pipeline(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
388
static_cast<const D3D11Shader*>(config.compute_shader)->GetComputeShader(),
389
D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, 0, 0));
390
}
391
392
void D3D11Device::SetPipeline(GPUPipeline* pipeline)
393
{
394
if (m_current_pipeline == pipeline)
395
return;
396
397
const bool was_compute = m_current_pipeline && m_current_pipeline->IsComputePipeline();
398
D3D11Pipeline* const PL = static_cast<D3D11Pipeline*>(pipeline);
399
m_current_pipeline = PL;
400
401
if (!PL->IsComputePipeline())
402
{
403
if (was_compute)
404
UnbindComputePipeline();
405
406
if (ID3D11InputLayout* il = PL->GetInputLayout(); m_current_input_layout != il)
407
{
408
m_current_input_layout = il;
409
m_context->IASetInputLayout(il);
410
}
411
412
if (const u32 vertex_stride = PL->GetVertexStride(); m_current_vertex_stride != vertex_stride)
413
{
414
const UINT offset = 0;
415
m_current_vertex_stride = PL->GetVertexStride();
416
m_context->IASetVertexBuffers(0, 1, m_vertex_buffer.GetD3DBufferArray(), &m_current_vertex_stride, &offset);
417
}
418
419
if (D3D_PRIMITIVE_TOPOLOGY topology = PL->GetPrimitiveTopology(); m_current_primitive_topology != topology)
420
{
421
m_current_primitive_topology = topology;
422
m_context->IASetPrimitiveTopology(topology);
423
}
424
425
if (ID3D11VertexShader* vs = PL->GetVertexShader(); m_current_vertex_shader != vs)
426
{
427
m_current_vertex_shader = vs;
428
m_context->VSSetShader(vs, nullptr, 0);
429
}
430
431
if (ID3D11GeometryShader* gs = PL->GetGeometryShader(); m_current_geometry_shader != gs)
432
{
433
m_current_geometry_shader = gs;
434
m_context->GSSetShader(gs, nullptr, 0);
435
}
436
437
if (ID3D11PixelShader* ps = PL->GetPixelShader(); m_current_pixel_shader != ps)
438
{
439
m_current_pixel_shader = ps;
440
m_context->PSSetShader(ps, nullptr, 0);
441
}
442
443
if (ID3D11RasterizerState* rs = PL->GetRasterizerState(); m_current_rasterizer_state != rs)
444
{
445
m_current_rasterizer_state = rs;
446
m_context->RSSetState(rs);
447
}
448
449
if (ID3D11DepthStencilState* ds = PL->GetDepthStencilState(); m_current_depth_state != ds)
450
{
451
m_current_depth_state = ds;
452
m_context->OMSetDepthStencilState(ds, 0);
453
}
454
455
if (ID3D11BlendState* bs = PL->GetBlendState();
456
m_current_blend_state != bs || m_current_blend_factor != PL->GetBlendFactor())
457
{
458
m_current_blend_state = bs;
459
m_current_blend_factor = PL->GetBlendFactor();
460
m_context->OMSetBlendState(bs, RGBA8ToFloat(m_current_blend_factor).data(), 0xFFFFFFFFu);
461
}
462
}
463
else
464
{
465
if (ID3D11ComputeShader* cs = m_current_pipeline->GetComputeShader(); cs != m_current_compute_shader)
466
{
467
m_current_compute_shader = cs;
468
m_context->CSSetShader(cs, nullptr, 0);
469
}
470
471
if (!was_compute)
472
{
473
// need to bind all SRVs/samplers
474
u32 count;
475
for (count = 0; count < MAX_TEXTURE_SAMPLERS; count++)
476
{
477
if (!m_current_textures[count])
478
break;
479
}
480
if (count > 0)
481
{
482
m_context->CSSetShaderResources(0, count, m_current_textures.data());
483
m_context->CSSetSamplers(0, count, m_current_samplers.data());
484
}
485
486
if (m_current_render_pass_flags & GPUPipeline::BindRenderTargetsAsImages)
487
{
488
ID3D11UnorderedAccessView* uavs[MAX_TEXTURE_SAMPLERS];
489
for (u32 i = 0; i < m_num_current_render_targets; i++)
490
uavs[i] = m_current_render_targets[i]->GetD3DUAV();
491
492
m_context->OMSetRenderTargets(0, nullptr, nullptr);
493
m_context->CSSetUnorderedAccessViews(0, m_num_current_render_targets, uavs, nullptr);
494
}
495
}
496
}
497
}
498
499
void D3D11Device::UnbindPipeline(D3D11Pipeline* pl)
500
{
501
if (m_current_pipeline != pl)
502
return;
503
504
if (pl->IsComputePipeline())
505
UnbindComputePipeline();
506
507
// Let the runtime deal with the dead objects...
508
m_current_pipeline = nullptr;
509
}
510
511
void D3D11Device::UnbindComputePipeline()
512
{
513
m_current_compute_shader = nullptr;
514
515
ID3D11ShaderResourceView* null_srvs[MAX_TEXTURE_SAMPLERS] = {};
516
ID3D11SamplerState* null_samplers[MAX_TEXTURE_SAMPLERS] = {};
517
ID3D11UnorderedAccessView* null_uavs[MAX_RENDER_TARGETS] = {};
518
m_context->CSSetShader(nullptr, nullptr, 0);
519
m_context->CSSetShaderResources(0, MAX_TEXTURE_SAMPLERS, null_srvs);
520
m_context->CSSetSamplers(0, MAX_TEXTURE_SAMPLERS, null_samplers);
521
if (m_current_render_pass_flags & GPUPipeline::BindRenderTargetsAsImages)
522
m_context->CSSetUnorderedAccessViews(0, m_num_current_render_targets, null_uavs, nullptr);
523
}
524
525