1#include "EffectsD3D12.h"
3#include <D3Dcompiler.h>
5#include "../Base/Utilities.h"
7#include "GraphicsDeviceD3D12.h"
16 for (
size_t i = 0; i < macros.size(); i++) {
17 LOG_DEBUG(logger,
"PPM: %s: %s", macros[i].Name, macros[i].Definition);
20 const char* start = src.data();
25 while ((*stop !=
'\0') && (*stop !=
'\n') && (*stop !=
'\r')) { stop++; }
27 LOG_DEBUG(logger,
"%3d: %s", line++, std::string(start, stop - start).c_str());
29 while ((*stop !=
'\0') && (*stop !=
'\n')) { stop++; }
30 while ((*stop !=
'\0') && (*stop ==
'\r')) { stop++; }
33 }
while (*stop !=
'\0');
41 this->effects.removeResource(handle);
44HRESULT Cogs::EffectsD3D12::compileShader(
const std::string & source,
const std::vector<D3D_SHADER_MACRO> & macros,
const std::string & entryPoint,
const std::string & profile, UINT flags,
ID3DBlob ** byteCode,
Cogs::EffectFlags::EEffectFlags effectFlags)
48 if (FAILED(D3DCompile(source.c_str(), source.size(),
nullptr, macros.data(),
nullptr, entryPoint.c_str(), profile.c_str(), flags, 0, byteCode, errorBlob.internalPointer()))) {
49 dumpSource(source, macros, effectFlags);
51 LOG_ERROR(logger,
"%s", errorBlob->GetBufferPointer());
54 }
else if (errorBlob) {
55 dumpSource(source, macros, effectFlags);
57 LOG_WARNING(logger,
"%s", errorBlob->GetBufferPointer());
63void Cogs::EffectsD3D12::setDevice(
const ResourcePointer<ID3D12Device>& device, GraphicsDeviceD3D12 * graphicsDevice)
65 this->device = device;
66 this->persistentEffects = 0;
67 this->graphicsDevice = graphicsDevice;
69 EffectsCommon::initialize(graphicsDevice->getBuffers());
80 Utilities::readFile(handler, fileName, csSource);
85 std::vector<D3D_SHADER_MACRO> macros(defines.size() + 1);
87 for (
size_t i = 0; i < defines.size(); ++i) {
88 D3D_SHADER_MACRO macro = { defines[i].first.c_str(), defines[i].second.c_str() };
93 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY | D3DCOMPILE_DEBUG | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
95 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
98 if (FAILED(D3DCompile(csSource.content.c_str(), csSource.content.size(),
nullptr, macros.data(),
nullptr,
"main",
"cs_5_0", flags, 0, effect.computeShader.byteCode.internalPointer(), errorBlob.internalPointer()))) {
99 LOG_ERROR(logger,
"%s", errorBlob->GetBufferPointer());
101 }
else if (errorBlob) {
102 LOG_WARNING(logger,
"%s", errorBlob->GetBufferPointer());
105 reflectShader(effect.computeShader);
107 return effects.addResource(effect);
123 std::vector<D3D_SHADER_MACRO> macros(desc.definitions.size() + 1);
125 for (
size_t i = 0; i < desc.definitions.size(); ++i) {
126 D3D_SHADER_MACRO macro = { desc.definitions[i].first.c_str(), desc.definitions[i].second.c_str() };
131 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY | D3DCOMPILE_DEBUG | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
133 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
136 const char * profiles[ShaderType::NumShaderTypes] = {
"vs_5_0",
"hs_5_0",
"ds_5_0",
"gs_5_0",
"ps_5_0" };
137 const ProcessedContent * sources[ShaderType::NumShaderTypes] = { &vsSource, &hsSource, &dsSource, &gsSource, &psSource };
138 const StringView * entryPoints[ShaderType::NumShaderTypes] = { &vsEntryPoint, &hsEntryPoint, &dsEntryPoint, &gsEntryPoint, &psEntryPoint };
139 ResourcePointer<ID3DBlob> byteCode[ShaderType::NumShaderTypes];
142 for (
int i = 0; i < ShaderType::NumShaderTypes; i++) {
143 if (sources[i]->content.empty()) {
147 if (FAILED(D3DCompile(sources[i]->content.c_str(),
148 sources[i]->content.size(),
152 entryPoints[i]->data(),
154 flags, 0, byteCode[i].internalPointer(), errorBlob.internalPointer())))
158 }
else if (errorBlob) {
162 effect.shaders[i].byteCode = &*byteCode[i];
163 effect.shaders[i].byteCode->AddRef();
165 reflectShader(effect.shaders[i]);
168 effect.buildSignature();
170 effect.rootSignature = createSignature(effect.signature);
172 auto handle = this->effects.addResource(effect);
179 this->effects.clear();
182void Cogs::EffectsD3D12::reflectShader(
Shader & shader)
184 auto code = shader.byteCode.get<
ID3DBlob>();
186 ID3D12ShaderReflection * reflector =
nullptr;
187 D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D12ShaderReflection, (
void **) &reflector);
189 D3D12_SHADER_DESC shaderDesc;
190 reflector->GetDesc(&shaderDesc);
192 shader.reflection.constantBuffers.resize(shaderDesc.ConstantBuffers);
194 for (UINT i = 0; i < shaderDesc.ConstantBuffers; ++i) {
195 auto constantBufferReflect = reflector->GetConstantBufferByIndex(i);
196 auto & constantBuffer = shader.reflection.constantBuffers[i];
197 constantBuffer.slot = i;
198 constantBuffer.dirty =
true;
200 D3D12_SHADER_BUFFER_DESC cbDesc;
201 constantBufferReflect->GetDesc(&cbDesc);
203 shader.reflection.slots[
StringId(cbDesc.Name)] = i;
205 constantBuffer.memoryBuffer.resize(cbDesc.Size);
209 constantBuffer.offsets.resize(cbDesc.Variables);
210 constantBuffer.sizes.resize(cbDesc.Variables);
212 for (UINT j = 0; j < cbDesc.Variables; ++j) {
213 auto variable = constantBufferReflect->GetVariableByIndex(j);
215 D3D12_SHADER_VARIABLE_DESC vDesc;
216 variable->GetDesc(&vDesc);
218 D3D12_SHADER_TYPE_DESC tDesc;
219 variable->GetType()->GetDesc(&tDesc);
221 constantBuffer.variables[
StringId(vDesc.Name)] =
static_cast<uint16_t
>(j);
222 constantBuffer.offsets[j] = vDesc.StartOffset;
223 constantBuffer.sizes[j] = vDesc.Size;
227 for (UINT i = 0; i < shaderDesc.BoundResources; ++i) {
228 D3D12_SHADER_INPUT_BIND_DESC iDesc;
229 reflector->GetResourceBindingDesc(i, &iDesc);
231 if (iDesc.Type == D3D_SIT_TEXTURE || iDesc.Type == D3D_SIT_UAV_RWTYPED) {
232 shader.reflection.textures[StringId(iDesc.Name)] = iDesc.BindPoint;
233 shader.reflection.srvSlots = std::max(shader.reflection.srvSlots, iDesc.BindPoint + 1);
234 }
else if (iDesc.Type == D3D_SIT_SAMPLER) {
235 shader.reflection.samplers[StringId(iDesc.Name)] = iDesc.BindPoint;
236 }
else if (iDesc.Type == D3D_SIT_UAV_RWSTRUCTURED || iDesc.Type == D3D_SIT_UAV_RWBYTEADDRESS || iDesc.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) {
237 shader.reflection.bufferUAVs[StringId(iDesc.Name)] = iDesc.BindPoint;
238 }
else if (iDesc.Type == D3D_SIT_STRUCTURED || iDesc.Type == D3D_SIT_BYTEADDRESS) {
239 shader.reflection.bufferSRVs[StringId(iDesc.Name)] = iDesc.BindPoint;
240 shader.reflection.srvSlots = std::max(shader.reflection.srvSlots, iDesc.BindPoint + 1);
247 const D3D12_DESCRIPTOR_RANGE_TYPE rangeTypes[] = {
248 D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
249 D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
250 D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
251 D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
254 const D3D12_SHADER_VISIBILITY shaderVisibilities[] = {
255 D3D12_SHADER_VISIBILITY_VERTEX,
256 D3D12_SHADER_VISIBILITY_HULL,
257 D3D12_SHADER_VISIBILITY_DOMAIN,
258 D3D12_SHADER_VISIBILITY_GEOMETRY,
259 D3D12_SHADER_VISIBILITY_PIXEL
262 std::vector<CD3DX12_DESCRIPTOR_RANGE> ranges(
size_t(SlotType::NumSlotTypes) *
size_t(ShaderType::NumShaderTypes));
263 std::vector<CD3DX12_ROOT_PARAMETER> slotRootParameter;
265 for (uint32_t i = 0; i < SlotType::NumSlotTypes; ++i) {
266 for (uint32_t j = 0; j < ShaderType::NumShaderTypes; ++j) {
267 auto & rangeDesc = ranges[i * ShaderType::NumShaderTypes + j];
269 auto & slots = signature.slots[i].values[j];
272 rangeDesc.Init(rangeTypes[i], slots, 0);
274 slotRootParameter.emplace_back();
276 auto & parameter = slotRootParameter.back();
277 parameter.InitAsDescriptorTable(1, &rangeDesc, shaderVisibilities[j]);
282 const D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
284 CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
285 descRootSignature.Init(
static_cast<UINT
>(slotRootParameter.size()), slotRootParameter.data(), 0,
nullptr, rootSignatureFlags);
287 ResourcePointer<ID3D12RootSignature> rootSignature;
288 ResourcePointer<ID3DBlob> pOutBlob;
289 ResourcePointer<ID3DBlob> pErrorBlob;
290 if (FAILED(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pOutBlob.internalPointer(), pErrorBlob.internalPointer()))) {
291 LOG_ERROR(logger,
"Could not serialize root signature: %s", pErrorBlob->GetBufferPointer());
296 if (FAILED(device->CreateRootSignature(0, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(rootSignature.internalPointer())))) {
297 LOG_ERROR(logger,
"Could not create root signature.");
302 return rootSignature;
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
std::vector< PreprocessorDefinition > PreprocessorDefinitions
A set of preprocessor definitions.
@ Write
The buffer can be mapped and written to by the CPU after creation.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Contains an effect description used to load a single effect.
EEffectFlags
Effect source flags.
@ LogShaderSource
Log the contents of the shader on error.
@ Pinned
Effect can only be released explicitly, not using releaseResources().
void releaseResources()
Release all allocated effect resources.
void releaseEffect(EffectHandle handle)
Release the effect with the given handle, freeing all resources generated during program loading.
EffectHandle loadComputeEffect(const StringView &fileName, EffectFlags::EEffectFlags effectFlags) override
Load the compute shader with the given file name and create an effect.
static const Handle_t InvalidHandle
Represents an invalid handle.