diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 43512c1003..0c77ddabda 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -434,7 +434,7 @@ void D3D12GSRender::end() std::chrono::time_point programLoadEnd = std::chrono::system_clock::now(); m_timers.m_programLoadDuration += std::chrono::duration_cast(programLoadEnd - programLoadStart).count(); - getCurrentResourceStorage().m_commandList->SetGraphicsRootSignature(m_rootSignatures[m_PSO->second].Get()); + getCurrentResourceStorage().m_commandList->SetGraphicsRootSignature(m_rootSignatures[std::get<2>(*m_PSO)].Get()); getCurrentResourceStorage().m_commandList->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]); std::chrono::time_point constantsDurationStart = std::chrono::system_clock::now(); @@ -448,15 +448,15 @@ void D3D12GSRender::end() std::chrono::time_point constantsDurationEnd = std::chrono::system_clock::now(); m_timers.m_constantsDuration += std::chrono::duration_cast(constantsDurationEnd - constantsDurationStart).count(); - getCurrentResourceStorage().m_commandList->SetPipelineState(m_PSO->first); + getCurrentResourceStorage().m_commandList->SetPipelineState(std::get<0>(*m_PSO)); std::chrono::time_point textureDurationStart = std::chrono::system_clock::now(); - if (m_PSO->second > 0) + if (std::get<2>(*m_PSO) > 0) { size_t usedTexture = UploadTextures(getCurrentResourceStorage().m_commandList.Get(), currentDescriptorIndex + 3); // Fill empty slots - for (; usedTexture < m_PSO->second; usedTexture++) + for (; usedTexture < std::get<2>(*m_PSO); usedTexture++) { D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index b6dad40eb7..7827534c08 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -309,7 +309,7 @@ private: RSXFragmentProgram fragment_program; PipelineStateObjectCache m_cachePSO; - std::pair *m_PSO; + std::tuple, size_t> *m_PSO; std::unordered_map local_transform_constants; struct diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index fee5c8fd6a..d05ad6149c 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -90,6 +90,7 @@ public: u32 id; ComPtr bytecode; + std::vector vertex_shader_inputs; std::vector FragmentConstantOffsetCache; size_t m_textureCount; @@ -103,11 +104,40 @@ public: void Compile(const std::string &code, enum class SHADER_TYPE st); }; +static +bool has_attribute(size_t attribute, const std::vector &desc) +{ + for (const auto &attribute_desc : desc) + { + if (attribute_desc.SemanticIndex == attribute) + return true; + } + return false; +} + +static +std::vector completes_IA_desc(const std::vector &desc, const std::vector &inputs) +{ + std::vector result(desc); + for (size_t attribute : inputs) + { + if (has_attribute(attribute, desc)) + continue; + D3D12_INPUT_ELEMENT_DESC extra_ia_desc = {}; + extra_ia_desc.SemanticIndex = (UINT)attribute; + extra_ia_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + extra_ia_desc.SemanticName = "TEXCOORD"; + extra_ia_desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; + result.push_back(extra_ia_desc); + } + return result; +} + struct D3D12Traits { typedef Shader VertexProgramData; typedef Shader FragmentProgramData; - typedef std::pair PipelineData; + typedef std::tuple, size_t> PipelineData; typedef D3D12PipelineProperties PipelineProperties; typedef std::pair *> ExtraData; @@ -144,7 +174,7 @@ struct D3D12Traits D3D12VertexProgramDecompiler VS(RSXVP->data); std::string shaderCode = VS.Decompile(); vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX); - + vertexProgramData.vertex_shader_inputs = VS.input_slots; // TODO: This shouldn't use current dir std::string filename = "./VertexProgram" + std::to_string(ID) + ".hlsl"; fs::file(filename, fom::write | fom::create | fom::trunc).write(shaderCode.c_str(), shaderCode.size()); @@ -155,7 +185,7 @@ struct D3D12Traits PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData) { - std::pair *result = new std::pair(); + std::tuple, size_t> *result = new std::tuple, size_t>(); D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {}; if (vertexProgramData.bytecode == nullptr) @@ -169,7 +199,7 @@ struct D3D12Traits graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer(); graphicPipelineStateDesc.pRootSignature = extraData.second[fragmentProgramData.m_textureCount].Get(); - result->second = fragmentProgramData.m_textureCount; + std::get<2>(*result) = fragmentProgramData.m_textureCount; graphicPipelineStateDesc.BlendState = pipelineProperties.Blend; graphicPipelineStateDesc.DepthStencilState = pipelineProperties.DepthStencil; @@ -181,20 +211,23 @@ struct D3D12Traits graphicPipelineStateDesc.RTVFormats[i] = pipelineProperties.RenderTargetsFormat; graphicPipelineStateDesc.DSVFormat = pipelineProperties.DepthStencilFormat; - graphicPipelineStateDesc.InputLayout.pInputElementDescs = pipelineProperties.IASet.data(); - graphicPipelineStateDesc.InputLayout.NumElements = (UINT)pipelineProperties.IASet.size(); + const std::vector &completed_IA_desc = completes_IA_desc(pipelineProperties.IASet, vertexProgramData.vertex_shader_inputs); + + graphicPipelineStateDesc.InputLayout.pInputElementDescs = completed_IA_desc.data(); + graphicPipelineStateDesc.InputLayout.NumElements = (UINT)completed_IA_desc.size(); graphicPipelineStateDesc.SampleDesc.Count = 1; graphicPipelineStateDesc.SampleMask = UINT_MAX; graphicPipelineStateDesc.NodeMask = 1; - extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result->first)); + extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&std::get<0>(*result))); + std::get<1>(*result) = vertexProgramData.vertex_shader_inputs; return result; } static void DeleteProgram(PipelineData *ptr) { - ptr->first->Release(); + std::get<0>(*ptr)->Release(); delete ptr; } }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp index 856a53de4c..0c2c986baa 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp @@ -43,9 +43,13 @@ void D3D12VertexProgramDecompiler::insertInputs(std::stringstream & OS, const st for (const ParamType PT : inputs) { for (const ParamItem &PI : PT.items) + { OS << " " << PT.type << " " << PI.name << ": TEXCOORD" << PI.location << ";" << std::endl; + input_slots.push_back(PI.location); + } } OS << "};" << std::endl; + } void D3D12VertexProgramDecompiler::insertConstants(std::stringstream & OS, const std::vector & constants) @@ -132,6 +136,8 @@ void D3D12VertexProgramDecompiler::insertMainStart(std::stringstream & OS) OS << " " << PT.type << " " << PI.name; if (!PI.value.empty()) OS << " = " << PI.value; + else + OS << " = " << "float4(0., 0., 0., 0.);"; OS << ";" << std::endl; } } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h index 45165fdf2c..bdc1655cd4 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h @@ -19,5 +19,6 @@ protected: virtual void insertMainStart(std::stringstream &OS); virtual void insertMainEnd(std::stringstream &OS); public: + std::vector input_slots; D3D12VertexProgramDecompiler(std::vector& data); };