-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShaderReflection.h
150 lines (128 loc) · 4.29 KB
/
ShaderReflection.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma once
#include <D3D11.h>
#include <D3Dcompiler.h>
#include <d3d11shader.h>
#include <string>
#include <map>
#include <fstream>
#include <sstream>
#include <vector>
#include "DXCore.h" // Replace with your DXCore etc
#pragma comment(lib, "dxguid.lib")
enum ShaderStage {
VertexShader,
PixelShader
};
struct ConstantBufferVariable {
unsigned int offset;
unsigned int size;
};
class ConstantBuffer {
public:
std::string name;
std::map<std::string, ConstantBufferVariable> constantBufferData;
ID3D11Buffer* cb;
unsigned char* buffer;
unsigned int cbSizeInBytes;
int dirty;
int index;
ShaderStage shaderStage;
void init(DXCore* core, unsigned int sizeInBytes, int constantBufferIndex, ShaderStage _shaderStage) {
unsigned int sizeInBytes16 = ((sizeInBytes + 15) & -16);
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA data;
bd.ByteWidth = sizeInBytes16;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
core->device->CreateBuffer(&bd, NULL, &cb);
buffer = new unsigned char[sizeInBytes16];
cbSizeInBytes = sizeInBytes;
index = constantBufferIndex;
dirty = 1;
shaderStage = _shaderStage;
}
void update(std::string name, void* data) {
ConstantBufferVariable cbVariable = constantBufferData[name];
memcpy(&buffer[cbVariable.offset], data, cbVariable.size);
dirty = 1;
}
void upload(DXCore* core) {
if (dirty == 1) {
D3D11_MAPPED_SUBRESOURCE mapped;
core->devicecontext->Map(cb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
memcpy(mapped.pData, buffer, cbSizeInBytes);
core->devicecontext->Unmap(cb, 0);
if (shaderStage == ShaderStage::VertexShader) {
core->devicecontext->VSSetConstantBuffers(index, 1, &cb);
}
if (shaderStage == ShaderStage::PixelShader) {
core->devicecontext->PSSetConstantBuffers(index, 1, &cb);
}
dirty = 0;
}
}
void free() {
cb->Release();
}
};
class ConstantBufferReflection {
public:
void build(DXCore* core, ID3DBlob* shader, std::vector<ConstantBuffer>& buffers, std::map<std::string, int>& textureBindPoints, ShaderStage _shaderStage) {
ID3D11ShaderReflection* reflection;
D3DReflect(shader->GetBufferPointer(), shader->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflection);
D3D11_SHADER_DESC desc;
reflection->GetDesc(&desc);
for (int i = 0; i < desc.ConstantBuffers; i++) {
ConstantBuffer buffer;
ID3D11ShaderReflectionConstantBuffer* constantBuffer = reflection->GetConstantBufferByIndex(i);
D3D11_SHADER_BUFFER_DESC cbDesc;
constantBuffer->GetDesc(&cbDesc);
buffer.name = cbDesc.Name;
unsigned int totalSize = 0;
for (int n = 0; n < cbDesc.Variables; n++) {
ID3D11ShaderReflectionVariable* var = constantBuffer->GetVariableByIndex(n);
D3D11_SHADER_VARIABLE_DESC vDesc;
var->GetDesc(&vDesc);
ConstantBufferVariable bufferVariable;
bufferVariable.offset = vDesc.StartOffset;
bufferVariable.size = vDesc.Size;
buffer.constantBufferData.insert({ vDesc.Name, bufferVariable });
totalSize += bufferVariable.size;
}
buffer.init(core, totalSize, i, _shaderStage);
buffers.push_back(buffer);
}
for (int i = 0; i < desc.BoundResources; i++) {
D3D11_SHADER_INPUT_BIND_DESC bindDesc;
reflection->GetResourceBindingDesc(i, &bindDesc);
if (bindDesc.Type == D3D_SIT_TEXTURE) {
textureBindPoints.insert({ bindDesc.Name, bindDesc.BindPoint });
}
}
}
};
// How to use
/*
Define in shader class:
std::vector<ConstantBuffer> psConstantBuffers;
std::vector<ConstantBuffer> vsConstantBuffers;
std::map<std::string, int> textureBindPointsVS;
std::map<std::string, int> textureBindPointsPS;
void loadPS(Core *core, std::string hlsl)
{
ID3DBlob* shader;
ID3DBlob* status;
HRESULT hr = D3DCompile(hlsl.c_str(), strlen(hlsl.c_str()), NULL, NULL, NULL, "PS", "ps_5_0", 0, 0, &shader, &status);
if (FAILED(hr))
{
printf("%s\n", (char*)status->GetBufferPointer());
exit(0);
}
core->device->CreatePixelShader(shader->GetBufferPointer(), shader->GetBufferSize(), NULL, &ps);
ConstantBufferReflection reflection;
reflection.build(core, shader, psConstantBuffers, textureBindPointsPS);
}
And repeat for loadVS
*/