diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp new file mode 100644 index 0000000000..643a4d4081 --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -0,0 +1,4 @@ +#include "stdafx.h" +#if defined(DX12_SUPPORT) + +#endif \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.h b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.h new file mode 100644 index 0000000000..1a857ae62c --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.h @@ -0,0 +1,4 @@ +#pragma once +#if defined(DX12_SUPPORT) + +#endif \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index a1b6d44602..8c140c8b1c 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -194,6 +194,267 @@ void D3D12GSRender::ExecCMD(u32 cmd) m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**) &commandList); } +// Where are these type defined ??? +static +DXGI_FORMAT getFormat(u8 type, u8 size) +{ + /*static const u32 gl_types[] = + { + GL_SHORT, + GL_FLOAT, + GL_HALF_FLOAT, + GL_UNSIGNED_BYTE, + GL_SHORT, + GL_FLOAT, // Needs conversion + GL_UNSIGNED_BYTE, + }; + + static const bool gl_normalized[] = + { + GL_TRUE, + GL_FALSE, + GL_FALSE, + GL_TRUE, + GL_FALSE, + GL_TRUE, + GL_FALSE, + };*/ + static const DXGI_FORMAT typeX1[] = + { + DXGI_FORMAT_R16_SNORM, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R8_UINT + }; + static const DXGI_FORMAT typeX2[] = + { + DXGI_FORMAT_R16G16_SNORM, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R8G8_UINT + }; + static const DXGI_FORMAT typeX3[] = + { + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R8G8B8A8_UINT + }; + static const DXGI_FORMAT typeX4[] = + { + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R8G8B8A8_UINT + }; + + switch (size) + { + case 1: + return typeX1[type]; + case 2: + return typeX2[type]; + case 3: + return typeX3[type]; + case 4: + return typeX4[type]; + } +} + +void D3D12GSRender::EnableVertexData(bool indexed_draw) +{ + static u32 offset_list[m_vertex_count]; + u32 cur_offset = 0; + + const u32 data_offset = indexed_draw ? 0 : m_draw_array_first; + + for (u32 i = 0; i < m_vertex_count; ++i) + { + offset_list[i] = cur_offset; + + if (!m_vertex_data[i].IsEnabled()) continue; + const size_t item_size = m_vertex_data[i].GetTypeSize() * m_vertex_data[i].size; + const size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size; + const u32 pos = m_vdata.size(); + + cur_offset += data_size; + m_vdata.resize(m_vdata.size() + data_size); + memcpy(&m_vdata[pos], &m_vertex_data[i].data[data_offset * item_size], data_size); + } + +/* m_vao.Create(); + m_vao.Bind(); + checkForGlError("initializing vao"); + + m_vbo.Create(indexed_draw ? 2 : 1); + m_vbo.Bind(0); + m_vbo.SetData(m_vdata.data(), m_vdata.size());*/ + + if (indexed_draw) + { + // TODO: Use default heap and upload data + D3D12_HEAP_PROPERTIES heapProp = {}; + heapProp.Type = D3D12_HEAP_TYPE_UPLOAD; + + D3D12_RESOURCE_DESC resDesc = {}; + resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resDesc.Width = (UINT)m_indexed_array.m_data.size(); + resDesc.Height = 1; + resDesc.DepthOrArraySize = 1; + resDesc.SampleDesc.Count = 1; + check(m_device->CreateCommittedResource( + &heapProp, + D3D12_HEAP_FLAG_NONE, + &resDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&m_indexBuffer) + )); + void *indexBufferMap; + check(m_indexBuffer->Map(0, nullptr, (void**)indexBufferMap)); + memcpy(indexBufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size()); + m_indexBuffer->Unmap(0, nullptr); + + D3D12_INDEX_BUFFER_VIEW indexBufferView = {}; + indexBufferView.SizeInBytes = (UINT)m_indexed_array.m_data.size(); + indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); + } + +#if DUMP_VERTEX_DATA + rFile dump("VertexDataArray.dump", rFile::write); +#endif + + m_IASet.clear(); + + for (u32 i = 0; i < m_vertex_count; ++i) + { + if (!m_vertex_data[i].IsEnabled()) continue; + +#if DUMP_VERTEX_DATA + dump.Write(wxString::Format("VertexData[%d]:\n", i)); + switch (m_vertex_data[i].type) + { + case CELL_GCM_VERTEX_S1: + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) + { + dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + case CELL_GCM_VERTEX_F: + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 4) + { + dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); + if (!(((j + 4) / 4) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + case CELL_GCM_VERTEX_SF: + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) + { + dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + case CELL_GCM_VERTEX_UB: + for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j) + { + dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); + if (!((j + 1) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + case CELL_GCM_VERTEX_S32K: + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) + { + dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + // case CELL_GCM_VERTEX_CMP: + + case CELL_GCM_VERTEX_UB256: + for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j) + { + dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); + if (!((j + 1) % m_vertex_data[i].size)) dump.Write("\n"); + } + break; + + default: + LOG_ERROR(HLE, "Bad cv type! %d", m_vertex_data[i].type); + return; + } + + dump.Write("\n"); +#endif + + if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7) + { + LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", m_vertex_data[i].type); + } + + D3D12_INPUT_ELEMENT_DESC IAElement = {}; +/* if (!m_vertex_data[i].addr) + { + switch (m_vertex_data[i].type) + { + case CELL_GCM_VERTEX_S32K: + case CELL_GCM_VERTEX_S1: + switch (m_vertex_data[i].size) + { + case 1: glVertexAttrib1s(i, (GLshort&)m_vertex_data[i].data[0]); break; + case 2: glVertexAttrib2sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; + case 3: glVertexAttrib3sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; + case 4: glVertexAttrib4sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; + } + break; + + case CELL_GCM_VERTEX_F: + switch (m_vertex_data[i].size) + { + case 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break; + case 2: glVertexAttrib2fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; + case 3: glVertexAttrib3fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; + case 4: glVertexAttrib4fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; + } + break; + + case CELL_GCM_VERTEX_CMP: + case CELL_GCM_VERTEX_UB: + glVertexAttrib4ubv(i, (GLubyte*)&m_vertex_data[i].data[0]); + break; + } + + checkForGlError("glVertexAttrib"); + } + else*/ + { + IAElement.SemanticName = "TEXCOORD"; + IAElement.SemanticIndex = i; + IAElement.Format = getFormat(m_vertex_data[i].type - 1, m_vertex_data[i].size); + + IAElement.AlignedByteOffset = offset_list[i]; + } + m_IASet.push_back(IAElement); + } +} + bool D3D12GSRender::LoadProgram() { @@ -211,12 +472,25 @@ bool D3D12GSRender::LoadProgram() return false; } - m_PSO = cachePSO.getGraphicPipelineState(m_device, m_cur_vertex_prog, m_cur_fragment_prog); + m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_cur_vertex_prog, m_cur_fragment_prog, m_IASet); return true; } void D3D12GSRender::ExecCMD() { + if (m_indexed_array.m_count) + { + // LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); + } + + if (m_indexed_array.m_count || m_draw_array_count) + { + EnableVertexData(m_indexed_array.m_count ? true : false); + + // InitVertexData(); + // InitFragmentData(); + } + if (!LoadProgram()) { LOG_ERROR(RSX, "LoadProgram failed."); @@ -520,24 +794,9 @@ void D3D12GSRender::ExecCMD() m_program.SetVTex(i); m_gl_vertex_textures[i].Init(m_vertex_textures[i]); checkForGlError(fmt::Format("m_gl_vertex_textures[%d].Init", i)); - } + }*/ - m_vao.Bind(); - - if (m_indexed_array.m_count) - { - LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); - } - - if (m_indexed_array.m_count || m_draw_array_count) - { - EnableVertexData(m_indexed_array.m_count ? true : false); - - InitVertexData(); - InitFragmentData(); - } - - if (m_indexed_array.m_count) +/* if (m_indexed_array.m_count) { switch (m_indexed_array.m_type) { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index a1ee7947e8..50419a5e42 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -12,6 +12,7 @@ #include "D3D12RenderTargetSets.h" #include "D3D12PipelineState.h" +#include "D3D12Buffer.h" #pragma comment (lib, "d3d12.lib") #pragma comment (lib, "dxgi.lib") @@ -39,18 +40,14 @@ typedef GSFrameBase2*(*GetGSFrameCb2)(); void SetGetD3DGSFrameCallback(GetGSFrameCb2 value); -class D3D12GSRender //TODO: find out why this used to inherit from wxWindow - : //public wxWindow - /*,*/ public GSRender +class D3D12GSRender : public GSRender { private: - // std::vector m_vdata; + std::vector m_vdata; // std::vector m_post_draw_objs; - PipelineStateObjectCache cachePSO; + PipelineStateObjectCache m_cachePSO; ID3D12PipelineState *m_PSO; - int m_fp_buf_num; - int m_vp_buf_num; // GLProgramBuffer m_prog_buffer; // GLFragmentProgram m_fragment_prog; @@ -59,6 +56,8 @@ private: // GLTexture m_gl_textures[m_textures_count]; // GLTexture m_gl_vertex_textures[m_textures_count]; + ID3D12Resource *m_indexBuffer; + std::vector m_IASet; // GLvao m_vao; // GLvbo m_vbo; D3D12RenderTargetSets *m_fbo; @@ -73,9 +72,6 @@ private: ID3D12DescriptorHeap *m_backbufferAsRendertarget[2]; size_t m_lastWidth, m_lastHeight, m_lastDepth; - - void* m_context; - public: GSFrameBase2 *m_frame; u32 m_draw_frames; @@ -88,8 +84,8 @@ private: virtual void Close() override; bool LoadProgram(); - /* void EnableVertexData(bool indexed_draw = false); - void DisableVertexData(); + void EnableVertexData(bool indexed_draw = false); + /*void DisableVertexData(); void InitVertexData(); void InitFragmentData(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index e7010aee3a..c08b247907 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -57,7 +57,8 @@ bool PipelineStateObjectCache::SearchVp(const RSXVertexProgram& rsx_vp, Shader& ID3D12PipelineState *PipelineStateObjectCache::GetProg(u32 fp, u32 vp) const { - u64 key = vp << 32 | fp; + u64 vpLong = vp; + u64 key = vpLong << 32 | fp; std::unordered_map::const_iterator It = cachePSO.find(key); if (It == cachePSO.end()) return nullptr; @@ -69,7 +70,7 @@ void PipelineStateObjectCache::AddVertexProgram(Shader& vp, RSXVertexProgram& rs size_t actualVPSize = rsx_vp.data.size() * 4; void *fpShadowCopy = malloc(actualVPSize); memcpy(fpShadowCopy, rsx_vp.data.data(), actualVPSize); - vp.Id = currentShaderId++; + vp.Id = (u32)currentShaderId++; cacheVS.insert(std::make_pair(fpShadowCopy, vp)); } @@ -78,17 +79,18 @@ void PipelineStateObjectCache::AddFragmentProgram(Shader& fp, RSXFragmentProgram size_t actualFPSize = getFPBinarySize(vm::get_ptr(rsx_fp.addr)); void *fpShadowCopy = malloc(actualFPSize); memcpy(fpShadowCopy, vm::get_ptr(rsx_fp.addr), actualFPSize); - fp.Id = currentShaderId++; + fp.Id = (u32)currentShaderId++; cacheFS.insert(std::make_pair(fpShadowCopy, fp)); } void PipelineStateObjectCache::Add(ID3D12PipelineState *prog, Shader& fp, Shader& vp) { - u64 key = vp.Id << 32 | fp.Id; + u64 vpLong = vp.Id; + u64 key = vpLong << 32 | fp.Id; cachePSO.insert(std::make_pair(key, prog)); } -ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader) +ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector &IASet) { ID3D12PipelineState *result = nullptr; Shader m_vertex_prog, m_fragment_prog; @@ -199,9 +201,9 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev { FALSE,FALSE, D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, - D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - D3D12_COLOR_WRITE_ENABLE_ALL, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, } }; @@ -214,8 +216,8 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev graphicPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; graphicPipelineStateDesc.DSVFormat = DXGI_FORMAT_D16_UNORM; -// graphicPipelineStateDesc.InputLayout.pInputElementDescs = VTXLayout::getInputAssemblyLayout(); -// graphicPipelineStateDesc.InputLayout.NumElements = (UINT)VTXLayout::getInputAssemblySize(); + graphicPipelineStateDesc.InputLayout.pInputElementDescs = IASet.data(); + graphicPipelineStateDesc.InputLayout.NumElements = (UINT)IASet.size(); graphicPipelineStateDesc.SampleDesc.Count = 1; graphicPipelineStateDesc.SampleMask = UINT_MAX; graphicPipelineStateDesc.NodeMask = 1; @@ -235,6 +237,7 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev m_debug_programs.push_back(program); }*/ } + return result; } @@ -245,7 +248,7 @@ 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 : POSITION) : SV_POSITION\n" + "float4 main(float4 pos : TEXCOORD0) : SV_POSITION\n" "{\n" " return pos;\n" "}"; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index 2b8edf061a..bddf433027 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -160,7 +160,8 @@ private: public: PipelineStateObjectCache(); ~PipelineStateObjectCache(); - ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader); + // 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 &IASet); }; diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index ca6c9fc43b..07f2c03563 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -971,6 +971,9 @@ Emu\GPU\RSX\D3D12 + + Emu\GPU\RSX\D3D12 + @@ -1840,5 +1843,8 @@ Emu\GPU\RSX\D3D12 + + Emu\GPU\RSX\D3D12 + \ No newline at end of file