1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "CoreThread/BsCoreObject.h"
7#include "Reflection/BsIReflectable.h"
8#include "Utility/BsDataBlob.h"
9#include "BsVertexDeclaration.h"
10
11namespace bs
12{
13 /** @addtogroup RenderAPI
14 * @{
15 */
16
17 struct GpuProgramBytecode;
18
19 /** Descriptor structure used for initialization of a GpuProgram. */
20 struct GPU_PROGRAM_DESC
21 {
22 String source; /**< Source code to compile the program from. */
23 String entryPoint; /**< Name of the entry point function, for example "main". */
24 String language; /**< Language the source is written in, for example "hlsl" or "glsl". */
25 GpuProgramType type = GPT_VERTEX_PROGRAM; /**< Type of the program, for example vertex or fragment. */
26 bool requiresAdjacency = false; /**< If true then adjacency information will be provided when rendering. */
27
28 /**
29 * Optional intermediate version of the GPU program. Can significantly speed up GPU program compilation/creation
30 * when supported by the render backend. Call ct::GpuProgram::compileBytecode to generate it.
31 */
32 SPtr<GpuProgramBytecode> bytecode;
33 };
34
35 /**
36 * Contains a GPU program such as vertex or fragment program which gets compiled from the provided source code.
37 *
38 * @note Sim thread only.
39 */
40 class BS_CORE_EXPORT GpuProgram : public IReflectable, public CoreObject
41 {
42 public:
43 /** Information returned when compiling a GPU program. */
44 struct CompileStatus
45 {
46 bool success = false;
47 String messages;
48 };
49
50 virtual ~GpuProgram() = default;
51
52 /**
53 * Returns true if the program was successfully compiled.
54 *
55 * @note Only valid after core thread has initialized the program.
56 */
57 bool isCompiled() const;
58
59 /**
60 * Returns an error message returned by the compiler, if the compilation failed.
61 *
62 * @note Only valid after core thread has initialized the program.
63 */
64 String getCompileErrorMessage() const;
65
66 /**
67 * Returns description of all parameters in this GPU program.
68 *
69 * @note Only valid after core thread has initialized the program.
70 */
71 SPtr<GpuParamDesc> getParamDesc() const;
72
73 /** Retrieves a core implementation of a gpu program usable only from the core thread. */
74 SPtr<ct::GpuProgram> getCore() const;
75
76 /**
77 * Creates a new GPU program using the provided source code. If compilation fails or program is not supported
78 * isCompiled() with return false, and you will be able to retrieve the error message via getCompileErrorMessage().
79 *
80 * @param[in] desc Description of the program to create.
81 */
82 static SPtr<GpuProgram> create(const GPU_PROGRAM_DESC& desc);
83
84 protected:
85 friend class GpuProgramManager;
86
87 GpuProgram(const GPU_PROGRAM_DESC& desc);
88
89 /** @copydoc CoreObject::createCore */
90 SPtr<ct::CoreObject> createCore() const override;
91
92 protected:
93 bool mNeedsAdjacencyInfo;
94 String mLanguage;
95 GpuProgramType mType;
96 String mEntryPoint;
97 String mSource;
98
99 SPtr<GpuProgramBytecode> mBytecode;
100
101 /************************************************************************/
102 /* SERIALIZATION */
103 /************************************************************************/
104 public:
105 friend class GpuProgramRTTI;
106 static RTTITypeBase* getRTTIStatic();
107 RTTITypeBase* getRTTI() const override;
108 };
109
110 /**
111 * A GPU program compiled to an intermediate bytecode format, as well as any relevant meta-data that could be
112 * extracted from that format.
113 */
114 struct BS_CORE_EXPORT GpuProgramBytecode : IReflectable
115 {
116 ~GpuProgramBytecode();
117
118 /** Instructions (compiled code) for the GPU program. Contains no data if compilation was not succesful. */
119 DataBlob instructions;
120
121 /** Reflected information about GPU program parameters. */
122 SPtr<GpuParamDesc> paramDesc;
123
124 /** Input parameters for a vertex GPU program. */
125 Vector<VertexElement> vertexInput;
126
127 /** Messages output during the compilation process. Includes errors in case compilation failed. */
128 String messages;
129
130 /** Identifier of the compiler that compiled the bytecode. */
131 String compilerId;
132
133 /** Version of the compiler that compiled the bytecode. */
134 UINT32 compilerVersion = 0;
135
136 /************************************************************************/
137 /* SERIALIZATION */
138 /************************************************************************/
139 public:
140 friend class GpuProgramBytecodeRTTI;
141 static RTTITypeBase* getRTTIStatic();
142 RTTITypeBase* getRTTI() const override;
143 };
144
145 /** @} */
146
147 namespace ct
148 {
149 /** @addtogroup RenderAPI-Internal
150 * @{
151 */
152
153 /**
154 * Core thread version of a bs::GpuProgram.
155 *
156 * @note Core thread only.
157 */
158 class BS_CORE_EXPORT GpuProgram : public CoreObject
159 {
160 public:
161 virtual ~GpuProgram();
162
163 /** Returns whether this program can be supported on the current renderer and hardware. */
164 virtual bool isSupported() const;
165
166 /** Returns true if program was successfully compiled. */
167 virtual bool isCompiled() const { return mIsCompiled; }
168
169 /** Returns an error message returned by the compiler, if the compilation failed. */
170 virtual String getCompileErrorMessage() const { return mCompileMessages; }
171
172 /**
173 * Sets whether this geometry program requires adjacency information from the input primitives.
174 *
175 * @note Only relevant for geometry programs.
176 */
177 virtual void setAdjacencyInfoRequired(bool required) { mNeedsAdjacencyInfo = required; }
178
179 /**
180 * Returns whether this geometry program requires adjacency information from the input primitives.
181 *
182 * @note Only relevant for geometry programs.
183 */
184 virtual bool isAdjacencyInfoRequired() const { return mNeedsAdjacencyInfo; }
185
186 /** Type of GPU program (for example fragment, vertex). */
187 GpuProgramType getType() const { return mType; }
188
189 /** @copydoc bs::GpuProgram::getParamDesc */
190 SPtr<GpuParamDesc> getParamDesc() const { return mParametersDesc; }
191
192 /** Returns GPU program input declaration. Only relevant for vertex programs. */
193 SPtr<VertexDeclaration> getInputDeclaration() const { return mInputDeclaration; }
194
195 /** Returns the compiled bytecode of this program. */
196 SPtr<GpuProgramBytecode> getBytecode() const { return mBytecode; }
197
198 /**
199 * @copydoc bs::GpuProgram::create(const GPU_PROGRAM_DESC&)
200 * @param[in] deviceMask Mask that determines on which GPU devices should the object be created on.
201 */
202 static SPtr<GpuProgram> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
203
204 /**
205 * Compiles the GPU program to an intermediate bytecode format. The bytecode can be cached and used for
206 * quicker compilation/creation of GPU programs.
207 */
208 static SPtr<GpuProgramBytecode> compileBytecode(const GPU_PROGRAM_DESC& desc);
209
210 protected:
211 friend class GpuProgramRTTI;
212
213 GpuProgram(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
214
215 bool mNeedsAdjacencyInfo;
216
217 bool mIsCompiled = false;
218 String mCompileMessages;
219
220 SPtr<GpuParamDesc> mParametersDesc;
221 SPtr<VertexDeclaration> mInputDeclaration;
222
223 GpuProgramType mType;
224 String mEntryPoint;
225 String mSource;
226
227 SPtr<GpuProgramBytecode> mBytecode;
228 };
229
230 /** @} */
231 }
232}
233