mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
d3d12: factorize render_target code in a template class to be shared with others backends.
This commit is contained in:
parent
0c5cfdddba
commit
e6bd681227
5 changed files with 354 additions and 236 deletions
|
@ -89,11 +89,6 @@ D3D12DLLManagement::~D3D12DLLManagement()
|
|||
D3D12GSRender::D3D12GSRender()
|
||||
: GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso({})
|
||||
{
|
||||
m_previous_address_a = 0;
|
||||
m_previous_address_b = 0;
|
||||
m_previous_address_c = 0;
|
||||
m_previous_address_d = 0;
|
||||
m_previous_address_z = 0;
|
||||
gfxHandler = [this](u32 addr) {
|
||||
bool result = invalidate_address(addr);
|
||||
if (result)
|
||||
|
@ -423,15 +418,15 @@ void D3D12GSRender::flip(int buffer)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (m_rtts.bound_render_targets[0] != nullptr)
|
||||
if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
|
||||
{
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
resource_to_flip = m_rtts.bound_render_targets[0];
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[0]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0]);
|
||||
}
|
||||
else if (m_rtts.bound_render_targets[1] != nullptr)
|
||||
else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
|
||||
{
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[1], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
resource_to_flip = m_rtts.bound_render_targets[1];
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[1]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1]);
|
||||
}
|
||||
else
|
||||
resource_to_flip = nullptr;
|
||||
|
@ -533,6 +528,8 @@ void D3D12GSRender::flip(int buffer)
|
|||
storage.fence_value++;
|
||||
|
||||
storage.in_use = true;
|
||||
storage.dirty_textures.merge(m_rtts.invalidated_resources);
|
||||
m_rtts.invalidated_resources.clear();
|
||||
|
||||
// Get the put pos - 1. This way after cleaning we can set the get ptr to
|
||||
// this value, allowing heap to proceed even if we cleant before allocating
|
||||
|
|
|
@ -129,11 +129,11 @@ private:
|
|||
ID3D12Resource *m_dummy_texture;
|
||||
|
||||
// Store previous fbo addresses to detect RTT config changes.
|
||||
u32 m_previous_address_a;
|
||||
u32 m_previous_address_b;
|
||||
u32 m_previous_address_c;
|
||||
u32 m_previous_address_d;
|
||||
u32 m_previous_address_z;
|
||||
std::array<u32, 4> m_previous_color_address = {};
|
||||
u32 m_previous_address_z = 0;
|
||||
u32 m_previous_target = 0;
|
||||
u32 m_previous_clip_horizontal = 0;
|
||||
u32 m_previous_clip_vertical = 0;
|
||||
public:
|
||||
D3D12GSRender();
|
||||
virtual ~D3D12GSRender();
|
||||
|
|
|
@ -77,29 +77,25 @@ void D3D12GSRender::clear_surface(u32 arg)
|
|||
|
||||
if (arg & 0x1 || arg & 0x2)
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * g_descriptor_stride_rtv);
|
||||
m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, handle);
|
||||
get_current_resource_storage().depth_stencil_descriptor_heap_index++;
|
||||
|
||||
if (arg & 0x1)
|
||||
{
|
||||
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
|
||||
u32 max_depth_value = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 0x0000ffff : 0x00ffffff;
|
||||
get_current_resource_storage().command_list->ClearDepthStencilView(handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
|
||||
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
|
||||
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
|
||||
}
|
||||
|
||||
if (arg & 0x2)
|
||||
get_current_resource_storage().command_list->ClearDepthStencilView(handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]),
|
||||
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]),
|
||||
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
|
||||
}
|
||||
|
||||
if (arg & 0xF0)
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * g_descriptor_stride_rtv);
|
||||
size_t rtt_index = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, handle);
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle);
|
||||
size_t rtt_index = get_num_rtt(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]);
|
||||
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
|
||||
for (unsigned i = 0; i < rtt_index; i++)
|
||||
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, g_descriptor_stride_rtv), get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(),
|
||||
|
@ -120,16 +116,8 @@ void D3D12GSRender::clear_surface(u32 arg)
|
|||
|
||||
void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist)
|
||||
{
|
||||
// check if something has changed
|
||||
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
|
||||
|
||||
u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
|
||||
u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
|
||||
|
||||
u32 clip_width = clip_horizontal >> 16;
|
||||
u32 clip_height = clip_vertical >> 16;
|
||||
u32 clip_x = clip_horizontal;
|
||||
u32 clip_y = clip_vertical;
|
||||
|
||||
u32 context_dma_color[] =
|
||||
{
|
||||
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A],
|
||||
|
@ -149,7 +137,7 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
|
|||
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
|
||||
|
||||
// FBO location has changed, previous data might be copied
|
||||
u32 address_color[] =
|
||||
std::array<u32, 4> address_color =
|
||||
{
|
||||
rsx::get_address(offset_color[0], context_dma_color[0]),
|
||||
rsx::get_address(offset_color[1], context_dma_color[1]),
|
||||
|
@ -158,202 +146,71 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
|
|||
};
|
||||
u32 address_z = rsx::get_address(offset_zeta, m_context_dma_z);
|
||||
|
||||
u32 clip_h_reg = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
|
||||
u32 clip_v_reg = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
|
||||
u32 target_reg = rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET];
|
||||
|
||||
// Exit early if there is no rtt changes
|
||||
if (m_previous_address_a == address_color[0] &&
|
||||
m_previous_address_b == address_color[1] &&
|
||||
m_previous_address_c == address_color[2] &&
|
||||
m_previous_address_d == address_color[3] &&
|
||||
if (m_previous_color_address == address_color &&
|
||||
m_previous_address_z == address_z &&
|
||||
m_surface.format == surface_format)
|
||||
m_surface.format == surface_format &&
|
||||
m_previous_clip_horizontal == clip_h_reg &&
|
||||
m_previous_clip_vertical == clip_v_reg &&
|
||||
m_previous_target == target_reg)
|
||||
return;
|
||||
|
||||
m_previous_address_a = address_color[0];
|
||||
m_previous_address_b = address_color[1];
|
||||
m_previous_address_c = address_color[2];
|
||||
m_previous_address_d = address_color[3];
|
||||
m_previous_color_address = address_color;
|
||||
m_previous_address_z = address_z;
|
||||
m_previous_target = target_reg;
|
||||
m_previous_clip_horizontal = clip_h_reg;
|
||||
m_previous_clip_vertical = clip_v_reg;
|
||||
|
||||
if (m_surface.format != surface_format)
|
||||
{
|
||||
m_surface.unpack(surface_format);
|
||||
m_surface.width = clip_width;
|
||||
m_surface.height = clip_height;
|
||||
}
|
||||
|
||||
// Make previous RTTs sampleable
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_rtts.bound_render_targets[i] == nullptr)
|
||||
continue;
|
||||
copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[i], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
}
|
||||
// Reset bound data
|
||||
memset(m_rtts.bound_render_targets_address, 0, 4 * sizeof(u32));
|
||||
memset(m_rtts.bound_render_targets, 0, 4 * sizeof(ID3D12Resource *));
|
||||
|
||||
|
||||
// Create/Reuse requested rtts
|
||||
std::array<float, 4> clear_color = get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]);
|
||||
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
|
||||
{
|
||||
ComPtr<ID3D12Resource> old_render_target_resource;
|
||||
m_rtts.bound_render_targets[i] = m_rtts.bind_address_as_render_targets(m_device.Get(), copycmdlist, address_color[i], clip_width, clip_height, m_surface.color_format,
|
||||
clear_color, old_render_target_resource);
|
||||
if (old_render_target_resource)
|
||||
get_current_resource_storage().dirty_textures.push_back(old_render_target_resource);
|
||||
m_rtts.bound_render_targets_address[i] = address_color[i];
|
||||
}
|
||||
m_rtts.prepare_render_target(copycmdlist, surface_format, clip_h_reg, clip_v_reg, target_reg, address_color, address_z, m_device.Get(), clear_color, 1.f, 0);
|
||||
|
||||
// Same for depth buffer
|
||||
if (m_rtts.bound_depth_stencil != nullptr)
|
||||
copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
m_rtts.bound_depth_stencil = nullptr;
|
||||
m_rtts.bound_depth_stencil_address = 0;
|
||||
if (!address_z)
|
||||
return;
|
||||
ComPtr<ID3D12Resource> old_depth_stencil_resource;
|
||||
ID3D12Resource *ds = m_rtts.bind_address_as_depth_stencil(m_device.Get(), copycmdlist, address_z, clip_width, clip_height, m_surface.depth_format, 1., 0, old_depth_stencil_resource);
|
||||
if (old_depth_stencil_resource)
|
||||
get_current_resource_storage().dirty_textures.push_back(old_depth_stencil_resource);
|
||||
m_rtts.bound_depth_stencil_address = address_z;
|
||||
m_rtts.bound_depth_stencil = ds;
|
||||
}
|
||||
|
||||
size_t render_targets::bind_render_targets(ID3D12Device *device, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE handle)
|
||||
{
|
||||
DXGI_FORMAT dxgi_format = get_color_surface_format(color_format);
|
||||
// write descriptors
|
||||
DXGI_FORMAT dxgi_format = get_color_surface_format(m_surface.color_format);
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {};
|
||||
rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
rtt_view_desc.Format = dxgi_format;
|
||||
|
||||
m_rtts.current_rtts_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * g_descriptor_stride_rtv);
|
||||
size_t rtt_index = 0;
|
||||
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
|
||||
{
|
||||
if (bound_render_targets[i] == nullptr)
|
||||
if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
|
||||
continue;
|
||||
device->CreateRenderTargetView(bound_render_targets[i], &rtt_view_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(handle).Offset((INT)rtt_index * g_descriptor_stride_rtv));
|
||||
m_device->CreateRenderTargetView(std::get<1>(m_rtts.m_bound_render_targets[i]), &rtt_view_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle).Offset((INT)rtt_index * g_descriptor_stride_rtv));
|
||||
rtt_index++;
|
||||
}
|
||||
return rtt_index;
|
||||
}
|
||||
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
|
||||
|
||||
size_t render_targets::bind_depth_stencil(ID3D12Device *device, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE handle)
|
||||
{
|
||||
if (!bound_depth_stencil)
|
||||
return 0;
|
||||
if (std::get<1>(m_rtts.m_bound_depth_stencil) == nullptr)
|
||||
return;
|
||||
m_rtts.current_ds_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * g_descriptor_stride_rtv);
|
||||
get_current_resource_storage().depth_stencil_descriptor_heap_index += 1;
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {};
|
||||
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(depth_format);
|
||||
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(m_surface.depth_format);
|
||||
depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
device->CreateDepthStencilView(bound_depth_stencil, &depth_stencil_view_desc, handle);
|
||||
return 1;
|
||||
m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle);
|
||||
}
|
||||
|
||||
void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list)
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * g_descriptor_stride_rtv);
|
||||
size_t num_rtt = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, handle);
|
||||
get_current_resource_storage().render_targets_descriptors_heap_index += num_rtt;
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE depth_stencil_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * g_descriptor_stride_rtv);
|
||||
size_t num_ds = m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, depth_stencil_handle);
|
||||
get_current_resource_storage().depth_stencil_descriptor_heap_index += num_ds;
|
||||
command_list->OMSetRenderTargets((UINT)num_rtt, num_rtt > 0 ? &handle : nullptr, !!num_rtt,
|
||||
num_ds > 0 ? &depth_stencil_handle : nullptr);
|
||||
UINT num_rtt = get_num_rtt(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* rtt_handle = (num_rtt > 0) ? &m_rtts.current_rtts_handle : nullptr;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* ds_handle = (std::get<1>(m_rtts.m_bound_depth_stencil) != nullptr) ? &m_rtts.current_ds_handle : nullptr;
|
||||
command_list->OMSetRenderTargets((UINT)num_rtt, rtt_handle, true, ds_handle);
|
||||
}
|
||||
|
||||
ID3D12Resource *render_targets::bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
|
||||
size_t width, size_t height, u8 surfaceColorFormat, const std::array<float, 4> &clear_color, ComPtr<ID3D12Resource> &dirtyRTT)
|
||||
void render_targets::init(ID3D12Device *device)
|
||||
{
|
||||
DXGI_FORMAT dxgi_format = get_color_surface_format(surfaceColorFormat);
|
||||
auto It = render_targets_storage.find(address);
|
||||
// TODO: Check if format and size match
|
||||
if (It != render_targets_storage.end())
|
||||
{
|
||||
ComPtr<ID3D12Resource> rtt;
|
||||
rtt = It->second.Get();
|
||||
if (rtt->GetDesc().Format == dxgi_format && rtt->GetDesc().Width == width && rtt->GetDesc().Height == height)
|
||||
{
|
||||
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||
return rtt.Get();
|
||||
}
|
||||
render_targets_storage.erase(address);
|
||||
dirtyRTT = rtt;
|
||||
}
|
||||
ComPtr<ID3D12Resource> rtt;
|
||||
LOG_WARNING(RSX, "Creating RTT");
|
||||
|
||||
D3D12_CLEAR_VALUE clear_color_value = {};
|
||||
clear_color_value.Format = dxgi_format;
|
||||
clear_color_value.Color[0] = clear_color[0];
|
||||
clear_color_value.Color[1] = clear_color[1];
|
||||
clear_color_value.Color[2] = clear_color[2];
|
||||
clear_color_value.Color[3] = clear_color[3];
|
||||
|
||||
device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
&clear_color_value,
|
||||
IID_PPV_ARGS(rtt.GetAddressOf())
|
||||
);
|
||||
render_targets_storage[address] = rtt;
|
||||
std::wstring name = L"rtt_@" + std::to_wstring(address);
|
||||
rtt->SetName(name.c_str());
|
||||
|
||||
return rtt.Get();
|
||||
}
|
||||
|
||||
ID3D12Resource * render_targets::bind_address_as_depth_stencil(ID3D12Device * device, ID3D12GraphicsCommandList * cmdList, u32 address, size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr<ID3D12Resource> &dirtyDS)
|
||||
{
|
||||
auto It = depth_stencil_storage.find(address);
|
||||
|
||||
// TODO: Check if surface depth format match
|
||||
|
||||
if (It != depth_stencil_storage.end())
|
||||
{
|
||||
ComPtr<ID3D12Resource> ds = It->second;
|
||||
if (ds->GetDesc().Width == width && ds->GetDesc().Height == height)
|
||||
{
|
||||
// set the resource as depth write
|
||||
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
return ds.Get();
|
||||
}
|
||||
// If size doesn't match, remove ds from cache
|
||||
depth_stencil_storage.erase(address);
|
||||
dirtyDS = ds;
|
||||
}
|
||||
|
||||
D3D12_CLEAR_VALUE clear_depth_value = {};
|
||||
clear_depth_value.DepthStencil.Depth = depthClear;
|
||||
|
||||
DXGI_FORMAT dxgi_format = get_depth_stencil_typeless_surface_format(surfaceDepthFormat);
|
||||
clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat);
|
||||
|
||||
ComPtr<ID3D12Resource> new_depth_stencil;
|
||||
device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
|
||||
D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||
&clear_depth_value,
|
||||
IID_PPV_ARGS(new_depth_stencil.GetAddressOf())
|
||||
);
|
||||
depth_stencil_storage[address] = new_depth_stencil;
|
||||
std::wstring name = L"ds_@" + std::to_wstring(address);
|
||||
new_depth_stencil->SetName(name.c_str());
|
||||
|
||||
return new_depth_stencil.Get();
|
||||
}
|
||||
|
||||
void render_targets::init(ID3D12Device *device)//, u8 surfaceDepthFormat, size_t width, size_t height, float clearColor[4], float clearDepth)
|
||||
{
|
||||
memset(bound_render_targets_address, 0, 4 * sizeof(u32));
|
||||
memset(bound_render_targets, 0, 4 * sizeof(ID3D12Resource*));
|
||||
bound_depth_stencil = nullptr;
|
||||
bound_depth_stencil_address = 0;
|
||||
g_descriptor_stride_rtv = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
}
|
||||
|
||||
|
@ -492,7 +349,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shader_resource_view_desc.Texture2D.MipLevels = 1;
|
||||
shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
m_device->CreateShaderResourceView(m_rtts.bound_depth_stencil, &shader_resource_view_desc,
|
||||
m_device->CreateShaderResourceView(std::get<1>(m_rtts.m_bound_depth_stencil), &shader_resource_view_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()));
|
||||
D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {};
|
||||
uav_desc.Format = DXGI_FORMAT_R8_UNORM;
|
||||
|
@ -501,7 +358,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(1, g_descriptor_stride_srv_cbv_uav));
|
||||
|
||||
// Convert
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
|
||||
get_current_resource_storage().command_list->SetPipelineState(m_convertPSO);
|
||||
get_current_resource_storage().command_list->SetComputeRootSignature(m_convertRootSignature);
|
||||
|
@ -511,7 +368,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
|
||||
D3D12_RESOURCE_BARRIER barriers[] =
|
||||
{
|
||||
CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE),
|
||||
CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE),
|
||||
CD3DX12_RESOURCE_BARRIER::UAV(depth_format_conversion_buffer.Get()),
|
||||
};
|
||||
get_current_resource_storage().command_list->ResourceBarrier(2, barriers);
|
||||
|
@ -531,7 +388,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
{
|
||||
if (!address_color[i])
|
||||
continue;
|
||||
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[i], m_surface.color_format);
|
||||
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), m_surface.color_format);
|
||||
invalidate_address(address_color[i]);
|
||||
need_transfer = true;
|
||||
}
|
||||
|
@ -605,7 +462,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
|
||||
void D3D12GSRender::copy_render_targets_to_memory(void *buffer, u8 rtt)
|
||||
{
|
||||
size_t heap_offset = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[rtt], m_surface.color_format);
|
||||
size_t heap_offset = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[rtt]), m_surface.color_format);
|
||||
|
||||
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
|
||||
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
|
||||
|
@ -645,11 +502,11 @@ void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer)
|
|||
size_t buffer_size = row_pitch * clip_h;
|
||||
size_t heap_offset = m_readback_resources.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
|
||||
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
|
||||
|
||||
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { heap_offset,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 0), nullptr);
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(std::get<1>(m_rtts.m_bound_depth_stencil), 0), nullptr);
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
|
||||
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
|
||||
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
|
||||
|
@ -680,11 +537,11 @@ void D3D12GSRender::copy_stencil_buffer_to_memory(void *buffer)
|
|||
size_t buffer_size = row_pitch * clip_h;
|
||||
size_t heap_offset = m_readback_resources.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
|
||||
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
|
||||
|
||||
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { heap_offset, { DXGI_FORMAT_R8_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 1), nullptr);
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
&CD3DX12_TEXTURE_COPY_LOCATION(std::get<1>(m_rtts.m_bound_depth_stencil), 1), nullptr);
|
||||
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
|
||||
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
|
||||
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
|
||||
|
|
|
@ -1,30 +1,297 @@
|
|||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <d3d12.h>
|
||||
#include "d3dx12.h"
|
||||
|
||||
struct render_targets
|
||||
#include "D3D12Formats.h"
|
||||
#include <gsl.h>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::vector<u8> get_rtt_indexes(u8 color_target)
|
||||
{
|
||||
switch (color_target)
|
||||
{
|
||||
case CELL_GCM_SURFACE_TARGET_NONE: return{};
|
||||
case CELL_GCM_SURFACE_TARGET_0: return{ 0 };
|
||||
case CELL_GCM_SURFACE_TARGET_1: return{ 1 };
|
||||
case CELL_GCM_SURFACE_TARGET_MRT1: return{ 0, 1 };
|
||||
case CELL_GCM_SURFACE_TARGET_MRT2: return{ 0, 1, 2 };
|
||||
case CELL_GCM_SURFACE_TARGET_MRT3: return{ 0, 1, 2, 3 };
|
||||
}
|
||||
throw EXCEPTION("Wrong color_target (%d)", color_target);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Traits>
|
||||
struct surface_store
|
||||
{
|
||||
private:
|
||||
using surface_storage_type = typename Traits::surface_storage_type;
|
||||
using surface_type = typename Traits::surface_type;
|
||||
using command_list_type = typename Traits::command_list_type;
|
||||
|
||||
std::unordered_map<u32, surface_storage_type> m_render_targets_storage = {};
|
||||
std::unordered_map<u32, surface_storage_type> m_depth_stencil_storage = {};
|
||||
|
||||
public:
|
||||
std::array<std::tuple<u32, surface_type>, 4> m_bound_render_targets = {};
|
||||
std::tuple<u32, surface_type> m_bound_depth_stencil = {};
|
||||
|
||||
std::list<surface_storage_type> invalidated_resources;
|
||||
|
||||
surface_store() = default;
|
||||
~surface_store() = default;
|
||||
surface_store(const surface_store&) = delete;
|
||||
private:
|
||||
/**
|
||||
* If render target already exists at address, issue state change operation on cmdList.
|
||||
* Otherwise create one with width, height, clearColor info.
|
||||
* returns the corresponding render target resource.
|
||||
*/
|
||||
template <typename ...Args>
|
||||
gsl::not_null<surface_type> bind_address_as_render_targets(
|
||||
command_list_type command_list,
|
||||
u32 address,
|
||||
u8 surface_color_format, size_t width, size_t height,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
auto It = m_render_targets_storage.find(address);
|
||||
// TODO: Fix corner cases
|
||||
// This doesn't take overlapping surface(s) into account.
|
||||
// Invalidated surface(s) should also copy their content to the new resources.
|
||||
if (It != m_render_targets_storage.end())
|
||||
{
|
||||
surface_storage_type &rtt = It->second;
|
||||
if (Traits::rtt_has_format_width_height(rtt, surface_color_format, width, height))
|
||||
{
|
||||
Traits::prepare_rtt_for_drawing(command_list, rtt.Get());
|
||||
return rtt.Get();
|
||||
}
|
||||
invalidated_resources.push_back(std::move(rtt));
|
||||
m_render_targets_storage.erase(address);
|
||||
}
|
||||
|
||||
m_render_targets_storage[address] = Traits::create_new_render_target(address, surface_color_format, width, height, std::forward<Args>(extra_params)...);
|
||||
return m_render_targets_storage[address].Get();
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
gsl::not_null<surface_type> bind_address_as_depth_stencil(
|
||||
command_list_type command_list,
|
||||
u32 address,
|
||||
u8 surface_depth_format, size_t width, size_t height,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
auto It = m_depth_stencil_storage.find(address);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
{
|
||||
surface_storage_type &ds = It->second;
|
||||
if (Traits::ds_has_format_width_height(ds, surface_depth_format, width, height))
|
||||
{
|
||||
Traits::prepare_ds_for_drawing(command_list, ds.Get());
|
||||
return ds.Get();
|
||||
}
|
||||
invalidated_resources.push_back(std::move(ds));
|
||||
m_depth_stencil_storage.erase(address);
|
||||
}
|
||||
|
||||
m_depth_stencil_storage[address] = Traits::create_new_depth_stencil(address, surface_depth_format, width, height, std::forward<Args>(extra_params)...);
|
||||
return m_depth_stencil_storage[address].Get();
|
||||
}
|
||||
public:
|
||||
template <typename ...Args>
|
||||
void prepare_render_target(
|
||||
command_list_type command_list,
|
||||
u32 set_surface_format_reg,
|
||||
u32 clip_horizontal_reg, u32 clip_vertical_reg,
|
||||
u32 set_surface_target,
|
||||
const std::array<u32, 4> &surface_addresses, u32 address_z,
|
||||
Args&&... extra_params)
|
||||
{
|
||||
u32 clip_width = clip_horizontal_reg >> 16;
|
||||
u32 clip_height = clip_vertical_reg >> 16;
|
||||
u32 clip_x = clip_horizontal_reg;
|
||||
u32 clip_y = clip_vertical_reg;
|
||||
|
||||
rsx::surface_info surface = {};
|
||||
surface.unpack(set_surface_format_reg);
|
||||
|
||||
// Make previous RTTs sampleable
|
||||
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
|
||||
{
|
||||
if (std::get<1>(rtt) != nullptr)
|
||||
Traits::prepare_rtt_for_sampling(command_list, std::get<1>(rtt));
|
||||
rtt = std::make_tuple(0, nullptr);
|
||||
}
|
||||
|
||||
// Create/Reuse requested rtts
|
||||
for (u8 surface_index : get_rtt_indexes(set_surface_target))
|
||||
{
|
||||
if (surface_addresses[surface_index] == 0)
|
||||
continue;
|
||||
|
||||
m_bound_render_targets[surface_index] = std::make_tuple(surface_addresses[surface_index],
|
||||
bind_address_as_render_targets(command_list, surface_addresses[surface_index], surface.color_format, clip_width, clip_height, std::forward<Args>(extra_params)...));
|
||||
}
|
||||
|
||||
// Same for depth buffer
|
||||
if (std::get<1>(m_bound_depth_stencil) != nullptr)
|
||||
Traits::prepare_ds_for_sampling(command_list, std::get<1>(m_bound_depth_stencil));
|
||||
m_bound_depth_stencil = std::make_tuple(0, nullptr);
|
||||
if (!address_z)
|
||||
return;
|
||||
m_bound_depth_stencil = std::make_tuple(address_z,
|
||||
bind_address_as_depth_stencil(command_list, address_z, surface.depth_format, clip_width, clip_height, std::forward<Args>(extra_params)...));
|
||||
}
|
||||
|
||||
surface_type get_texture_from_render_target_if_applicable(u32 address)
|
||||
{
|
||||
// TODO: Handle texture that overlaps one (or several) surface.
|
||||
// Handle texture conversion
|
||||
// FIXME: Disgaea 3 loading screen seems to use a subset of a surface. It's not properly handled here.
|
||||
// Note: not const because conversions/resolve/... can happen
|
||||
auto It = m_render_targets_storage.find(address);
|
||||
if (It != m_render_targets_storage.end())
|
||||
return It->second.Get();
|
||||
return surface_type();
|
||||
}
|
||||
|
||||
surface_type get_texture_from_depth_stencil_if_applicable(u32 address)
|
||||
{
|
||||
// TODO: Same as above although there wasn't any game using corner case for DS yet.
|
||||
auto It = m_depth_stencil_storage.find(address);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
return It->second.Get();
|
||||
return surface_type();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct render_target_traits
|
||||
{
|
||||
using surface_storage_type = ComPtr<ID3D12Resource>;
|
||||
using surface_type = ID3D12Resource*;
|
||||
using command_list_type = gsl::not_null<ID3D12GraphicsCommandList*>;
|
||||
|
||||
static
|
||||
ComPtr<ID3D12Resource> create_new_render_target(
|
||||
u32 address,
|
||||
u8 surface_color_format, size_t width, size_t height,
|
||||
gsl::not_null<ID3D12Device*> device, const std::array<float, 4> &clear_color, float, u8)
|
||||
{
|
||||
DXGI_FORMAT dxgi_format = get_color_surface_format(surface_color_format);
|
||||
ComPtr<ID3D12Resource> rtt;
|
||||
LOG_WARNING(RSX, "Creating RTT");
|
||||
|
||||
D3D12_CLEAR_VALUE clear_color_value = {};
|
||||
clear_color_value.Format = dxgi_format;
|
||||
clear_color_value.Color[0] = clear_color[0];
|
||||
clear_color_value.Color[1] = clear_color[1];
|
||||
clear_color_value.Color[2] = clear_color[2];
|
||||
clear_color_value.Color[3] = clear_color[3];
|
||||
|
||||
device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
&clear_color_value,
|
||||
IID_PPV_ARGS(rtt.GetAddressOf())
|
||||
);
|
||||
|
||||
std::wstring name = L"rtt_@" + std::to_wstring(address);
|
||||
rtt->SetName(name.c_str());
|
||||
|
||||
return rtt;
|
||||
}
|
||||
|
||||
static
|
||||
void prepare_rtt_for_drawing(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
|
||||
ID3D12Resource* rtt)
|
||||
{
|
||||
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||
}
|
||||
|
||||
static
|
||||
void prepare_rtt_for_sampling(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
|
||||
ID3D12Resource* rtt)
|
||||
{
|
||||
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
}
|
||||
|
||||
static
|
||||
ComPtr<ID3D12Resource> create_new_depth_stencil(
|
||||
u32 address,
|
||||
u8 surfaceDepthFormat, size_t width, size_t height,
|
||||
gsl::not_null<ID3D12Device*> device, const std::array<float, 4>& , float clear_depth, u8 clear_stencil)
|
||||
{
|
||||
D3D12_CLEAR_VALUE clear_depth_value = {};
|
||||
clear_depth_value.DepthStencil.Depth = clear_depth;
|
||||
clear_depth_value.DepthStencil.Stencil = clear_stencil;
|
||||
|
||||
DXGI_FORMAT dxgi_format = get_depth_stencil_typeless_surface_format(surfaceDepthFormat);
|
||||
clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat);
|
||||
|
||||
ComPtr<ID3D12Resource> new_depth_stencil;
|
||||
device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
|
||||
D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||
&clear_depth_value,
|
||||
IID_PPV_ARGS(new_depth_stencil.GetAddressOf())
|
||||
);
|
||||
std::wstring name = L"ds_@" + std::to_wstring(address);
|
||||
new_depth_stencil->SetName(name.c_str());
|
||||
|
||||
return new_depth_stencil;
|
||||
}
|
||||
|
||||
static
|
||||
void prepare_ds_for_drawing(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
|
||||
ID3D12Resource* ds)
|
||||
{
|
||||
// set the resource as depth write
|
||||
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
||||
}
|
||||
|
||||
static
|
||||
void prepare_ds_for_sampling(
|
||||
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
|
||||
ID3D12Resource* ds)
|
||||
{
|
||||
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, u8 surface_color_format, size_t width, size_t height)
|
||||
{
|
||||
DXGI_FORMAT dxgi_format = get_color_surface_format(surface_color_format);
|
||||
return rtt->GetDesc().Format == dxgi_format && rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
|
||||
}
|
||||
|
||||
static
|
||||
bool ds_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, u8 surface_depth_stencil_format, size_t width, size_t height)
|
||||
{
|
||||
//TODO: Check format
|
||||
return rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
|
||||
}
|
||||
};
|
||||
|
||||
struct render_targets : public rsx::surface_store<render_target_traits>
|
||||
{
|
||||
INT g_descriptor_stride_rtv;
|
||||
std::unordered_map<u32, ComPtr<ID3D12Resource> > render_targets_storage;
|
||||
ID3D12Resource *bound_render_targets[4];
|
||||
u32 bound_render_targets_address[4];
|
||||
std::unordered_map<u32, ComPtr<ID3D12Resource> > depth_stencil_storage;
|
||||
ID3D12Resource *bound_depth_stencil;
|
||||
u32 bound_depth_stencil_address;
|
||||
|
||||
size_t bind_render_targets(ID3D12Device *, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE);
|
||||
size_t bind_depth_stencil(ID3D12Device *, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE);
|
||||
|
||||
/**
|
||||
* If render target already exists at address, issue state change operation on cmdList.
|
||||
* Otherwise create one with width, height, clearColor info.
|
||||
* returns the corresponding render target resource.
|
||||
*/
|
||||
ID3D12Resource *bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
|
||||
size_t width, size_t height, u8 surfaceColorFormat, const std::array<float, 4> &clearColor, ComPtr<ID3D12Resource> &dirtyDS);
|
||||
|
||||
ID3D12Resource *bind_address_as_depth_stencil(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
|
||||
size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr<ID3D12Resource> &dirtyDS);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE current_rtts_handle;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE current_ds_handle;
|
||||
|
||||
void init(ID3D12Device *device);
|
||||
};
|
||||
|
|
|
@ -167,18 +167,15 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
bool is_swizzled = !(textures[i].format() & CELL_GCM_TEXTURE_LN);
|
||||
|
||||
ID3D12Resource *vram_texture;
|
||||
std::unordered_map<u32, ComPtr<ID3D12Resource> >::const_iterator ItRTT = m_rtts.render_targets_storage.find(texaddr);
|
||||
std::unordered_map<u32, ComPtr<ID3D12Resource> >::const_iterator ItDS = m_rtts.depth_stencil_storage.find(texaddr);
|
||||
std::pair<texture_entry, ComPtr<ID3D12Resource> > *cached_texture = m_texture_cache.find_data_if_available(texaddr);
|
||||
bool is_render_target = false, is_depth_stencil_texture = false;
|
||||
if (ItRTT != m_rtts.render_targets_storage.end())
|
||||
|
||||
if (vram_texture = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
|
||||
{
|
||||
vram_texture = ItRTT->second.Get();
|
||||
is_render_target = true;
|
||||
}
|
||||
else if (ItDS != m_rtts.depth_stencil_storage.end())
|
||||
else if (vram_texture = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
|
||||
{
|
||||
vram_texture = ItDS->second.Get();
|
||||
is_depth_stencil_texture = true;
|
||||
}
|
||||
else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, textures[i].mipmap())))
|
||||
|
|
Loading…
Add table
Reference in a new issue