Diligent Engine API Reference
PipelineStateBase.h
1 /* Copyright 2015-2018 Egor Yusov
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12  *
13  * In no event and under no legal theory, whether in tort (including negligence),
14  * contract, or otherwise, unless required by applicable law (such as deliberate
15  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16  * liable for any damages, including any direct, indirect, special, incidental,
17  * or consequential damages of any character arising as a result of this License or
18  * out of the use or inability to use the software (including but not limited to damages
19  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20  * all other commercial damages or losses), even if such Contributor has been advised
21  * of the possibility of such damages.
22  */
23 
24 #pragma once
25 
28 
29 #include "PipelineState.h"
30 #include "DeviceObjectBase.h"
31 #include "STDAllocator.h"
32 #include "EngineMemory.h"
33 #include "GraphicsAccessories.h"
34 
35 namespace Diligent
36 {
37 
39 
45 template<class BaseInterface, class RenderDeviceBaseInterface>
46 class PipelineStateBase : public DeviceObjectBase<BaseInterface, PipelineStateDesc>
47 {
48 public:
51 
57  PipelineStateBase( IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const PipelineStateDesc& PSODesc, bool bIsDeviceInternal = false ) :
58  TDeviceObjectBase( pRefCounters, pDevice, PSODesc, bIsDeviceInternal ),
59  m_LayoutElements( PSODesc.GraphicsPipeline.InputLayout.NumElements, LayoutElement(), STD_ALLOCATOR_RAW_MEM(LayoutElement, GetRawAllocator(), "Allocator for vector<LayoutElement>" ) ),
60  m_NumShaders(0)
61  {
62  memset(m_ppShaders, 0, sizeof(m_ppShaders));
63 
64  if (this->m_Desc.IsComputePipeline)
65  {
66  const auto &ComputePipeline = PSODesc.ComputePipeline;
67  if (ComputePipeline.pCS == nullptr)
68  {
69  LOG_ERROR_AND_THROW( "Compute shader is not provided" );
70  }
71 
72 #define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName)\
73  if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \
74  { \
75  LOG_ERROR_AND_THROW( GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not valid type for ", ShaderName, " shader" );\
76  }
77  VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute")
78 
79  m_pCS = ComputePipeline.pCS;
80  m_ppShaders[0] = ComputePipeline.pCS;
81  m_NumShaders = 1;
82  }
83  else
84  {
85  const auto &GraphicsPipeline = PSODesc.GraphicsPipeline;
86 
87  VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex")
88  VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel")
89  VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry")
90  VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull")
91  VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain")
92 #undef VALIDATE_SHADER_TYPE
93 
94  m_pVS = GraphicsPipeline.pVS;
95  m_pPS = GraphicsPipeline.pPS;
96  m_pGS = GraphicsPipeline.pGS;
97  m_pDS = GraphicsPipeline.pDS;
98  m_pHS = GraphicsPipeline.pHS;
99 
100  if( GraphicsPipeline.pVS )m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS;
101  if( GraphicsPipeline.pPS )m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS;
102  if( GraphicsPipeline.pGS )m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS;
103  if( GraphicsPipeline.pHS )m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS;
104  if( GraphicsPipeline.pDS )m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS;
105  }
106 
107  const auto &InputLayout = PSODesc.GraphicsPipeline.InputLayout;
108  for( size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem )
109  m_LayoutElements[Elem] = InputLayout.LayoutElements[Elem];
110  this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = m_LayoutElements.data();
111 
112  // Correct description and compute offsets and tight strides
113  for( auto It = m_LayoutElements.begin(); It != m_LayoutElements.end(); ++It )
114  {
115  if( It->ValueType == VT_FLOAT32 || It->ValueType == VT_FLOAT16 )
116  It->IsNormalized = false; // Floating point values cannot be normalized
117 
118  auto BuffSlot = It->BufferSlot;
119  if( BuffSlot >= _countof(m_TightStrides) )
120  {
121  UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds the limit (", _countof(m_TightStrides), ")");
122  continue;
123  }
124 
125  auto &CurrStride = m_TightStrides[BuffSlot];
126  if( It->RelativeOffset < CurrStride )
127  {
128  if( It->RelativeOffset == 0 )
129  It->RelativeOffset = CurrStride;
130  else
131  UNEXPECTED( "Overlapping layout elements" );
132  }
133 
134  CurrStride += It->NumComponents * GetValueSize( It->ValueType );
135  }
136  }
137 
139  {
140  /*
148  auto &PipelineStateRegistry = static_cast<TRenderDeviceBase*>(this->GetDevice())->GetBSRegistry();
149  auto &RasterizerStateRegistry = static_cast<TRenderDeviceBase*>(this->GetDevice())->GetRSRegistry();
150  auto &DSSRegistry = static_cast<TRenderDeviceBase*>(this->GetDevice())->GetDSSRegistry();
151  // StateObjectsRegistry::ReportDeletedObject() does not lock the registry, but only
152  // atomically increments the outstanding deleted objects counter.
153  PipelineStateRegistry.ReportDeletedObject();
154  RasterizerStateRegistry.ReportDeletedObject();
155  DSSRegistry.ReportDeletedObject();
156  */
157  }
158 
159  IMPLEMENT_QUERY_INTERFACE_IN_PLACE( IID_PipelineState, TDeviceObjectBase )
160 
161  virtual const Uint32* GetTightStrides()const
162  {
163  return m_TightStrides;
164  }
165 
166  IShader* GetVS(){return m_pVS;}
167  IShader* GetPS(){return m_pPS;}
168  IShader* GetGS(){return m_pGS;}
169  IShader* GetDS(){return m_pDS;}
170  IShader* GetHS(){return m_pHS;}
171  IShader* GetCS(){return m_pCS;}
172 
173  IShader* const* GetShaders()const{return m_ppShaders;}
174  Uint32 GetNumShaders()const{return m_NumShaders;}
175 
176 protected:
177  std::vector<LayoutElement, STDAllocatorRawMem<LayoutElement> > m_LayoutElements;
178 
179  // The size of this array must be equal to the
180  // maximum number of buffer slots, because a layout
181  // element can refer to any input slot
182  Uint32 m_TightStrides[MaxBufferSlots] = {};
183 
191  Uint32 m_NumShaders;
192 };
193 
194 }
static constexpr Uint32 MaxBufferSlots
Maximum number of input buffer slots. D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT == 32...
Definition: Constants.h:33
RefCntAutoPtr< IShader > m_pDS
Strong reference to the domain shader.
Definition: PipelineStateBase.h:187
Render device interface.
Definition: RenderDevice.h:55
Shader interface.
Definition: Shader.h:288
RefCntAutoPtr< IShader > m_pCS
Strong reference to the compute shader.
Definition: PipelineStateBase.h:189
Template class implementing base functionality for a pipeline state object.
Definition: PipelineStateBase.h:46
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Pixel (fragment) shader.
Definition: Shader.h:50
RefCntAutoPtr< IShader > m_pVS
Strong reference to the vertex shader.
Definition: PipelineStateBase.h:184
IMemoryAllocator & GetRawAllocator()
Returns raw memory allocator.
Definition: EngineMemory.cpp:46
Hull (tessellation control) shader.
Definition: Shader.h:52
Domain (tessellation evaluation) shader.
Definition: Shader.h:53
PipelineStateBase(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const PipelineStateDesc &PSODesc, bool bIsDeviceInternal=false)
Definition: PipelineStateBase.h:57
Description of a single element of the input layout.
Definition: InputLayout.h:37
Base implementation of a render device.
Definition: DeviceObjectBase.h:36
Vertex shader.
Definition: Shader.h:49
Uint32 m_NumShaders
Number of shaders that this PSO uses.
Definition: PipelineStateBase.h:191
PipelineStateDesc m_Desc
Object description.
Definition: DeviceObjectBase.h:138
RefCntAutoPtr< IShader > m_pGS
Strong reference to the geometry shader.
Definition: PipelineStateBase.h:186
Half-precision 16-bit floating point.
Definition: GraphicsTypes.h:48
Full-precision 32-bit floating point.
Definition: GraphicsTypes.h:49
ComputePipelineDesc ComputePipeline
Compute pipeline state description. This memeber is ignored if IsComputePipeline == False...
Definition: PipelineState.h:188
InputLayoutDesc InputLayout
Input layout.
Definition: PipelineState.h:124
IShader * m_ppShaders[5]
Array of pointers to shaders that this PSO uses.
Definition: PipelineStateBase.h:190
RefCntAutoPtr< IShader > m_pHS
Strong reference to the hull shader.
Definition: PipelineStateBase.h:188
Template class that implements reference counting.
Definition: RefCntAutoPtr.h:71
bool IsComputePipeline
Flag indicating if pipeline state is a compute pipeline state.
Definition: PipelineState.h:182
GraphicsPipelineDesc GraphicsPipeline
Graphics pipeline state description. This memeber is ignored if IsComputePipeline == True...
Definition: PipelineState.h:185
RefCntAutoPtr< IShader > m_pPS
Strong reference to the pixel shader.
Definition: PipelineStateBase.h:185
Template class implementing base functionality for a device object.
Definition: DeviceObjectBase.h:42
Pipeline state description.
Definition: PipelineState.h:179
Compute shader.
Definition: Shader.h:54
Geometry shader.
Definition: Shader.h:51