Files

198 lines
5.3 KiB
C++
Raw Permalink Normal View History

2025-05-13 02:50:08 +03:00
#include "Material.h"
#include <d3d11.h>
#include <stdint.h>
#include "nativelinq.h"
#include <cassert>
#include <cstring>
#include "d3dx12.h"
#include "FatalError.h"
void Material::SetShader(ShaderPtr _shader) {
shader = _shader;
RebuildBuffers();
}
std::string Material::DiffuseMapName() {
return "_DiffuseMap";
}
std::string Material::NormalMapName() {
return "_NormalMap";
}
std::string Material::DiffuseColorName() {
return "_DiffuseColor";
}
MaterialPtr Material::Create(std::string name) {
return std::shared_ptr<Material>(new Material(name));
}
MaterialPtr Material::Create(ShaderPtr shader, std::string name) {
auto material = Create(name);
material->SetShader(shader);
return material;
}
void Material::Apply() {
for(int i = 0; i < (int)ShaderType::Count; ++i) {
auto s = shader->GetShader((ShaderType)i);
if(s != nullptr) {
//apply shaders
//s->Apply(context);
auto& p = shaderParameters[i];
//update and apply buffers
for (auto& bufferCtx : p.buffers) {
D3D12_RANGE range;
range.Begin = range.End = 0;
uint8_t* data = nullptr;
auto hr = bufferCtx.buffer->Map(0, &range, (void**)&data);
assert(hr == S_OK);
//write all variables
for (auto& variable : bufferCtx.variables) {
auto param = parameters.GetParameterByName(variable.name);
if (param != nullptr) {
memcpy(data + variable.offset, param->GetPointer(), variable.size);
}
}
range.End = bufferCtx.size;
bufferCtx.buffer->Unmap(0, &range);
assert(hr == S_OK);
/*context->Unmap(bufferCtx.buffer, 0);
ID3D11Buffer* buffers[1] = { bufferCtx.buffer };
switch ((ShaderType)i)
{
case ShaderType::Vs:
context->VSSetConstantBuffers(bufferCtx.bindPoint, 1, buffers);
break;
case ShaderType::Ps:
context->PSSetConstantBuffers(bufferCtx.bindPoint, 1, buffers);
break;
default:
assert(false && "not implemented");
}*/
//sr.pData
}
//apply shader resources
/*for (auto& resourceCtx : p.resources) {
auto param = parameters.GetParameterByName(resourceCtx.name);
if (param != nullptr) {
auto resourceParam = std::dynamic_pointer_cast<ShaderResourceParameter>(param);
ID3D11ShaderResourceView* resources[1] = { resourceParam->value };
switch ((ShaderType)i)
{
case ShaderType::Vs:
context->VSSetShaderResources(resourceCtx.bindPoint, 1, resources);
break;
case ShaderType::Ps:
context->PSSetShaderResources(resourceCtx.bindPoint, 1, resources);
break;
default:
assert(false && "not implemented");
}
}
}*/
} else {
}
}
}
void Material::RebuildShaderParameters(ShaderParametersContext& params, ComPtr<ID3D12ShaderReflection> reflection) {
D3D12_SHADER_DESC d;
reflection->GetDesc(&d);
params.Clear();
//get resource variables
for(uint32_t i = 0; i < d.BoundResources; ++i) {
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
reflection->GetResourceBindingDesc(i, &bindDesc);
ShaderResourceVariable var;
var.bindPoint = bindDesc.BindPoint;
var.name = bindDesc.Name;
var.type = bindDesc.Type;
params.resources.push_back(var);
}
//get constant buffers
for(uint32_t i = 0; i < d.ConstantBuffers; ++i) {
ShaderBufferContext ctx;
ID3D12ShaderReflectionConstantBuffer* cb = reflection->GetConstantBufferByIndex(i);
auto device = shader->GetDevice();
D3D12_SHADER_BUFFER_DESC bufferDesc;
cb->GetDesc(&bufferDesc);
ctx.name = bufferDesc.Name;
D3D11_BUFFER_DESC cbDesc;
cbDesc.ByteWidth = bufferDesc.Size;
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.StructureByteStride = 0;
auto hr = device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), // this heap will be used to upload the constant buffer data
D3D12_HEAP_FLAG_NONE, // no flags
&CD3DX12_RESOURCE_DESC::Buffer(1024 * 64), // Must be a multiple of 64KB for single-textures and constant buffers. TODO: handle size overflow o_O Maybe.
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&ctx.buffer));
ctx.buffer->SetName(L"Constant Buffer Upload Resource Heap");
//device->CreateBuffer(&cbDesc, nullptr, &ctx.buffer);
for(uint32_t j = 0; j < bufferDesc.Variables; ++j) {
auto variable = cb->GetVariableByIndex(j);
D3D12_SHADER_VARIABLE_DESC varDesc;
variable->GetDesc(&varDesc);
ctx.variables.push_back(ShaderBufferVariable(varDesc.Name, varDesc.StartOffset, varDesc.Size));
}
//find buffer's bind point
auto res = Where(params.resources, [ctx](ShaderResourceVariable srv) {return srv.name == ctx.name && srv.type == D3D_SIT_CBUFFER; })->ToVector();
ctx.bindPoint = res[0].bindPoint;
ctx.type = res[0].type;
ctx.size = cbDesc.ByteWidth;
params.buffers.push_back(ctx);
}
}
void Material::RebuildBuffers() {
ComPtr<ID3D12ShaderReflection> reflection;
for(int i = 0; i < (int)ShaderType::Count; ++i) {
auto& vs = shader->GetShader((ShaderType)i);
if(vs != nullptr) {
reflection = nullptr;
D3DReflect(vs->blob->GetBufferPointer(), vs->blob->GetBufferSize(), __uuidof(reflection), (void**)&reflection);
RebuildShaderParameters(shaderParameters[i], reflection);
}
}
}
void Material::SetParametersBlock(ShaderParametersBlock& block) {
parameters = block;
}