· 6 years ago · Aug 04, 2019, 05:44 AM
1#include "SimpleShader.h"
2
3///////////////////////////////////////////////////////////////////////////////
4// ------ BASE SIMPLE SHADER --------------------------------------------------
5///////////////////////////////////////////////////////////////////////////////
6
7// --------------------------------------------------------
8// Constructor accepts DirectX device & context
9// --------------------------------------------------------
10ISimpleShader::ISimpleShader(ID3D11Device* device, ID3D11DeviceContext* context)
11{
12 // Save the device
13 this->device = device;
14 this->deviceContext = context;
15
16 // Set up fields
17 constantBufferCount = 0;
18 constantBuffers = 0;
19 shaderBlob = 0;
20}
21
22// --------------------------------------------------------
23// Destructor
24// --------------------------------------------------------
25ISimpleShader::~ISimpleShader()
26{
27 // Derived class destructors will call this class's CleanUp method
28 if(shaderBlob)
29 shaderBlob->Release();
30}
31
32// --------------------------------------------------------
33// Cleans up the variable table and buffers - Some things will
34// be handled by derived classes
35// --------------------------------------------------------
36void ISimpleShader::CleanUp()
37{
38 // Handle constant buffers and local data buffers
39 for (unsigned int i = 0; i < constantBufferCount; i++)
40 {
41 constantBuffers[i].ConstantBuffer->Release();
42 delete[] constantBuffers[i].LocalDataBuffer;
43 }
44
45 if (constantBuffers)
46 {
47 delete[] constantBuffers;
48 constantBufferCount = 0;
49 }
50
51 for (unsigned int i = 0; i < shaderResourceViews.size(); i++)
52 delete shaderResourceViews[i];
53
54 for (unsigned int i = 0; i < samplerStates.size(); i++)
55 delete samplerStates[i];
56
57 // Clean up tables
58 varTable.clear();
59 cbTable.clear();
60 samplerTable.clear();
61 textureTable.clear();
62}
63
64// --------------------------------------------------------
65// Loads the specified shader and builds the variable table using shader
66// reflection. This must be a separate step from the constructor since
67// we can't invoke derived class overrides in the base class constructor.
68//
69// shaderFile - A "wide string" specifying the compiled shader to load
70//
71// Returns true if shader is loaded properly, false otherwise
72// --------------------------------------------------------
73bool ISimpleShader::LoadShaderFile(LPCWSTR shaderFile)
74{
75 // Load the shader to a blob and ensure it worked
76 HRESULT hr = D3DReadFileToBlob(shaderFile, &shaderBlob);
77 if (hr != S_OK)
78 {
79 return false;
80 }
81
82 // Create the shader - Calls an overloaded version of this abstract
83 // method in the appropriate child class
84 shaderValid = CreateShader(shaderBlob);
85 if (!shaderValid)
86 {
87 return false;
88 }
89
90 // Set up shader reflection to get information about
91 // this shader and its variables, buffers, etc.
92 ID3D11ShaderReflection* refl;
93 D3DReflect(
94 shaderBlob->GetBufferPointer(),
95 shaderBlob->GetBufferSize(),
96 IID_ID3D11ShaderReflection,
97 (void**)&refl);
98
99 // Get the description of the shader
100 D3D11_SHADER_DESC shaderDesc;
101 refl->GetDesc(&shaderDesc);
102
103 // Get the number of buffers and make the resource array
104 constantBufferCount = shaderDesc.ConstantBuffers;
105 constantBuffers = new SimpleConstantBuffer[constantBufferCount];
106
107 // Handle bound resources (like shaders and samplers)
108 unsigned int resourceCount = shaderDesc.BoundResources;
109 for (unsigned int r = 0; r < resourceCount; r++)
110 {
111 // Get this resource's description
112 D3D11_SHADER_INPUT_BIND_DESC resourceDesc;
113 refl->GetResourceBindingDesc(r, &resourceDesc);
114
115 // Check the type
116 switch (resourceDesc.Type)
117 {
118 case D3D_SIT_TEXTURE: // A texture resource
119 {
120 // Create the SRV wrapper
121 SimpleSRV* srv = new SimpleSRV();
122 srv->BindIndex = resourceDesc.BindPoint; // Shader bind point
123 srv->Index = (unsigned int)shaderResourceViews.size(); // Raw index
124
125 textureTable.insert(std::pair<std::string, SimpleSRV*>(resourceDesc.Name, srv));
126 shaderResourceViews.push_back(srv);
127 }
128 break;
129
130 case D3D_SIT_SAMPLER: // A sampler resource
131 {
132 // Create the sampler wrapper
133 SimpleSampler* samp = new SimpleSampler();
134 samp->BindIndex = resourceDesc.BindPoint; // Shader bind point
135 samp->Index = (unsigned int)samplerStates.size(); // Raw index
136
137 samplerTable.insert(std::pair<std::string, SimpleSampler*>(resourceDesc.Name, samp));
138 samplerStates.push_back(samp);
139 }
140 break;
141 }
142 }
143
144 // Loop through all constant buffers
145 for (unsigned int b = 0; b < constantBufferCount; b++)
146 {
147 // Get this buffer
148 ID3D11ShaderReflectionConstantBuffer* cb =
149 refl->GetConstantBufferByIndex(b);
150
151 // Get the description of this buffer
152 D3D11_SHADER_BUFFER_DESC bufferDesc;
153 cb->GetDesc(&bufferDesc);
154
155 // Save the type, which we reference when setting these buffers
156 constantBuffers[b].Type = bufferDesc.Type;
157
158 // Get the description of the resource binding, so
159 // we know exactly how it's bound in the shader
160 D3D11_SHADER_INPUT_BIND_DESC bindDesc;
161 refl->GetResourceBindingDescByName(bufferDesc.Name, &bindDesc);
162
163 // Set up the buffer and put its pointer in the table
164 constantBuffers[b].BindIndex = bindDesc.BindPoint;
165 constantBuffers[b].Name = bufferDesc.Name;
166 cbTable.insert(std::pair<std::string, SimpleConstantBuffer*>(bufferDesc.Name, &constantBuffers[b]));
167
168 // Create this constant buffer
169 D3D11_BUFFER_DESC newBuffDesc;
170 newBuffDesc.Usage = D3D11_USAGE_DEFAULT;
171 newBuffDesc.ByteWidth = max(bufferDesc.Size, 16); // NEW: Must be multiple of 16
172 newBuffDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
173 newBuffDesc.CPUAccessFlags = 0;
174 newBuffDesc.MiscFlags = 0;
175 newBuffDesc.StructureByteStride = 0;
176 device->CreateBuffer(&newBuffDesc, 0, &constantBuffers[b].ConstantBuffer);
177
178 // Set up the data buffer for this constant buffer
179 constantBuffers[b].Size = bufferDesc.Size;
180 constantBuffers[b].LocalDataBuffer = new unsigned char[bufferDesc.Size];
181 ZeroMemory(constantBuffers[b].LocalDataBuffer, bufferDesc.Size);
182
183 // Loop through all variables in this buffer
184 for (unsigned int v = 0; v < bufferDesc.Variables; v++)
185 {
186 // Get this variable
187 ID3D11ShaderReflectionVariable* var =
188 cb->GetVariableByIndex(v);
189
190 // Get the description of the variable and its type
191 D3D11_SHADER_VARIABLE_DESC varDesc;
192 var->GetDesc(&varDesc);
193
194 // Create the variable struct
195 SimpleShaderVariable varStruct;
196 varStruct.ConstantBufferIndex = b;
197 varStruct.ByteOffset = varDesc.StartOffset;
198 varStruct.Size = varDesc.Size;
199
200 // Get a string version
201 std::string varName(varDesc.Name);
202
203 // Add this variable to the table and the constant buffer
204 varTable.insert(std::pair<std::string, SimpleShaderVariable>(varName, varStruct));
205 constantBuffers[b].Variables.push_back(varStruct);
206 }
207 }
208
209 // All set
210 refl->Release();
211 return true;
212}
213
214// --------------------------------------------------------
215// Helper for looking up a variable by name and also
216// verifying that it is the requested size
217//
218// name - the name of the variable to look for
219// size - the size of the variable (for verification), or -1 to bypass
220// --------------------------------------------------------
221SimpleShaderVariable* ISimpleShader::FindVariable(std::string name, int size)
222{
223 // Look for the key
224 std::unordered_map<std::string, SimpleShaderVariable>::iterator result =
225 varTable.find(name);
226
227 // Did we find the key?
228 if (result == varTable.end())
229 return 0;
230
231 // Grab the result from the iterator
232 SimpleShaderVariable* var = &(result->second);
233
234 // Is the data size correct ?
235 if (size > 0 && var->Size != size)
236 return 0;
237
238 // Success
239 return var;
240}
241
242// --------------------------------------------------------
243// Helper for looking up a constant buffer by name
244// --------------------------------------------------------
245SimpleConstantBuffer* ISimpleShader::FindConstantBuffer(std::string name)
246{
247 // Look for the key
248 std::unordered_map<std::string, SimpleConstantBuffer*>::iterator result =
249 cbTable.find(name);
250
251 // Did we find the key?
252 if (result == cbTable.end())
253 return 0;
254
255 // Success
256 return result->second;
257}
258
259// --------------------------------------------------------
260// Sets the shader and associated constant buffers in DirectX
261// --------------------------------------------------------
262void ISimpleShader::SetShader()
263{
264 // Ensure the shader is valid
265 if (!shaderValid) return;
266
267 // Set the shader and any relevant constant buffers, which
268 // is an overloaded method in a subclass
269 SetShaderAndCBs();
270}
271
272// --------------------------------------------------------
273// Copies the relevant data to the all of this
274// shader's constant buffers. To just copy one
275// buffer, use CopyBufferData()
276// --------------------------------------------------------
277void ISimpleShader::CopyAllBufferData()
278{
279 // Ensure the shader is valid
280 if (!shaderValid) return;
281
282 // Loop through the constant buffers and copy all data
283 for (unsigned int i = 0; i < constantBufferCount; i++)
284 {
285 // Copy the entire local data buffer
286 deviceContext->UpdateSubresource(
287 constantBuffers[i].ConstantBuffer, 0, 0,
288 constantBuffers[i].LocalDataBuffer, 0, 0);
289 }
290}
291
292// --------------------------------------------------------
293// Copies local data to the shader's specified constant buffer
294//
295// index - The index of the buffer to copy.
296// Useful for updating more frequently-changing
297// variables without having to re-copy all buffers.
298//
299// NOTE: The "index" of the buffer might NOT be the same
300// as its register, especially if you have buffers
301// bound to non-sequential registers!
302// --------------------------------------------------------
303void ISimpleShader::CopyBufferData(unsigned int index)
304{
305 // Ensure the shader is valid
306 if (!shaderValid) return;
307
308 // Validate the index
309 if(index >= this->constantBufferCount)
310 return;
311
312 // Check for the buffer
313 SimpleConstantBuffer* cb = &this->constantBuffers[index];
314 if (!cb) return;
315
316 // Copy the data and get out
317 deviceContext->UpdateSubresource(
318 cb->ConstantBuffer, 0, 0,
319 cb->LocalDataBuffer, 0, 0);
320}
321
322// --------------------------------------------------------
323// Copies local data to the shader's specified constant buffer
324//
325// bufferName - Specifies the name of the buffer to copy.
326// Useful for updating more frequently-changing
327// variables without having to re-copy all buffers.
328// --------------------------------------------------------
329void ISimpleShader::CopyBufferData(std::string bufferName)
330{
331 // Ensure the shader is valid
332 if (!shaderValid) return;
333
334 // Check for the buffer
335 SimpleConstantBuffer* cb = this->FindConstantBuffer(bufferName);
336 if (!cb) return;
337
338 // Copy the data and get out
339 deviceContext->UpdateSubresource(
340 cb->ConstantBuffer, 0, 0,
341 cb->LocalDataBuffer, 0, 0);
342}
343
344
345// --------------------------------------------------------
346// Sets a variable by name with arbitrary data of the specified size
347//
348// name - The name of the shader variable
349// data - The data to set in the buffer
350// size - The size of the data (this must match the variable's size)
351//
352// Returns true if data is copied, false if variable doesn't
353// exist or sizes don't match
354// --------------------------------------------------------
355bool ISimpleShader::SetData(std::string name, const void* data, unsigned int size)
356{
357 // Look for the variable and verify
358 SimpleShaderVariable* var = FindVariable(name, size);
359 if (var == 0)
360 return false;
361
362 // Set the data in the local data buffer
363 memcpy(
364 constantBuffers[var->ConstantBufferIndex].LocalDataBuffer + var->ByteOffset,
365 data,
366 size);
367
368 // Success
369 return true;
370}
371
372// --------------------------------------------------------
373// Sets INTEGER data
374// --------------------------------------------------------
375bool ISimpleShader::SetInt(std::string name, int data)
376{
377 return this->SetData(name, (void*)(&data), sizeof(int));
378}
379
380// --------------------------------------------------------
381// Sets a FLOAT variable by name in the local data buffer
382// --------------------------------------------------------
383bool ISimpleShader::SetFloat(std::string name, float data)
384{
385 return this->SetData(name, (void*)(&data), sizeof(float));
386}
387
388// --------------------------------------------------------
389// Sets a FLOAT2 variable by name in the local data buffer
390// --------------------------------------------------------
391bool ISimpleShader::SetFloat2(std::string name, const float data[2])
392{
393 return this->SetData(name, (void*)data, sizeof(float) * 2);
394}
395
396// --------------------------------------------------------
397// Sets a FLOAT2 variable by name in the local data buffer
398// --------------------------------------------------------
399bool ISimpleShader::SetFloat2(std::string name, const DirectX::XMFLOAT2 data)
400{
401 return this->SetData(name, &data, sizeof(float) * 2);
402}
403
404// --------------------------------------------------------
405// Sets a FLOAT3 variable by name in the local data buffer
406// --------------------------------------------------------
407bool ISimpleShader::SetFloat3(std::string name, const float data[3])
408{
409 return this->SetData(name, (void*)data, sizeof(float) * 3);
410}
411
412// --------------------------------------------------------
413// Sets a FLOAT3 variable by name in the local data buffer
414// --------------------------------------------------------
415bool ISimpleShader::SetFloat3(std::string name, const DirectX::XMFLOAT3 data)
416{
417 return this->SetData(name, &data, sizeof(float) * 3);
418}
419
420// --------------------------------------------------------
421// Sets a FLOAT4 variable by name in the local data buffer
422// --------------------------------------------------------
423bool ISimpleShader::SetFloat4(std::string name, const float data[4])
424{
425 return this->SetData(name, (void*)data, sizeof(float) * 4);
426}
427
428// --------------------------------------------------------
429// Sets a FLOAT4 variable by name in the local data buffer
430// --------------------------------------------------------
431bool ISimpleShader::SetFloat4(std::string name, const DirectX::XMFLOAT4 data)
432{
433 return this->SetData(name, &data, sizeof(float) * 4);
434}
435
436// --------------------------------------------------------
437// Sets a MATRIX (4x4) variable by name in the local data buffer
438// --------------------------------------------------------
439bool ISimpleShader::SetMatrix4x4(std::string name, const float data[16])
440{
441 return this->SetData(name, (void*)data, sizeof(float) * 16);
442}
443
444// --------------------------------------------------------
445// Sets a MATRIX (4x4) variable by name in the local data buffer
446// --------------------------------------------------------
447bool ISimpleShader::SetMatrix4x4(std::string name, const DirectX::XMFLOAT4X4 data)
448{
449 return this->SetData(name, &data, sizeof(float) * 16);
450}
451
452// --------------------------------------------------------
453// Gets info about a shader variable, if it exists
454// --------------------------------------------------------
455const SimpleShaderVariable* ISimpleShader::GetVariableInfo(std::string name)
456{
457 return FindVariable(name, -1);
458}
459
460// --------------------------------------------------------
461// Gets info about an SRV in the shader (or null)
462//
463// name - the name of the SRV
464// --------------------------------------------------------
465const SimpleSRV* ISimpleShader::GetShaderResourceViewInfo(std::string name)
466{
467 // Look for the key
468 std::unordered_map<std::string, SimpleSRV*>::iterator result =
469 textureTable.find(name);
470
471 // Did we find the key?
472 if (result == textureTable.end())
473 return 0;
474
475 // Success
476 return result->second;
477}
478
479
480// --------------------------------------------------------
481// Gets info about an SRV in the shader (or null)
482//
483// index - the index of the SRV
484// --------------------------------------------------------
485const SimpleSRV* ISimpleShader::GetShaderResourceViewInfo(unsigned int index)
486{
487 // Valid index?
488 if (index >= shaderResourceViews.size()) return 0;
489
490 // Grab the bind index
491 return shaderResourceViews[index];
492}
493
494
495// --------------------------------------------------------
496// Gets info about a sampler in the shader (or null)
497//
498// name - the name of the sampler
499// --------------------------------------------------------
500const SimpleSampler* ISimpleShader::GetSamplerInfo(std::string name)
501{
502 // Look for the key
503 std::unordered_map<std::string, SimpleSampler*>::iterator result =
504 samplerTable.find(name);
505
506 // Did we find the key?
507 if (result == samplerTable.end())
508 return 0;
509
510 // Success
511 return result->second;
512}
513
514// --------------------------------------------------------
515// Gets info about a sampler in the shader (or null)
516//
517// index - the index of the sampler
518// --------------------------------------------------------
519const SimpleSampler* ISimpleShader::GetSamplerInfo(unsigned int index)
520{
521 // Valid index?
522 if (index >= samplerStates.size()) return 0;
523
524 // Grab the bind index
525 return samplerStates[index];
526}
527
528
529// --------------------------------------------------------
530// Gets the number of constant buffers in this shader
531// --------------------------------------------------------
532unsigned int ISimpleShader::GetBufferCount() { return constantBufferCount; }
533
534
535
536// --------------------------------------------------------
537// Gets the size of a particular constant buffer, or -1
538// --------------------------------------------------------
539unsigned int ISimpleShader::GetBufferSize(unsigned int index)
540{
541 // Valid index?
542 if (index >= constantBufferCount)
543 return -1;
544
545 // Grab the size
546 return constantBuffers[index].Size;
547}
548
549// --------------------------------------------------------
550// Gets info about a particular constant buffer
551// by name, if it exists
552// --------------------------------------------------------
553const SimpleConstantBuffer * ISimpleShader::GetBufferInfo(std::string name)
554{
555 return FindConstantBuffer(name);
556}
557
558// --------------------------------------------------------
559// Gets info about a particular constant buffer
560//
561// index - the index of the constant buffer
562// --------------------------------------------------------
563const SimpleConstantBuffer * ISimpleShader::GetBufferInfo(unsigned int index)
564{
565 // Check for valid index
566 if (index >= constantBufferCount) return 0;
567
568 // Return the specific buffer
569 return &constantBuffers[index];
570}
571
572
573
574
575
576///////////////////////////////////////////////////////////////////////////////
577// ------ SIMPLE VERTEX SHADER ------------------------------------------------
578///////////////////////////////////////////////////////////////////////////////
579
580// --------------------------------------------------------
581// Constructor just calls the base
582// --------------------------------------------------------
583SimpleVertexShader::SimpleVertexShader(ID3D11Device* device, ID3D11DeviceContext* context)
584 : ISimpleShader(device, context)
585{
586 // Ensure we set to zero to successfully trigger
587 // the Input Layout creation during LoadShader()
588 this->inputLayout = 0;
589 this->shader = 0;
590 this->perInstanceCompatible = false;
591}
592
593// --------------------------------------------------------
594// Constructor overload which takes a custom input layout
595//
596// Passing in a valid input layout will stop LoadShader()
597// from creating an input layout from shader reflection
598// --------------------------------------------------------
599SimpleVertexShader::SimpleVertexShader(ID3D11Device * device, ID3D11DeviceContext * context, ID3D11InputLayout * inputLayout, bool perInstanceCompatible)
600 : ISimpleShader(device, context)
601{
602 // Save the custom input layout
603 this->inputLayout = inputLayout;
604 this->shader = 0;
605
606 // Unable to determine from an input layout, require user to tell us
607 this->perInstanceCompatible = perInstanceCompatible;
608}
609
610// --------------------------------------------------------
611// Destructor - Clean up actual shader (base will be called automatically)
612// --------------------------------------------------------
613SimpleVertexShader::~SimpleVertexShader()
614{
615 CleanUp();
616}
617
618// --------------------------------------------------------
619// Handles cleaning up shader and base class clean up
620// --------------------------------------------------------
621void SimpleVertexShader::CleanUp()
622{
623 ISimpleShader::CleanUp();
624 if (shader) { shader->Release(); shader = 0; }
625 if (inputLayout) { inputLayout->Release(); inputLayout = 0; }
626}
627
628// --------------------------------------------------------
629// Creates the DirectX vertex shader
630//
631// shaderBlob - The shader's compiled code
632//
633// Returns true if shader is created correctly, false otherwise
634// --------------------------------------------------------
635bool SimpleVertexShader::CreateShader(ID3DBlob* shaderBlob)
636{
637 // Clean up first, in the event this method is
638 // called more than once on the same object
639 this->CleanUp();
640
641 // Create the shader from the blob
642 HRESULT result = device->CreateVertexShader(
643 shaderBlob->GetBufferPointer(),
644 shaderBlob->GetBufferSize(),
645 0,
646 &shader);
647
648 // Did the creation work?
649 if (result != S_OK)
650 return false;
651
652 // Do we already have an input layout?
653 // (This would come from one of the constructor overloads)
654 if (inputLayout)
655 return true;
656
657 // Vertex shader was created successfully, so we now use the
658 // shader code to re-reflect and create an input layout that
659 // matches what the vertex shader expects. Code adapted from:
660 // https://takinginitiative.wordpress.com/2011/12/11/directx-1011-basic-shader-reflection-automatic-input-layout-creation/
661
662 // Reflect shader info
663 ID3D11ShaderReflection* refl;
664 D3DReflect(
665 shaderBlob->GetBufferPointer(),
666 shaderBlob->GetBufferSize(),
667 IID_ID3D11ShaderReflection,
668 (void**)&refl);
669
670 // Get shader info
671 D3D11_SHADER_DESC shaderDesc;
672 refl->GetDesc(&shaderDesc);
673
674 // Read input layout description from shader info
675 std::vector<D3D11_INPUT_ELEMENT_DESC> inputLayoutDesc;
676 for (unsigned int i = 0; i< shaderDesc.InputParameters; i++)
677 {
678 D3D11_SIGNATURE_PARAMETER_DESC paramDesc;
679 refl->GetInputParameterDesc(i, ¶mDesc);
680
681 // Check the semantic name for "_PER_INSTANCE"
682 std::string perInstanceStr = "_PER_INSTANCE";
683 std::string sem = paramDesc.SemanticName;
684 int lenDiff = (int)sem.size() - (int)perInstanceStr.size();
685 bool isPerInstance =
686 lenDiff >= 0 &&
687 sem.compare(lenDiff, perInstanceStr.size(), perInstanceStr) == 0;
688
689 // Fill out input element desc
690 D3D11_INPUT_ELEMENT_DESC elementDesc;
691 elementDesc.SemanticName = paramDesc.SemanticName;
692 elementDesc.SemanticIndex = paramDesc.SemanticIndex;
693 elementDesc.InputSlot = 0;
694 elementDesc.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
695 elementDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
696 elementDesc.InstanceDataStepRate = 0;
697
698 // Replace anything affected by "per instance" data
699 if (isPerInstance)
700 {
701 elementDesc.InputSlot = 1; // Assume per instance data comes from another input slot!
702 elementDesc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
703 elementDesc.InstanceDataStepRate = 1;
704
705 perInstanceCompatible = true;
706 }
707
708 // Determine DXGI format
709 if (paramDesc.Mask == 1)
710 {
711 if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32_UINT;
712 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32_SINT;
713 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32_FLOAT;
714 }
715 else if (paramDesc.Mask <= 3)
716 {
717 if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32_UINT;
718 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32_SINT;
719 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32_FLOAT;
720 }
721 else if (paramDesc.Mask <= 7)
722 {
723 if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_UINT;
724 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_SINT;
725 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
726 }
727 else if (paramDesc.Mask <= 15)
728 {
729 if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT;
730 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT;
731 else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
732 }
733
734 // Save element desc
735 inputLayoutDesc.push_back(elementDesc);
736 }
737
738 // Try to create Input Layout
739 HRESULT hr = device->CreateInputLayout(
740 &inputLayoutDesc[0],
741 (unsigned int)inputLayoutDesc.size(),
742 shaderBlob->GetBufferPointer(),
743 shaderBlob->GetBufferSize(),
744 &inputLayout);
745
746 // All done, clean up
747 refl->Release();
748 return true;
749}
750
751// --------------------------------------------------------
752// Sets the vertex shader, input layout and constant buffers
753// for future DirectX drawing
754// --------------------------------------------------------
755void SimpleVertexShader::SetShaderAndCBs()
756{
757 // Is shader valid?
758 if (!shaderValid) return;
759
760 // Set the shader and input layout
761 deviceContext->IASetInputLayout(inputLayout);
762 deviceContext->VSSetShader(shader, 0, 0);
763
764 // Set the constant buffers
765 for (unsigned int i = 0; i < constantBufferCount; i++)
766 {
767 // Skip "buffers" that aren't true constant buffers
768 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
769 continue;
770
771 // This is a real constant buffer, so set it
772 deviceContext->VSSetConstantBuffers(
773 constantBuffers[i].BindIndex,
774 1,
775 &constantBuffers[i].ConstantBuffer);
776 }
777}
778
779// --------------------------------------------------------
780// Sets a shader resource view in the vertex shader stage
781//
782// name - The name of the texture resource in the shader
783// srv - The shader resource view of the texture in GPU memory
784//
785// Returns true if a texture of the given name was found, false otherwise
786// --------------------------------------------------------
787bool SimpleVertexShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
788{
789 // Look for the variable and verify
790 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
791 if (srvInfo == 0)
792 return false;
793
794 // Set the shader resource view
795 deviceContext->VSSetShaderResources(srvInfo->BindIndex, 1, &srv);
796
797 // Success
798 return true;
799}
800
801// --------------------------------------------------------
802// Sets a sampler state in the vertex shader stage
803//
804// name - The name of the sampler state in the shader
805// samplerState - The sampler state in GPU memory
806//
807// Returns true if a sampler of the given name was found, false otherwise
808// --------------------------------------------------------
809bool SimpleVertexShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
810{
811 // Look for the variable and verify
812 const SimpleSampler* sampInfo = GetSamplerInfo(name);
813 if (sampInfo == 0)
814 return false;
815
816 // Set the shader resource view
817 deviceContext->VSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
818
819 // Success
820 return true;
821}
822
823
824///////////////////////////////////////////////////////////////////////////////
825// ------ SIMPLE PIXEL SHADER -------------------------------------------------
826///////////////////////////////////////////////////////////////////////////////
827
828// --------------------------------------------------------
829// Constructor just calls the base
830// --------------------------------------------------------
831SimplePixelShader::SimplePixelShader(ID3D11Device* device, ID3D11DeviceContext* context)
832 : ISimpleShader(device, context)
833{
834 this->shader = 0;
835}
836
837// --------------------------------------------------------
838// Destructor - Clean up actual shader (base will be called automatically)
839// --------------------------------------------------------
840SimplePixelShader::~SimplePixelShader()
841{
842 CleanUp();
843}
844
845// --------------------------------------------------------
846// Handles cleaning up shader and base class clean up
847// --------------------------------------------------------
848void SimplePixelShader::CleanUp()
849{
850 ISimpleShader::CleanUp();
851 if (shader) { shader->Release(); shader = 0; }
852}
853
854// --------------------------------------------------------
855// Creates the DirectX pixel shader
856//
857// shaderBlob - The shader's compiled code
858//
859// Returns true if shader is created correctly, false otherwise
860// --------------------------------------------------------
861bool SimplePixelShader::CreateShader(ID3DBlob* shaderBlob)
862{
863 // Clean up first, in the event this method is
864 // called more than once on the same object
865 this->CleanUp();
866
867 // Create the shader from the blob
868 HRESULT result = device->CreatePixelShader(
869 shaderBlob->GetBufferPointer(),
870 shaderBlob->GetBufferSize(),
871 0,
872 &shader);
873
874 // Check the result
875 return (result == S_OK);
876}
877
878// --------------------------------------------------------
879// Sets the pixel shader and constant buffers for
880// future DirectX drawing
881// --------------------------------------------------------
882void SimplePixelShader::SetShaderAndCBs()
883{
884 // Is shader valid?
885 if (!shaderValid) return;
886
887 // Set the shader
888 deviceContext->PSSetShader(shader, 0, 0);
889
890 // Set the constant buffers
891 for (unsigned int i = 0; i < constantBufferCount; i++)
892 {
893 // Skip "buffers" that aren't true constant buffers
894 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
895 continue;
896
897 // This is a real constant buffer, so set it
898 deviceContext->PSSetConstantBuffers(
899 constantBuffers[i].BindIndex,
900 1,
901 &constantBuffers[i].ConstantBuffer);
902 }
903}
904
905// --------------------------------------------------------
906// Sets a shader resource view in the pixel shader stage
907//
908// name - The name of the texture resource in the shader
909// srv - The shader resource view of the texture in GPU memory
910//
911// Returns true if a texture of the given name was found, false otherwise
912// --------------------------------------------------------
913bool SimplePixelShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
914{
915 // Look for the variable and verify
916 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
917 if (srvInfo == 0)
918 return false;
919
920 // Set the shader resource view
921 deviceContext->PSSetShaderResources(srvInfo->BindIndex, 1, &srv);
922
923 // Success
924 return true;
925}
926
927// --------------------------------------------------------
928// Sets a sampler state in the pixel shader stage
929//
930// name - The name of the sampler state in the shader
931// samplerState - The sampler state in GPU memory
932//
933// Returns true if a sampler of the given name was found, false otherwise
934// --------------------------------------------------------
935bool SimplePixelShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
936{
937 // Look for the variable and verify
938 const SimpleSampler* sampInfo = GetSamplerInfo(name);
939 if (sampInfo == 0)
940 return false;
941
942 // Set the shader resource view
943 deviceContext->PSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
944
945 // Success
946 return true;
947}
948
949
950
951
952///////////////////////////////////////////////////////////////////////////////
953// ------ SIMPLE DOMAIN SHADER ------------------------------------------------
954///////////////////////////////////////////////////////////////////////////////
955
956// --------------------------------------------------------
957// Constructor just calls the base
958// --------------------------------------------------------
959SimpleDomainShader::SimpleDomainShader(ID3D11Device* device, ID3D11DeviceContext* context)
960 : ISimpleShader(device, context)
961{
962 this->shader = 0;
963}
964
965// --------------------------------------------------------
966// Destructor - Clean up actual shader (base will be called automatically)
967// --------------------------------------------------------
968SimpleDomainShader::~SimpleDomainShader()
969{
970 CleanUp();
971}
972
973// --------------------------------------------------------
974// Handles cleaning up shader and base class clean up
975// --------------------------------------------------------
976void SimpleDomainShader::CleanUp()
977{
978 ISimpleShader::CleanUp();
979 if (shader) { shader->Release(); shader = 0; }
980}
981
982// --------------------------------------------------------
983// Creates the DirectX domain shader
984//
985// shaderBlob - The shader's compiled code
986//
987// Returns true if shader is created correctly, false otherwise
988// --------------------------------------------------------
989bool SimpleDomainShader::CreateShader(ID3DBlob* shaderBlob)
990{
991 // Clean up first, in the event this method is
992 // called more than once on the same object
993 this->CleanUp();
994
995 // Create the shader from the blob
996 HRESULT result = device->CreateDomainShader(
997 shaderBlob->GetBufferPointer(),
998 shaderBlob->GetBufferSize(),
999 0,
1000 &shader);
1001
1002 // Check the result
1003 return (result == S_OK);
1004}
1005
1006// --------------------------------------------------------
1007// Sets the domain shader and constant buffers for
1008// future DirectX drawing
1009// --------------------------------------------------------
1010void SimpleDomainShader::SetShaderAndCBs()
1011{
1012 // Is shader valid?
1013 if (!shaderValid) return;
1014
1015 // Set the shader
1016 deviceContext->DSSetShader(shader, 0, 0);
1017
1018 // Set the constant buffers
1019 for (unsigned int i = 0; i < constantBufferCount; i++)
1020 {
1021 // Skip "buffers" that aren't true constant buffers
1022 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
1023 continue;
1024
1025 // This is a real constant buffer, so set it
1026 deviceContext->DSSetConstantBuffers(
1027 constantBuffers[i].BindIndex,
1028 1,
1029 &constantBuffers[i].ConstantBuffer);
1030 }
1031}
1032
1033// --------------------------------------------------------
1034// Sets a shader resource view in the domain shader stage
1035//
1036// name - The name of the texture resource in the shader
1037// srv - The shader resource view of the texture in GPU memory
1038//
1039// Returns true if a texture of the given name was found, false otherwise
1040// --------------------------------------------------------
1041bool SimpleDomainShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
1042{
1043 // Look for the variable and verify
1044 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
1045 if (srvInfo == 0)
1046 return false;
1047
1048 // Set the shader resource view
1049 deviceContext->DSSetShaderResources(srvInfo->BindIndex, 1, &srv);
1050
1051 // Success
1052 return true;
1053}
1054
1055// --------------------------------------------------------
1056// Sets a sampler state in the domain shader stage
1057//
1058// name - The name of the sampler state in the shader
1059// samplerState - The sampler state in GPU memory
1060//
1061// Returns true if a sampler of the given name was found, false otherwise
1062// --------------------------------------------------------
1063bool SimpleDomainShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
1064{
1065 // Look for the variable and verify
1066 const SimpleSampler* sampInfo = GetSamplerInfo(name);
1067 if (sampInfo == 0)
1068 return false;
1069
1070 // Set the shader resource view
1071 deviceContext->DSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
1072
1073 // Success
1074 return true;
1075}
1076
1077
1078
1079///////////////////////////////////////////////////////////////////////////////
1080// ------ SIMPLE HULL SHADER --------------------------------------------------
1081///////////////////////////////////////////////////////////////////////////////
1082
1083// --------------------------------------------------------
1084// Constructor just calls the base
1085// --------------------------------------------------------
1086SimpleHullShader::SimpleHullShader(ID3D11Device* device, ID3D11DeviceContext* context)
1087 : ISimpleShader(device, context)
1088{
1089 this->shader = 0;
1090}
1091
1092// --------------------------------------------------------
1093// Destructor - Clean up actual shader (base will be called automatically)
1094// --------------------------------------------------------
1095SimpleHullShader::~SimpleHullShader()
1096{
1097 CleanUp();
1098}
1099
1100// --------------------------------------------------------
1101// Handles cleaning up shader and base class clean up
1102// --------------------------------------------------------
1103void SimpleHullShader::CleanUp()
1104{
1105 ISimpleShader::CleanUp();
1106 if (shader) { shader->Release(); shader = 0; }
1107}
1108
1109// --------------------------------------------------------
1110// Creates the DirectX hull shader
1111//
1112// shaderBlob - The shader's compiled code
1113//
1114// Returns true if shader is created correctly, false otherwise
1115// --------------------------------------------------------
1116bool SimpleHullShader::CreateShader(ID3DBlob* shaderBlob)
1117{
1118 // Clean up first, in the event this method is
1119 // called more than once on the same object
1120 this->CleanUp();
1121
1122 // Create the shader from the blob
1123 HRESULT result = device->CreateHullShader(
1124 shaderBlob->GetBufferPointer(),
1125 shaderBlob->GetBufferSize(),
1126 0,
1127 &shader);
1128
1129 // Check the result
1130 return (result == S_OK);
1131}
1132
1133// --------------------------------------------------------
1134// Sets the hull shader and constant buffers for
1135// future DirectX drawing
1136// --------------------------------------------------------
1137void SimpleHullShader::SetShaderAndCBs()
1138{
1139 // Is shader valid?
1140 if (!shaderValid) return;
1141
1142 // Set the shader
1143 deviceContext->HSSetShader(shader, 0, 0);
1144
1145 // Set the constant buffers?
1146 for (unsigned int i = 0; i < constantBufferCount; i++)
1147 {
1148 // Skip "buffers" that aren't true constant buffers
1149 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
1150 continue;
1151
1152 // This is a real constant buffer, so set it
1153 deviceContext->HSSetConstantBuffers(
1154 constantBuffers[i].BindIndex,
1155 1,
1156 &constantBuffers[i].ConstantBuffer);
1157 }
1158}
1159
1160// --------------------------------------------------------
1161// Sets a shader resource view in the hull shader stage
1162//
1163// name - The name of the texture resource in the shader
1164// srv - The shader resource view of the texture in GPU memory
1165//
1166// Returns true if a texture of the given name was found, false otherwise
1167// --------------------------------------------------------
1168bool SimpleHullShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
1169{
1170 // Look for the variable and verify
1171 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
1172 if (srvInfo == 0)
1173 return false;
1174
1175 // Set the shader resource view
1176 deviceContext->HSSetShaderResources(srvInfo->BindIndex, 1, &srv);
1177
1178 // Success
1179 return true;
1180}
1181
1182// --------------------------------------------------------
1183// Sets a sampler state in the hull shader stage
1184//
1185// name - The name of the sampler state in the shader
1186// samplerState - The sampler state in GPU memory
1187//
1188// Returns true if a sampler of the given name was found, false otherwise
1189// --------------------------------------------------------
1190bool SimpleHullShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
1191{
1192 // Look for the variable and verify
1193 const SimpleSampler* sampInfo = GetSamplerInfo(name);
1194 if (sampInfo == 0)
1195 return false;
1196
1197 // Set the shader resource view
1198 deviceContext->HSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
1199
1200 // Success
1201 return true;
1202}
1203
1204
1205
1206
1207///////////////////////////////////////////////////////////////////////////////
1208// ------ SIMPLE GEOMETRY SHADER ----------------------------------------------
1209///////////////////////////////////////////////////////////////////////////////
1210
1211// --------------------------------------------------------
1212// Constructor calls the base and sets up potential stream-out options
1213// --------------------------------------------------------
1214SimpleGeometryShader::SimpleGeometryShader(ID3D11Device* device, ID3D11DeviceContext* context, bool useStreamOut, bool allowStreamOutRasterization)
1215 : ISimpleShader(device, context)
1216{
1217 this->shader = 0;
1218 this->useStreamOut = useStreamOut;
1219 this->allowStreamOutRasterization = allowStreamOutRasterization;
1220}
1221
1222// --------------------------------------------------------
1223// Destructor - Clean up actual shader (base will be called automatically)
1224// --------------------------------------------------------
1225SimpleGeometryShader::~SimpleGeometryShader()
1226{
1227 CleanUp();
1228}
1229
1230// --------------------------------------------------------
1231// Handles cleaning up shader and base class clean up
1232// --------------------------------------------------------
1233void SimpleGeometryShader::CleanUp()
1234{
1235 ISimpleShader::CleanUp();
1236 if (shader) { shader->Release(); shader = 0; }
1237}
1238
1239// --------------------------------------------------------
1240// Creates the DirectX Geometry shader
1241//
1242// shaderBlob - The shader's compiled code
1243//
1244// Returns true if shader is created correctly, false otherwise
1245// --------------------------------------------------------
1246bool SimpleGeometryShader::CreateShader(ID3DBlob* shaderBlob)
1247{
1248 // Clean up first, in the event this method is
1249 // called more than once on the same object
1250 this->CleanUp();
1251
1252 // Using stream out?
1253 if (useStreamOut)
1254 return this->CreateShaderWithStreamOut(shaderBlob);
1255
1256 // Create the shader from the blob
1257 HRESULT result = device->CreateGeometryShader(
1258 shaderBlob->GetBufferPointer(),
1259 shaderBlob->GetBufferSize(),
1260 0,
1261 &shader);
1262
1263 // Check the result
1264 return (result == S_OK);
1265}
1266
1267// --------------------------------------------------------
1268// Creates the DirectX Geometry shader and sets it up for
1269// stream output, if possible.
1270//
1271// shaderBlob - The shader's compiled code
1272//
1273// Returns true if shader is created correctly, false otherwise
1274// --------------------------------------------------------
1275bool SimpleGeometryShader::CreateShaderWithStreamOut(ID3DBlob* shaderBlob)
1276{
1277 // Clean up first, in the event this method is
1278 // called more than once on the same object
1279 this->CleanUp();
1280
1281 // Reflect shader info
1282 ID3D11ShaderReflection* refl;
1283 D3DReflect(
1284 shaderBlob->GetBufferPointer(),
1285 shaderBlob->GetBufferSize(),
1286 IID_ID3D11ShaderReflection,
1287 (void**)&refl);
1288
1289 // Get shader info
1290 D3D11_SHADER_DESC shaderDesc;
1291 refl->GetDesc(&shaderDesc);
1292
1293 // Set up the output signature
1294 streamOutVertexSize = 0;
1295 std::vector<D3D11_SO_DECLARATION_ENTRY> soDecl;
1296 for (unsigned int i = 0; i < shaderDesc.OutputParameters; i++)
1297 {
1298 // Get the info about this entry
1299 D3D11_SIGNATURE_PARAMETER_DESC paramDesc;
1300 refl->GetOutputParameterDesc(i, ¶mDesc);
1301
1302 // Create the SO Declaration
1303 D3D11_SO_DECLARATION_ENTRY entry;
1304 entry.SemanticIndex = paramDesc.SemanticIndex;
1305 entry.SemanticName = paramDesc.SemanticName;
1306 entry.Stream = paramDesc.Stream;
1307 entry.StartComponent = 0; // Assume starting at 0
1308 entry.OutputSlot = 0; // Assume the first output slot
1309
1310 // Check the mask to determine how many components are used
1311 entry.ComponentCount = CalcComponentCount(paramDesc.Mask);
1312
1313 // Increment the size
1314 streamOutVertexSize += entry.ComponentCount * sizeof(float);
1315
1316 // Add to the declaration
1317 soDecl.push_back(entry);
1318 }
1319
1320 // Rasterization allowed?
1321 unsigned int rast = allowStreamOutRasterization ? 0 : D3D11_SO_NO_RASTERIZED_STREAM;
1322
1323 // Create the shader
1324 HRESULT result = device->CreateGeometryShaderWithStreamOutput(
1325 shaderBlob->GetBufferPointer(), // Shader blob pointer
1326 shaderBlob->GetBufferSize(), // Shader blob size
1327 &soDecl[0], // Stream out declaration
1328 (unsigned int)soDecl.size(), // Number of declaration entries
1329 NULL, // Buffer strides (not used - assume tightly packed?)
1330 0, // No buffer strides
1331 rast, // Index of the stream to rasterize (if any)
1332 NULL, // Not using class linkage
1333 &shader);
1334
1335 return (result == S_OK);
1336}
1337
1338// --------------------------------------------------------
1339// Creates a vertex buffer that is compatible with the stream output
1340// delcaration that was used to create the shader. This buffer will
1341// not be cleaned up (Released) by the simple shader - you must clean
1342// it up yourself when you're done with it. Immediately returns
1343// false if the shader was not created with stream output, the shader
1344// isn't valid or the determined stream out vertex size is zero.
1345//
1346// buffer - Pointer to an ID3D11Buffer pointer to hold the buffer ref
1347// vertexCount - Amount of vertices the buffer should hold
1348//
1349// Returns true if buffer is created successfully AND stream output
1350// was used to create the shader. False otherwise.
1351// --------------------------------------------------------
1352bool SimpleGeometryShader::CreateCompatibleStreamOutBuffer(ID3D11Buffer** buffer, int vertexCount)
1353{
1354 // Was stream output actually used?
1355 if (!this->useStreamOut || !shaderValid || streamOutVertexSize == 0)
1356 return false;
1357
1358 // Set up the buffer description
1359 D3D11_BUFFER_DESC desc;
1360 desc.BindFlags = D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_VERTEX_BUFFER;
1361 desc.ByteWidth = streamOutVertexSize * vertexCount;
1362 desc.CPUAccessFlags = 0;
1363 desc.MiscFlags = 0;
1364 desc.StructureByteStride = 0;
1365 desc.Usage = D3D11_USAGE_DEFAULT;
1366
1367 // Attempt to create the buffer and return the result
1368 HRESULT result = device->CreateBuffer(&desc, 0, buffer);
1369 return (result == S_OK);
1370}
1371
1372// --------------------------------------------------------
1373// Helper method to unbind all stream out buffers from the SO stage
1374// --------------------------------------------------------
1375void SimpleGeometryShader::UnbindStreamOutStage(ID3D11DeviceContext* deviceContext)
1376{
1377 unsigned int offset = 0;
1378 ID3D11Buffer* unset[1] = { 0 };
1379 deviceContext->SOSetTargets(1, unset, &offset);
1380}
1381
1382// --------------------------------------------------------
1383// Sets the geometry shader and constant buffers for
1384// future DirectX drawing
1385// --------------------------------------------------------
1386void SimpleGeometryShader::SetShaderAndCBs()
1387{
1388 // Is shader valid?
1389 if (!shaderValid) return;
1390
1391 // Set the shader
1392 deviceContext->GSSetShader(shader, 0, 0);
1393
1394 // Set the constant buffers?
1395 for (unsigned int i = 0; i < constantBufferCount; i++)
1396 {
1397 // Skip "buffers" that aren't true constant buffers
1398 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
1399 continue;
1400
1401 // This is a real constant buffer, so set it
1402 deviceContext->GSSetConstantBuffers(
1403 constantBuffers[i].BindIndex,
1404 1,
1405 &constantBuffers[i].ConstantBuffer);
1406 }
1407}
1408
1409// --------------------------------------------------------
1410// Sets a shader resource view in the Geometry shader stage
1411//
1412// name - The name of the texture resource in the shader
1413// srv - The shader resource view of the texture in GPU memory
1414//
1415// Returns true if a texture of the given name was found, false otherwise
1416// --------------------------------------------------------
1417bool SimpleGeometryShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
1418{
1419 // Look for the variable and verify
1420 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
1421 if (srvInfo == 0)
1422 return false;
1423
1424 // Set the shader resource view
1425 deviceContext->GSSetShaderResources(srvInfo->BindIndex, 1, &srv);
1426
1427 // Success
1428 return true;
1429}
1430
1431// --------------------------------------------------------
1432// Sets a sampler state in the Geometry shader stage
1433//
1434// name - The name of the sampler state in the shader
1435// samplerState - The sampler state in GPU memory
1436//
1437// Returns true if a sampler of the given name was found, false otherwise
1438// --------------------------------------------------------
1439bool SimpleGeometryShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
1440{
1441 // Look for the variable and verify
1442 const SimpleSampler* sampInfo = GetSamplerInfo(name);
1443 if (sampInfo == 0)
1444 return false;
1445
1446 // Set the shader resource view
1447 deviceContext->GSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
1448
1449 // Success
1450 return true;
1451}
1452
1453// --------------------------------------------------------
1454// Calculates the number of components specified by a parameter description mask
1455//
1456// mask - The mask to check (only values 0 - 15 are considered)
1457//
1458// Returns an integer between 0 - 4 inclusive
1459// --------------------------------------------------------
1460unsigned int SimpleGeometryShader::CalcComponentCount(unsigned int mask)
1461{
1462 unsigned int result = 0;
1463 result += (unsigned int)((mask & 1) == 1);
1464 result += (unsigned int)((mask & 2) == 2);
1465 result += (unsigned int)((mask & 4) == 4);
1466 result += (unsigned int)((mask & 8) == 8);
1467 return result;
1468}
1469
1470
1471
1472///////////////////////////////////////////////////////////////////////////////
1473// ------ SIMPLE COMPUTE SHADER -----------------------------------------------
1474///////////////////////////////////////////////////////////////////////////////
1475
1476// --------------------------------------------------------
1477// Constructor just calls the base
1478// --------------------------------------------------------
1479SimpleComputeShader::SimpleComputeShader(ID3D11Device* device, ID3D11DeviceContext* context)
1480 : ISimpleShader(device, context)
1481{
1482 this->shader = 0;
1483}
1484
1485// --------------------------------------------------------
1486// Destructor - Clean up actual shader (base will be called automatically)
1487// --------------------------------------------------------
1488SimpleComputeShader::~SimpleComputeShader()
1489{
1490 CleanUp();
1491}
1492
1493// --------------------------------------------------------
1494// Handles cleaning up shader and base class clean up
1495// --------------------------------------------------------
1496void SimpleComputeShader::CleanUp()
1497{
1498 ISimpleShader::CleanUp();
1499 if (shader) { shader->Release(); shader = 0; }
1500
1501 uavTable.clear();
1502}
1503
1504// --------------------------------------------------------
1505// Creates the DirectX Compute shader
1506//
1507// shaderBlob - The shader's compiled code
1508//
1509// Returns true if shader is created correctly, false otherwise
1510// --------------------------------------------------------
1511bool SimpleComputeShader::CreateShader(ID3DBlob* shaderBlob)
1512{
1513 // Clean up first, in the event this method is
1514 // called more than once on the same object
1515 this->CleanUp();
1516
1517 // Create the shader from the blob
1518 HRESULT result = device->CreateComputeShader(
1519 shaderBlob->GetBufferPointer(),
1520 shaderBlob->GetBufferSize(),
1521 0,
1522 &shader);
1523
1524 // Was the shader created correctly?
1525 if (result != S_OK)
1526 return false;
1527
1528 // Set up shader reflection to get information about UAV's
1529 ID3D11ShaderReflection* refl;
1530 D3DReflect(
1531 shaderBlob->GetBufferPointer(),
1532 shaderBlob->GetBufferSize(),
1533 IID_ID3D11ShaderReflection,
1534 (void**)&refl);
1535
1536 // Get the description of the shader
1537 D3D11_SHADER_DESC shaderDesc;
1538 refl->GetDesc(&shaderDesc);
1539
1540 // Grab the thread info
1541 threadsTotal = refl->GetThreadGroupSize(
1542 &threadsX,
1543 &threadsY,
1544 &threadsZ);
1545
1546 // Loop and get all UAV resources
1547 unsigned int resourceCount = shaderDesc.BoundResources;
1548 for (unsigned int r = 0; r < resourceCount; r++)
1549 {
1550 // Get this resource's description
1551 D3D11_SHADER_INPUT_BIND_DESC resourceDesc;
1552 refl->GetResourceBindingDesc(r, &resourceDesc);
1553
1554 // Check the type, looking for any kind of UAV
1555 switch (resourceDesc.Type)
1556 {
1557 case D3D_SIT_UAV_APPEND_STRUCTURED:
1558 case D3D_SIT_UAV_CONSUME_STRUCTURED:
1559 case D3D_SIT_UAV_RWBYTEADDRESS:
1560 case D3D_SIT_UAV_RWSTRUCTURED:
1561 case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
1562 case D3D_SIT_UAV_RWTYPED:
1563 uavTable.insert(std::pair<std::string, unsigned int>(resourceDesc.Name, resourceDesc.BindPoint));
1564 }
1565 }
1566
1567 // All set
1568 refl->Release();
1569 return true;
1570}
1571
1572// --------------------------------------------------------
1573// Sets the Compute shader and constant buffers for
1574// future DirectX drawing
1575// --------------------------------------------------------
1576void SimpleComputeShader::SetShaderAndCBs()
1577{
1578 // Is shader valid?
1579 if (!shaderValid) return;
1580
1581 // Set the shader
1582 deviceContext->CSSetShader(shader, 0, 0);
1583
1584 // Set the constant buffers?
1585 for (unsigned int i = 0; i < constantBufferCount; i++)
1586 {
1587 // Skip "buffers" that aren't true constant buffers
1588 if (constantBuffers[i].Type != D3D11_CT_CBUFFER)
1589 continue;
1590
1591 // This is a real constant buffer, so set it
1592 deviceContext->CSSetConstantBuffers(
1593 constantBuffers[i].BindIndex,
1594 1,
1595 &constantBuffers[i].ConstantBuffer);
1596 }
1597}
1598
1599// --------------------------------------------------------
1600// Dispatches the compute shader with the specified amount
1601// of groups, using the number of threads per group
1602// specified in the shader file itself
1603//
1604// For example, calling this method with params (5,1,1) on
1605// a shader with (8,2,2) threads per group will launch a
1606// total of 160 threads: ((5 * 8) * (1 * 2) * (1 * 2))
1607//
1608// This is identical to using the device context's
1609// Dispatch() method yourself.
1610//
1611// Note: This will dispatch the currently active shader,
1612// not necessarily THIS shader. Be sure to activate this
1613// shader with SetShader() before calling Dispatch
1614//
1615// groupsX - Numbers of groups in the X dimension
1616// groupsY - Numbers of groups in the Y dimension
1617// groupsZ - Numbers of groups in the Z dimension
1618// --------------------------------------------------------
1619void SimpleComputeShader::DispatchByGroups(unsigned int groupsX, unsigned int groupsY, unsigned int groupsZ)
1620{
1621 deviceContext->Dispatch(groupsX, groupsY, groupsZ);
1622}
1623
1624// --------------------------------------------------------
1625// Dispatches the compute shader with AT LEAST the
1626// specified amount of threads, calculating the number of
1627// groups to dispatch using the number of threads per group
1628// specified in the shader file itself
1629//
1630// For example, calling this method with params (10,3,3) on
1631// a shader with (5,2,2) threads per group will launch
1632// 8 total groups and 160 total threads, calculated by:
1633// Groups: ceil(10/5) * ceil(3/2) * ceil(3/2) = 8
1634// Threads: ((2 * 5) * (2 * 2) * (2 * 2)) = 160
1635//
1636// Note: This will dispatch the currently active shader,
1637// not necessarily THIS shader. Be sure to activate this
1638// shader with SetShader() before calling Dispatch
1639//
1640// threadsX - Desired numbers of threads in the X dimension
1641// threadsY - Desired numbers of threads in the Y dimension
1642// threadsZ - Desired numbers of threads in the Z dimension
1643// --------------------------------------------------------
1644void SimpleComputeShader::DispatchByThreads(unsigned int threadsX, unsigned int threadsY, unsigned int threadsZ)
1645{
1646 deviceContext->Dispatch(
1647 max((unsigned int)ceil((float)threadsX / this->threadsX), 1),
1648 max((unsigned int)ceil((float)threadsY / this->threadsY), 1),
1649 max((unsigned int)ceil((float)threadsZ / this->threadsZ), 1));
1650}
1651
1652// --------------------------------------------------------
1653// Sets a shader resource view in the Compute shader stage
1654//
1655// name - The name of the texture resource in the shader
1656// srv - The shader resource view of the texture in GPU memory
1657//
1658// Returns true if a texture of the given name was found, false otherwise
1659// --------------------------------------------------------
1660bool SimpleComputeShader::SetShaderResourceView(std::string name, ID3D11ShaderResourceView* srv)
1661{
1662 // Look for the variable and verify
1663 const SimpleSRV* srvInfo = GetShaderResourceViewInfo(name);
1664 if (srvInfo == 0)
1665 return false;
1666
1667 // Set the shader resource view
1668 deviceContext->CSSetShaderResources(srvInfo->BindIndex, 1, &srv);
1669
1670 // Success
1671 return true;
1672}
1673
1674// --------------------------------------------------------
1675// Sets a sampler state in the Compute shader stage
1676//
1677// name - The name of the sampler state in the shader
1678// samplerState - The sampler state in GPU memory
1679//
1680// Returns true if a sampler of the given name was found, false otherwise
1681// --------------------------------------------------------
1682bool SimpleComputeShader::SetSamplerState(std::string name, ID3D11SamplerState* samplerState)
1683{
1684 // Look for the variable and verify
1685 const SimpleSampler* sampInfo = GetSamplerInfo(name);
1686 if (sampInfo == 0)
1687 return false;
1688
1689 // Set the shader resource view
1690 deviceContext->CSSetSamplers(sampInfo->BindIndex, 1, &samplerState);
1691
1692 // Success
1693 return true;
1694}
1695
1696// --------------------------------------------------------
1697// Sets an unordered access view in the Compute shader stage
1698//
1699// name - The name of the sampler state in the shader
1700// uav - The UAV in GPU memory
1701// appendConsumeOffset - Used for append or consume UAV's (optional)
1702//
1703// Returns true if a UAV of the given name was found, false otherwise
1704// --------------------------------------------------------
1705bool SimpleComputeShader::SetUnorderedAccessView(std::string name, ID3D11UnorderedAccessView * uav, unsigned int appendConsumeOffset)
1706{
1707 // Look for the variable and verify
1708 unsigned int bindIndex = GetUnorderedAccessViewIndex(name);
1709 if (bindIndex == -1)
1710 return false;
1711
1712 // Set the shader resource view
1713 deviceContext->CSSetUnorderedAccessViews(bindIndex, 1, &uav, &appendConsumeOffset);
1714
1715 // Success
1716 return true;
1717}
1718
1719// --------------------------------------------------------
1720// Gets the index of the specified UAV (or -1)
1721// --------------------------------------------------------
1722int SimpleComputeShader::GetUnorderedAccessViewIndex(std::string name)
1723{
1724 // Look for the key
1725 std::unordered_map<std::string, unsigned int>::iterator result =
1726 uavTable.find(name);
1727
1728 // Did we find the key?
1729 if (result == uavTable.end())
1730 return -1;
1731
1732 // Success
1733 return result->second;
1734}