mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
d3d12: Enable constant buffer support
This commit is contained in:
parent
6f487f910c
commit
65fbc57221
4 changed files with 196 additions and 31 deletions
|
@ -20,7 +20,9 @@ static void check(HRESULT hr)
|
|||
D3D12GSRender::D3D12GSRender()
|
||||
: GSRender(), m_fbo(nullptr), m_PSO(nullptr)
|
||||
{
|
||||
memset(vertexBufferSize, 0, sizeof(vertexBufferSize));
|
||||
memset(m_vertexBufferSize, 0, sizeof(m_vertexBufferSize));
|
||||
m_constantsBufferOffset = 0;
|
||||
m_constantsBufferIndex = 0;
|
||||
// Enable d3d debug layer
|
||||
Microsoft::WRL::ComPtr<ID3D12Debug> debugInterface;
|
||||
D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface));
|
||||
|
@ -95,6 +97,45 @@ D3D12GSRender::D3D12GSRender()
|
|||
IID_PPV_ARGS(&m_vertexBuffer[i])
|
||||
));
|
||||
}
|
||||
|
||||
check(m_device->CreateCommittedResource(
|
||||
&heapProp,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&m_constantsBuffer)
|
||||
));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
descriptorHeapDesc.NumDescriptors = 1000; // For safety
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
check(m_device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_constantsBufferDescriptorsHeap)));
|
||||
|
||||
// Common root signature
|
||||
D3D12_DESCRIPTOR_RANGE descriptorRange = {};
|
||||
descriptorRange.BaseShaderRegister = 0;
|
||||
descriptorRange.NumDescriptors = 1;
|
||||
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
D3D12_ROOT_PARAMETER RP = {};
|
||||
RP.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP.DescriptorTable.pDescriptorRanges = &descriptorRange;
|
||||
RP.DescriptorTable.NumDescriptorRanges = 1;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
rootSignatureDesc.NumParameters = 1;
|
||||
rootSignatureDesc.pParameters = &RP;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
|
||||
check(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, nullptr));
|
||||
|
||||
m_device->CreateRootSignature(0,
|
||||
rootSignatureBlob->GetBufferPointer(),
|
||||
rootSignatureBlob->GetBufferSize(),
|
||||
IID_PPV_ARGS(&m_rootSignature));
|
||||
}
|
||||
|
||||
D3D12GSRender::~D3D12GSRender()
|
||||
|
@ -238,7 +279,7 @@ void D3D12GSRender::EnableVertexData(bool indexed_draw)
|
|||
memcpy((char*)bufferMap + data_offset * item_size, &m_vertex_data[i].data[data_offset * item_size], data_size);
|
||||
m_vertexBuffer[i]->Unmap(0, nullptr);
|
||||
size_t newOffset = (data_offset + data_size) * item_size;
|
||||
vertexBufferSize[i] = newOffset > vertexBufferSize[i] ? newOffset : vertexBufferSize[i];
|
||||
m_vertexBufferSize[i] = newOffset > m_vertexBufferSize[i] ? newOffset : m_vertexBufferSize[i];
|
||||
}
|
||||
|
||||
if (indexed_draw)
|
||||
|
@ -270,6 +311,86 @@ void D3D12GSRender::EnableVertexData(bool indexed_draw)
|
|||
}
|
||||
}
|
||||
|
||||
void D3D12GSRender::FillVertexShaderConstantsBuffer()
|
||||
{
|
||||
float scaleOffsetMat[16] =
|
||||
{
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
size_t currentoffset = 0;
|
||||
void *constantsBufferMap;
|
||||
// TODO: Use finer range
|
||||
D3D12_RANGE range = {
|
||||
m_constantsBufferOffset,
|
||||
1024 * 1024 - m_constantsBufferOffset
|
||||
};
|
||||
check(m_constantsBuffer->Map(0, &range, &constantsBufferMap));
|
||||
|
||||
// Scale
|
||||
scaleOffsetMat[0] = (float&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 0)] / (RSXThread::m_width / RSXThread::m_width_scale);
|
||||
scaleOffsetMat[5] = (float&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 1)] / (RSXThread::m_height / RSXThread::m_height_scale);
|
||||
scaleOffsetMat[10] = (float&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 2)];
|
||||
|
||||
// Offset
|
||||
scaleOffsetMat[3] = (float&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 0)] - (RSXThread::m_width / RSXThread::m_width_scale);
|
||||
scaleOffsetMat[7] = (float&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 1)] - (RSXThread::m_height / RSXThread::m_height_scale);
|
||||
scaleOffsetMat[11] = (float&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 2)] - 1 / 2.0f;
|
||||
|
||||
scaleOffsetMat[3] /= RSXThread::m_width / RSXThread::m_width_scale;
|
||||
scaleOffsetMat[7] /= RSXThread::m_height / RSXThread::m_height_scale;
|
||||
|
||||
memcpy((char*)constantsBufferMap + m_constantsBufferOffset + currentoffset, scaleOffsetMat, 16 * sizeof(float));
|
||||
currentoffset += 16 * sizeof(float);
|
||||
|
||||
for (const RSXTransformConstant& c : m_transform_constants)
|
||||
{
|
||||
float vector[] = { c.x, c.y, c.z, c.w };
|
||||
memcpy((char*)constantsBufferMap + m_constantsBufferOffset + currentoffset, vector, 4 * sizeof(float));
|
||||
currentoffset += 4 * sizeof(float);
|
||||
}
|
||||
m_constantsBuffer->Unmap(0, &range);
|
||||
// Align to 256 byte
|
||||
currentoffset = (currentoffset + 255) & ~255;
|
||||
|
||||
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {};
|
||||
constantBufferViewDesc.BufferLocation = m_constantsBuffer->GetGPUVirtualAddress() + m_constantsBufferOffset;
|
||||
constantBufferViewDesc.SizeInBytes = (UINT)currentoffset;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_constantsBufferDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
|
||||
m_constantsBufferOffset += currentoffset;
|
||||
}
|
||||
|
||||
void D3D12GSRender::FillPixelShaderConstantsBuffer()
|
||||
{
|
||||
/* if (!m_cur_fragment_prog)
|
||||
{
|
||||
LOG_ERROR(RSX, "InitFragmentData: m_cur_shader_prog == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const RSXTransformConstant& c : m_fragment_constants)
|
||||
{
|
||||
u32 id = c.id - m_cur_fragment_prog->offset;
|
||||
|
||||
//LOG_WARNING(RSX,"fc%u[0x%x - 0x%x] = (%f, %f, %f, %f)", id, c.id, m_cur_shader_prog->offset, c.x, c.y, c.z, c.w);
|
||||
|
||||
const std::string name = fmt::Format("fc%u", id);
|
||||
const int l = m_program.GetLocation(name);
|
||||
checkForGlError("glGetUniformLocation " + name);
|
||||
|
||||
glUniform4f(l, c.x, c.y, c.z, c.w);
|
||||
checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
|
||||
}
|
||||
|
||||
//if (m_fragment_constants.GetCount())*/
|
||||
// LOG_NOTICE(HLE, "");
|
||||
}
|
||||
|
||||
|
||||
bool D3D12GSRender::LoadProgram()
|
||||
{
|
||||
|
@ -287,7 +408,7 @@ bool D3D12GSRender::LoadProgram()
|
|||
return false;
|
||||
}
|
||||
|
||||
m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_cur_vertex_prog, m_cur_fragment_prog, m_IASet);
|
||||
m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_rootSignature, m_cur_vertex_prog, m_cur_fragment_prog, m_IASet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -297,6 +418,8 @@ void D3D12GSRender::ExecCMD()
|
|||
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
|
||||
m_inflightCommandList.push_back(commandList);
|
||||
|
||||
commandList->SetGraphicsRootSignature(m_rootSignature);
|
||||
|
||||
if (m_indexed_array.m_count)
|
||||
{
|
||||
// LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
|
||||
|
@ -313,15 +436,21 @@ void D3D12GSRender::ExecCMD()
|
|||
D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {};
|
||||
|
||||
vertexBufferView.BufferLocation = m_vertexBuffer[i]->GetGPUVirtualAddress();
|
||||
vertexBufferView.SizeInBytes = (UINT)vertexBufferSize[i];
|
||||
vertexBufferView.SizeInBytes = (UINT)m_vertexBufferSize[i];
|
||||
vertexBufferView.StrideInBytes = (UINT)item_size;
|
||||
vertexBufferViews.push_back(vertexBufferView);
|
||||
|
||||
assert((m_draw_array_first + m_draw_array_count) * item_size <= vertexBufferSize[i]);
|
||||
assert((m_draw_array_first + m_draw_array_count) * item_size <= m_vertexBufferSize[i]);
|
||||
}
|
||||
commandList->IASetVertexBuffers(0, (UINT)vertexBufferViews.size(), vertexBufferViews.data());
|
||||
// InitVertexData();
|
||||
// InitFragmentData();
|
||||
FillVertexShaderConstantsBuffer();
|
||||
commandList->SetDescriptorHeaps(1, &m_constantsBufferDescriptorsHeap);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE Handle = m_constantsBufferDescriptorsHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
commandList->SetGraphicsRootDescriptorTable(0, Handle);
|
||||
m_constantsBufferIndex++;
|
||||
|
||||
FillPixelShaderConstantsBuffer();
|
||||
}
|
||||
|
||||
if (!LoadProgram())
|
||||
|
@ -758,6 +887,8 @@ void D3D12GSRender::Flip()
|
|||
for (ID3D12GraphicsCommandList *gfxCommandList : m_inflightCommandList)
|
||||
gfxCommandList->Release();
|
||||
m_inflightCommandList.clear();
|
||||
memset(vertexBufferSize, 0, sizeof(vertexBufferSize));
|
||||
memset(m_vertexBufferSize, 0, sizeof(m_vertexBufferSize));
|
||||
m_constantsBufferOffset = 0;
|
||||
m_constantsBufferIndex = 0;
|
||||
}
|
||||
#endif
|
|
@ -43,17 +43,21 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value);
|
|||
class D3D12GSRender : public GSRender
|
||||
{
|
||||
private:
|
||||
size_t vertexBufferSize[32];
|
||||
size_t m_vertexBufferSize[32];
|
||||
std::vector<u8> m_vdata;
|
||||
// std::vector<PostDrawObj> m_post_draw_objs;
|
||||
|
||||
PipelineStateObjectCache m_cachePSO;
|
||||
ID3D12PipelineState *m_PSO;
|
||||
ID3D12RootSignature *m_rootSignature;
|
||||
|
||||
// GLTexture m_gl_textures[m_textures_count];
|
||||
// GLTexture m_gl_vertex_textures[m_textures_count];
|
||||
|
||||
ID3D12Resource *m_indexBuffer, *m_vertexBuffer[m_vertex_count];
|
||||
ID3D12Resource *m_constantsBuffer;
|
||||
ID3D12DescriptorHeap *m_constantsBufferDescriptorsHeap;
|
||||
size_t m_constantsBufferOffset, m_constantsBufferIndex;
|
||||
std::vector<D3D12_INPUT_ELEMENT_DESC> m_IASet;
|
||||
D3D12RenderTargetSets *m_fbo;
|
||||
ID3D12Device* m_device;
|
||||
|
@ -80,9 +84,9 @@ private:
|
|||
|
||||
bool LoadProgram();
|
||||
void EnableVertexData(bool indexed_draw = false);
|
||||
void FillVertexShaderConstantsBuffer();
|
||||
void FillPixelShaderConstantsBuffer();
|
||||
/*void DisableVertexData();
|
||||
void InitVertexData();
|
||||
void InitFragmentData();
|
||||
|
||||
void WriteBuffers();
|
||||
void WriteDepthBuffer();
|
||||
|
|
|
@ -90,7 +90,7 @@ void PipelineStateObjectCache::Add(ID3D12PipelineState *prog, Shader& fp, Shader
|
|||
cachePSO.insert(std::make_pair(key, prog));
|
||||
}
|
||||
|
||||
ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet)
|
||||
ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Device *device, ID3D12RootSignature *rootSignature, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet)
|
||||
{
|
||||
ID3D12PipelineState *result = nullptr;
|
||||
Shader m_vertex_prog, m_fragment_prog;
|
||||
|
@ -163,10 +163,18 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev
|
|||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {};
|
||||
|
||||
graphicPipelineStateDesc.VS.BytecodeLength = m_vertex_prog.bytecode->GetBufferSize();
|
||||
graphicPipelineStateDesc.VS.pShaderBytecode = m_vertex_prog.bytecode->GetBufferPointer();
|
||||
graphicPipelineStateDesc.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize();
|
||||
graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer();
|
||||
if (m_vertex_prog.bytecode != nullptr)
|
||||
{
|
||||
graphicPipelineStateDesc.VS.BytecodeLength = m_vertex_prog.bytecode->GetBufferSize();
|
||||
graphicPipelineStateDesc.VS.pShaderBytecode = m_vertex_prog.bytecode->GetBufferPointer();
|
||||
}
|
||||
if (m_fragment_prog.bytecode != nullptr)
|
||||
{
|
||||
graphicPipelineStateDesc.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize();
|
||||
graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer();
|
||||
}
|
||||
|
||||
graphicPipelineStateDesc.pRootSignature = rootSignature;
|
||||
|
||||
// Sensible default value
|
||||
static D3D12_RASTERIZER_DESC CD3D12_RASTERIZER_DESC =
|
||||
|
@ -240,22 +248,44 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev
|
|||
return result;
|
||||
}
|
||||
|
||||
#define TO_STRING(x) #x
|
||||
|
||||
void Shader::Compile(SHADER_TYPE st)
|
||||
{
|
||||
static const char VSstring[] =
|
||||
"#define RS \"RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)\"\n"
|
||||
"[RootSignature(RS)]\n"
|
||||
"float4 main(float4 pos : TEXCOORD0) : SV_POSITION\n"
|
||||
"{\n"
|
||||
" return float4(pos.x, pos.y, 0., 1.);\n"
|
||||
"}";
|
||||
static const char FSstring[] =
|
||||
"#define RS \"RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)\"\n"
|
||||
"[RootSignature(RS)]\n"
|
||||
"float4 main() : SV_TARGET"
|
||||
"{"
|
||||
"return float4(1.0f, 1.0f, 1.0f, 1.0f);"
|
||||
"}";
|
||||
static const char VSstring[] = TO_STRING(
|
||||
cbuffer CONSTANT : register(b0)
|
||||
{
|
||||
float4x4 scaleOffsetMat;
|
||||
};
|
||||
|
||||
struct vertex {
|
||||
float4 pos : TEXCOORD0;
|
||||
float4 color : TEXCOORD3;
|
||||
};
|
||||
|
||||
struct pixel {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : TEXCOORD0;
|
||||
};
|
||||
|
||||
pixel main(vertex In)
|
||||
{
|
||||
pixel Out;
|
||||
Out.pos = mul(float4(In.pos.x, In.pos.y, 0., 1.), scaleOffsetMat);
|
||||
Out.color = In.color;
|
||||
return Out;
|
||||
});
|
||||
|
||||
static const char FSstring[] = TO_STRING(
|
||||
struct pixel {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : TEXCOORD0;
|
||||
};
|
||||
float4 main(pixel In) : SV_TARGET
|
||||
{
|
||||
return In.color;
|
||||
});
|
||||
|
||||
HRESULT hr;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
|
||||
switch (st)
|
||||
|
|
|
@ -161,7 +161,7 @@ public:
|
|||
PipelineStateObjectCache();
|
||||
~PipelineStateObjectCache();
|
||||
// Note: the last param is not taken into account if the PSO is not regenerated
|
||||
ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet);
|
||||
ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, ID3D12RootSignature *rootSignature, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue