void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist) { // Exit early if there is no rtt changes if (!m_rtts_dirty) return; m_rtts_dirty = false; std::array<float, 4> clear_color = { rsx::method_registers.clear_color_r() / 255.f, rsx::method_registers.clear_color_g() / 255.f, rsx::method_registers.clear_color_b() / 255.f, rsx::method_registers.clear_color_a() / 255.f, }; m_rtts.prepare_render_target(copycmdlist, rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(), rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height(), rsx::method_registers.surface_color_target(), get_color_surface_addresses(), get_zeta_surface_address(), m_device.Get(), clear_color, 1.f, 0); // write descriptors DXGI_FORMAT dxgi_format = get_color_surface_format(rsx::method_registers.surface_color()); 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 * m_descriptor_stride_rtv); size_t rtt_index = 0; for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target())) { if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr) continue; 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 * m_descriptor_stride_rtv)); rtt_index++; } get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index; 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 * m_descriptor_stride_dsv); 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(rsx::method_registers.surface_depth_fmt()); depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle); }
void GLGSRender::init_buffers(bool skip_reading) { if (draw_fbo && !m_rtts_dirty) { set_viewport(); return; } //We are about to change buffers, flush any pending requests for the old buffers synchronize_buffers(); m_rtts_dirty = false; const u16 clip_horizontal = rsx::method_registers.surface_clip_width(); const u16 clip_vertical = rsx::method_registers.surface_clip_height(); const auto pitchs = get_pitchs(); const auto surface_format = rsx::method_registers.surface_color(); const auto depth_format = rsx::method_registers.surface_depth_fmt(); const auto surface_addresses = get_color_surface_addresses(); const auto depth_address = get_zeta_surface_address(); m_rtts.prepare_render_target(nullptr, surface_format, depth_format, clip_horizontal, clip_vertical, rsx::method_registers.surface_color_target(), surface_addresses, depth_address); draw_fbo.recreate(); for (int i = 0; i < rsx::limits::color_buffers_count; ++i) { if (std::get<0>(m_rtts.m_bound_render_targets[i])) { __glcheck draw_fbo.color[i] = *std::get<1>(m_rtts.m_bound_render_targets[i]); std::get<1>(m_rtts.m_bound_render_targets[i])->set_rsx_pitch(pitchs[i]); surface_info[i] = { surface_addresses[i], pitchs[i], false, surface_format, depth_format, clip_horizontal, clip_vertical }; //Verify pitch given is correct if pitch <= 64 (especially 64) if (pitchs[i] <= 64) { const u16 native_pitch = std::get<1>(m_rtts.m_bound_render_targets[i])->get_native_pitch(); if (native_pitch > pitchs[i]) { LOG_WARNING(RSX, "Bad color surface pitch given: surface_width=%d, format=%d, pitch=%d, native_pitch=%d", clip_horizontal, (u32)surface_format, pitchs[i], native_pitch); //Will not transfer this surface between cell and rsx due to misalignment //TODO: Verify correct behaviour surface_info[i].pitch = 0; } } } else surface_info[i] = {}; } if (std::get<0>(m_rtts.m_bound_depth_stencil)) { if (depth_format == rsx::surface_depth_format::z24s8) __glcheck draw_fbo.depth_stencil = *std::get<1>(m_rtts.m_bound_depth_stencil); else __glcheck draw_fbo.depth = *std::get<1>(m_rtts.m_bound_depth_stencil); const u32 depth_surface_pitch = rsx::method_registers.surface_z_pitch(); std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch()); depth_surface_info = { depth_address, depth_surface_pitch, true, surface_format, depth_format, clip_horizontal, clip_vertical }; //Verify pitch given is correct if pitch <= 64 (especially 64) if (depth_surface_pitch <= 64) { const u16 native_pitch = std::get<1>(m_rtts.m_bound_depth_stencil)->get_native_pitch(); if (native_pitch > depth_surface_pitch) { LOG_WARNING(RSX, "Bad depth surface pitch given: surface_width=%d, format=%d, pitch=%d, native_pitch=%d", clip_horizontal, (u32)depth_format, depth_surface_pitch, native_pitch); //Will not transfer this surface between cell and rsx due to misalignment //TODO: Verify correct behaviour depth_surface_info.pitch = 0; } } } else depth_surface_info = {}; if (!draw_fbo.check()) return; draw_fbo.bind(); set_viewport(); switch (rsx::method_registers.surface_color_target()) { case rsx::surface_target::none: break; case rsx::surface_target::surface_a: __glcheck draw_fbo.draw_buffer(draw_fbo.color[0]); __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surface_b: __glcheck draw_fbo.draw_buffer(draw_fbo.color[1]); __glcheck draw_fbo.read_buffer(draw_fbo.color[1]); break; case rsx::surface_target::surfaces_a_b: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1] }); __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surfaces_a_b_c: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2] }); __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surfaces_a_b_c_d: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2], draw_fbo.color[3] }); __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; } //Mark buffer regions as NO_ACCESS on Cell visible side if (g_cfg_rsx_write_color_buffers) { auto color_format = rsx::internals::surface_color_format_to_gl(surface_format); for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i) { if (!surface_info[i].address || !surface_info[i].pitch) continue; const u32 range = surface_info[i].pitch * surface_info[i].height; m_gl_texture_cache.lock_rtt_region(surface_info[i].address, range, surface_info[i].width, surface_info[i].height, surface_info[i].pitch, color_format.format, color_format.type, color_format.swap_bytes, *std::get<1>(m_rtts.m_bound_render_targets[i])); } } if (g_cfg_rsx_write_depth_buffer) { if (depth_surface_info.address && depth_surface_info.pitch) { auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(depth_format); u32 pitch = depth_surface_info.width * 2; if (depth_surface_info.depth_format != rsx::surface_depth_format::z16) pitch *= 2; const u32 range = pitch * depth_surface_info.height; //TODO: Verify that depth surface pitch variance affects results if (pitch != depth_surface_info.pitch) LOG_WARNING(RSX, "Depth surface pitch does not match computed pitch, %d vs %d", depth_surface_info.pitch, pitch); m_gl_texture_cache.lock_rtt_region(depth_surface_info.address, range, depth_surface_info.width, depth_surface_info.height, pitch, depth_format_gl.format, depth_format_gl.type, true, *std::get<1>(m_rtts.m_bound_depth_stencil)); } } }