mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-23 11:13:19 +01:00
d3d12: Consume less descriptor slot if not required
This commit is contained in:
parent
6d9e542cde
commit
25b10c5e3e
@ -75,11 +75,12 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
||||
check(device->CreateHeap(&heapDescription, IID_PPV_ARGS(&m_textureStorage)));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC textureDescriptorDesc = {};
|
||||
textureDescriptorDesc.NumDescriptors = 2048; // For safety
|
||||
textureDescriptorDesc.NumDescriptors = 10000; // For safety
|
||||
textureDescriptorDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
textureDescriptorDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
check(device->CreateDescriptorHeap(&textureDescriptorDesc, IID_PPV_ARGS(&m_textureDescriptorsHeap)));
|
||||
|
||||
textureDescriptorDesc.NumDescriptors = 2048; // For safety
|
||||
textureDescriptorDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
check(device->CreateDescriptorHeap(&textureDescriptorDesc, IID_PPV_ARGS(&m_samplerDescriptorHeap)));
|
||||
}
|
||||
@ -230,55 +231,58 @@ D3D12GSRender::D3D12GSRender()
|
||||
m_device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_backbufferAsRendertarget[1]));
|
||||
m_device->CreateRenderTargetView(m_backBuffer[1], &rttDesc, m_backbufferAsRendertarget[1]->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
// Common root signature
|
||||
D3D12_DESCRIPTOR_RANGE descriptorRange[4] = {};
|
||||
// Scale Offset data
|
||||
descriptorRange[0].BaseShaderRegister = 0;
|
||||
descriptorRange[0].NumDescriptors = 1;
|
||||
descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
// Constants
|
||||
descriptorRange[1].BaseShaderRegister = 1;
|
||||
descriptorRange[1].NumDescriptors = 2;
|
||||
descriptorRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
// Textures
|
||||
descriptorRange[2].BaseShaderRegister = 0;
|
||||
descriptorRange[2].NumDescriptors = 16;
|
||||
descriptorRange[2].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
// Samplers
|
||||
descriptorRange[3].BaseShaderRegister = 0;
|
||||
descriptorRange[3].NumDescriptors = 16;
|
||||
descriptorRange[3].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
D3D12_ROOT_PARAMETER RP[4] = {};
|
||||
RP[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[0].DescriptorTable.pDescriptorRanges = &descriptorRange[0];
|
||||
RP[0].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[1].DescriptorTable.pDescriptorRanges = &descriptorRange[1];
|
||||
RP[1].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[2].DescriptorTable.pDescriptorRanges = &descriptorRange[2];
|
||||
RP[2].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[3].DescriptorTable.pDescriptorRanges = &descriptorRange[3];
|
||||
RP[3].DescriptorTable.NumDescriptorRanges = 1;
|
||||
// Common root signatures
|
||||
for (unsigned textureCount = 0; textureCount < 17; textureCount++)
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE descriptorRange[4] = {};
|
||||
// Scale Offset data
|
||||
descriptorRange[0].BaseShaderRegister = 0;
|
||||
descriptorRange[0].NumDescriptors = 1;
|
||||
descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
// Constants
|
||||
descriptorRange[1].BaseShaderRegister = 1;
|
||||
descriptorRange[1].NumDescriptors = 2;
|
||||
descriptorRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
// Textures
|
||||
descriptorRange[2].BaseShaderRegister = 0;
|
||||
descriptorRange[2].NumDescriptors = textureCount;
|
||||
descriptorRange[2].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
// Samplers
|
||||
descriptorRange[3].BaseShaderRegister = 0;
|
||||
descriptorRange[3].NumDescriptors = textureCount;
|
||||
descriptorRange[3].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
D3D12_ROOT_PARAMETER RP[4] = {};
|
||||
RP[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[0].DescriptorTable.pDescriptorRanges = &descriptorRange[0];
|
||||
RP[0].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[1].DescriptorTable.pDescriptorRanges = &descriptorRange[1];
|
||||
RP[1].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[2].DescriptorTable.pDescriptorRanges = &descriptorRange[2];
|
||||
RP[2].DescriptorTable.NumDescriptorRanges = 1;
|
||||
RP[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
RP[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
RP[3].DescriptorTable.pDescriptorRanges = &descriptorRange[3];
|
||||
RP[3].DescriptorTable.NumDescriptorRanges = 1;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
rootSignatureDesc.NumParameters = 4;
|
||||
rootSignatureDesc.pParameters = RP;
|
||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
rootSignatureDesc.NumParameters = (textureCount > 0) ? 4 : 2;
|
||||
rootSignatureDesc.pParameters = RP;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
|
||||
check(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
|
||||
check(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
|
||||
|
||||
m_device->CreateRootSignature(0,
|
||||
rootSignatureBlob->GetBufferPointer(),
|
||||
rootSignatureBlob->GetBufferSize(),
|
||||
IID_PPV_ARGS(&m_rootSignature));
|
||||
m_device->CreateRootSignature(0,
|
||||
rootSignatureBlob->GetBufferPointer(),
|
||||
rootSignatureBlob->GetBufferSize(),
|
||||
IID_PPV_ARGS(&m_rootSignatures[textureCount]));
|
||||
}
|
||||
|
||||
m_perFrameStorage.Init(m_device);
|
||||
m_perFrameStorage.Reset();
|
||||
@ -348,7 +352,8 @@ D3D12GSRender::~D3D12GSRender()
|
||||
m_backbufferAsRendertarget[1]->Release();
|
||||
m_backBuffer[1]->Release();
|
||||
m_rtts.Release();
|
||||
m_rootSignature->Release();
|
||||
for (unsigned i = 0; i < 17; i++)
|
||||
m_rootSignatures[i]->Release();
|
||||
m_swapChain->Release();
|
||||
m_device->Release();
|
||||
delete[] vertexConstantShadowCopy;
|
||||
@ -625,7 +630,7 @@ bool D3D12GSRender::LoadProgram()
|
||||
|
||||
prop.IASet = m_IASet;
|
||||
|
||||
m_PSO = m_cachePSO.getGraphicPipelineState(m_cur_vertex_prog, m_cur_fragment_prog, prop, std::make_pair(m_device, m_rootSignature));
|
||||
m_PSO = m_cachePSO.getGraphicPipelineState(m_cur_vertex_prog, m_cur_fragment_prog, prop, std::make_pair(m_device, m_rootSignatures));
|
||||
return m_PSO != nullptr;
|
||||
}
|
||||
|
||||
@ -637,8 +642,6 @@ void D3D12GSRender::ExecCMD()
|
||||
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
|
||||
m_perFrameStorage.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);
|
||||
|
||||
@ -657,6 +660,8 @@ void D3D12GSRender::ExecCMD()
|
||||
return;
|
||||
}
|
||||
|
||||
commandList->SetGraphicsRootSignature(m_rootSignatures[m_PSO->second]);
|
||||
|
||||
// Constants
|
||||
setScaleOffset();
|
||||
commandList->SetDescriptorHeaps(1, &m_perFrameStorage.m_scaleOffsetDescriptorHeap);
|
||||
@ -675,43 +680,46 @@ void D3D12GSRender::ExecCMD()
|
||||
Handle = m_perFrameStorage.m_constantsBufferDescriptorsHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += currentBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
commandList->SetGraphicsRootDescriptorTable(1, Handle);
|
||||
commandList->SetPipelineState(m_PSO);
|
||||
commandList->SetPipelineState(m_PSO->first);
|
||||
|
||||
size_t usedTexture = UploadTextures();
|
||||
// Drivers don't like undefined texture descriptors
|
||||
for (; usedTexture < 16; usedTexture++)
|
||||
if (m_PSO->second > 0)
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.Texture2D.MipLevels = 1;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_perFrameStorage.m_textureDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
m_device->CreateShaderResourceView(m_dummyTexture, &srvDesc, Handle);
|
||||
size_t usedTexture = UploadTextures();
|
||||
// Drivers don't like undefined texture descriptors
|
||||
/* for (; usedTexture < 16; usedTexture++)
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.Texture2D.MipLevels = 1;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_perFrameStorage.m_textureDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
m_device->CreateShaderResourceView(m_dummyTexture, &srvDesc, Handle);
|
||||
|
||||
D3D12_SAMPLER_DESC samplerDesc = {};
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
Handle = m_perFrameStorage.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
m_device->CreateSampler(&samplerDesc, Handle);
|
||||
D3D12_SAMPLER_DESC samplerDesc = {};
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
Handle = m_perFrameStorage.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += (usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
m_device->CreateSampler(&samplerDesc, Handle);
|
||||
}*/
|
||||
|
||||
Handle = m_perFrameStorage.m_textureDescriptorsHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_perFrameStorage.m_currentTextureIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
commandList->SetDescriptorHeaps(1, &m_perFrameStorage.m_textureDescriptorsHeap);
|
||||
commandList->SetGraphicsRootDescriptorTable(2, Handle);
|
||||
|
||||
Handle = m_perFrameStorage.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_perFrameStorage.m_currentTextureIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
commandList->SetDescriptorHeaps(1, &m_perFrameStorage.m_samplerDescriptorHeap);
|
||||
commandList->SetGraphicsRootDescriptorTable(3, Handle);
|
||||
|
||||
m_perFrameStorage.m_currentTextureIndex += usedTexture;
|
||||
}
|
||||
|
||||
Handle = m_perFrameStorage.m_textureDescriptorsHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_perFrameStorage.m_currentTextureIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
commandList->SetDescriptorHeaps(1, &m_perFrameStorage.m_textureDescriptorsHeap);
|
||||
commandList->SetGraphicsRootDescriptorTable(2, Handle);
|
||||
|
||||
Handle = m_perFrameStorage.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
Handle.ptr += m_perFrameStorage.m_currentTextureIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
commandList->SetDescriptorHeaps(1, &m_perFrameStorage.m_samplerDescriptorHeap);
|
||||
commandList->SetGraphicsRootDescriptorTable(3, Handle);
|
||||
|
||||
m_perFrameStorage.m_currentTextureIndex += usedTexture;
|
||||
|
||||
size_t numRTT;
|
||||
switch (m_surface_color_target)
|
||||
{
|
||||
|
@ -54,8 +54,9 @@ private:
|
||||
// std::vector<PostDrawObj> m_post_draw_objs;
|
||||
|
||||
PipelineStateObjectCache m_cachePSO;
|
||||
ID3D12PipelineState *m_PSO;
|
||||
ID3D12RootSignature *m_rootSignature;
|
||||
std::pair<ID3D12PipelineState *, size_t> *m_PSO;
|
||||
// m_rootSignatures[N] is RS with N texture/sample
|
||||
ID3D12RootSignature *m_rootSignatures[17];
|
||||
|
||||
ID3D12PipelineState *m_convertPSO;
|
||||
ID3D12RootSignature *m_convertRootSignature;
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
u32 Id;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> bytecode;
|
||||
std::vector<size_t> FragmentConstantOffsetCache;
|
||||
size_t m_textureCount;
|
||||
|
||||
/**
|
||||
* Decompile a fragment shader located in the PS3's Memory. This function operates synchronously.
|
||||
@ -59,9 +60,9 @@ struct D3D12Traits
|
||||
{
|
||||
typedef Shader VertexProgramData;
|
||||
typedef Shader FragmentProgramData;
|
||||
typedef ID3D12PipelineState PipelineData;
|
||||
typedef std::pair<ID3D12PipelineState *, size_t> PipelineData;
|
||||
typedef D3D12PipelineProperties PipelineProperties;
|
||||
typedef std::pair<ID3D12Device *, ID3D12RootSignature *> ExtraData;
|
||||
typedef std::pair<ID3D12Device *, ID3D12RootSignature **> ExtraData;
|
||||
|
||||
static
|
||||
void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID)
|
||||
@ -69,12 +70,16 @@ struct D3D12Traits
|
||||
D3D12FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->offset);
|
||||
const std::string &shader = FS.Decompile();
|
||||
fragmentProgramData.Compile(shader, Shader::SHADER_TYPE::SHADER_TYPE_FRAGMENT);
|
||||
|
||||
fragmentProgramData.m_textureCount = 0;
|
||||
for (const ParamType& PT : FS.m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
if (PT.type == "sampler2D") continue;
|
||||
for (const ParamItem PI : PT.items)
|
||||
{
|
||||
if (PT.type == "sampler2D")
|
||||
{
|
||||
fragmentProgramData.m_textureCount++;
|
||||
continue;
|
||||
}
|
||||
size_t offset = atoi(PI.name.c_str() + 2);
|
||||
fragmentProgramData.FragmentConstantOffsetCache.push_back(offset);
|
||||
}
|
||||
@ -102,7 +107,8 @@ struct D3D12Traits
|
||||
static
|
||||
PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData)
|
||||
{
|
||||
ID3D12PipelineState *result;
|
||||
|
||||
std::pair<ID3D12PipelineState *, size_t> *result = new std::pair<ID3D12PipelineState *, size_t>();
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {};
|
||||
|
||||
if (vertexProgramData.bytecode == nullptr)
|
||||
@ -115,7 +121,8 @@ struct D3D12Traits
|
||||
graphicPipelineStateDesc.PS.BytecodeLength = fragmentProgramData.bytecode->GetBufferSize();
|
||||
graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer();
|
||||
|
||||
graphicPipelineStateDesc.pRootSignature = extraData.second;
|
||||
graphicPipelineStateDesc.pRootSignature = extraData.second[fragmentProgramData.m_textureCount];
|
||||
result->second = fragmentProgramData.m_textureCount;
|
||||
|
||||
// Sensible default value
|
||||
static D3D12_RASTERIZER_DESC CD3D12_RASTERIZER_DESC =
|
||||
@ -161,14 +168,15 @@ struct D3D12Traits
|
||||
graphicPipelineStateDesc.SampleMask = UINT_MAX;
|
||||
graphicPipelineStateDesc.NodeMask = 1;
|
||||
|
||||
extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result));
|
||||
extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result->first));
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
void DeleteProgram(PipelineData *ptr)
|
||||
{
|
||||
ptr->Release();
|
||||
ptr->first->Release();
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user