void DXStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, AbstractTexture* dst, const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer, u32 dst_level) { ASSERT(m_type == StagingTextureType::Upload); ASSERT(src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()); ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= GetWidth() && src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= GetHeight()); ASSERT(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= dst->GetWidth() && dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= dst->GetHeight()); if (IsMapped()) DXStagingTexture::Unmap(); if (static_cast<u32>(src_rect.GetWidth()) == dst->GetWidth() && static_cast<u32>(src_rect.GetHeight()) == dst->GetHeight()) { D3D::context->CopySubresourceRegion( static_cast<const DXTexture*>(dst)->GetD3DTexture(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()), 0, 0, 0, m_tex, 0, nullptr); } else { CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1); D3D::context->CopySubresourceRegion( static_cast<const DXTexture*>(dst)->GetD3DTexture(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()), static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex, 0, &src_box); } }
void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect) { // Can't do this within a game render pass. StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->SetPendingRebind(); // Can't render to a non-rendertarget (no framebuffer). _assert_msg_(VIDEO, dst_texture->config.rendertarget, "Destination texture for partial copy is not a rendertarget"); // Render pass expects dst_texture to be in SHADER_READ_ONLY state. src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); dst_texture->GetTexture()->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_render_pass, g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(), m_copy_shader); VkRect2D region = { { dst_rect.left, dst_rect.top }, { static_cast<u32>(dst_rect.GetWidth()), static_cast<u32>(dst_rect.GetHeight()) } }; draw.BeginRenderPass(dst_texture->GetFramebuffer(), region); draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler()); draw.DrawQuad(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight(), src_rect.left, src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(), static_cast<int>(src_texture->GetWidth()), static_cast<int>(src_texture->GetHeight())); draw.EndRenderPass(); }
void DXStagingTexture::CopyFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect) { ASSERT(m_type == StagingTextureType::Readback || m_type == StagingTextureType::Mutable); ASSERT(src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()); ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= src->GetWidth() && src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= src->GetHeight()); ASSERT(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= m_config.width && dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= m_config.height); if (IsMapped()) DXStagingTexture::Unmap(); if (static_cast<u32>(src_rect.GetWidth()) == GetWidth() && static_cast<u32>(src_rect.GetHeight()) == GetHeight()) { // Copy whole resource, needed for depth textures. D3D::context->CopySubresourceRegion( m_tex, 0, 0, 0, 0, static_cast<const DXTexture*>(src)->GetD3DTexture(), D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), nullptr); } else { CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1); D3D::context->CopySubresourceRegion( m_tex, 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, static_cast<const DXTexture*>(src)->GetD3DTexture(), D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), &src_box); } m_needs_flush = true; }
void TextureCache::CopyRectangleFromTexture(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect) { // Fast path when not scaling the image. if (src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()) CopyTextureRectangle(dst_texture, dst_rect, src_texture, src_rect); else ScaleTextureRectangle(dst_texture, dst_rect, src_texture, src_rect); }
void DXTexture::CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle<int>& srcrect, const MathUtil::Rectangle<int>& dstrect) { const DXTexture* srcentry = static_cast<const DXTexture*>(source); if (srcrect.GetWidth() == dstrect.GetWidth() && srcrect.GetHeight() == dstrect.GetHeight()) { D3D11_BOX srcbox; srcbox.left = srcrect.left; srcbox.top = srcrect.top; srcbox.right = srcrect.right; srcbox.bottom = srcrect.bottom; srcbox.front = 0; srcbox.back = srcentry->m_config.layers; D3D::context->CopySubresourceRegion(m_texture->GetTex(), 0, dstrect.left, dstrect.top, 0, srcentry->m_texture->GetTex(), 0, &srcbox); return; } else if (!m_config.rendertarget) { return; } g_renderer->ResetAPIState(); // reset any game specific settings const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(float(dstrect.left), float(dstrect.top), float(dstrect.GetWidth()), float(dstrect.GetHeight())); D3D::stateman->UnsetTexture(m_texture->GetSRV()); D3D::stateman->Apply(); D3D::context->OMSetRenderTargets(1, &m_texture->GetRTV(), nullptr); D3D::context->RSSetViewports(1, &vp); D3D::SetLinearCopySampler(); D3D11_RECT srcRC; srcRC.left = srcrect.left; srcRC.right = srcrect.right; srcRC.top = srcrect.top; srcRC.bottom = srcrect.bottom; D3D::drawShadedTexQuad(srcentry->m_texture->GetSRV(), &srcRC, srcentry->m_config.width, srcentry->m_config.height, PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader(), 1.0, 0); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); }
static MathUtil::Rectangle<T> maxRectangle(MathUtil::Rectangle<T> window_area, float screen_aspect_ratio) { float scale = std::min(static_cast<float>(window_area.GetWidth()), window_area.GetHeight() / screen_aspect_ratio); return MathUtil::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)), static_cast<T>(std::round(scale * screen_aspect_ratio))}; }
void DXTexture::ScaleRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle<int>& srcrect, const MathUtil::Rectangle<int>& dstrect) { const DXTexture* srcentry = static_cast<const DXTexture*>(source); _assert_(m_config.rendertarget); g_renderer->ResetAPIState(); // reset any game specific settings const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(float(dstrect.left), float(dstrect.top), float(dstrect.GetWidth()), float(dstrect.GetHeight())); D3D::stateman->UnsetTexture(m_texture->GetSRV()); D3D::stateman->Apply(); D3D::context->OMSetRenderTargets(1, &m_texture->GetRTV(), nullptr); D3D::context->RSSetViewports(1, &vp); D3D::SetLinearCopySampler(); D3D11_RECT srcRC; srcRC.left = srcrect.left; srcRC.right = srcrect.right; srcRC.top = srcrect.top; srcRC.bottom = srcrect.bottom; D3D::drawShadedTexQuad(srcentry->m_texture->GetSRV(), &srcRC, srcentry->m_config.width, srcentry->m_config.height, PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader(), 1.0, 0); FramebufferManager::BindEFBRenderTarget(); g_renderer->RestoreAPIState(); }
void VKTexture::ScaleRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { Texture2D* src_texture = static_cast<const VKTexture*>(source)->GetRawTexIdentifier(); // Can't do this within a game render pass. StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->SetPendingRebind(); // Can't render to a non-rendertarget (no framebuffer). _assert_msg_(VIDEO, m_config.rendertarget, "Destination texture for partial copy is not a rendertarget"); // Render pass expects dst_texture to be in COLOR_ATTACHMENT_OPTIMAL state. // src_texture should already be in SHADER_READ_ONLY state, but transition in case (XFB). src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VkRenderPass render_pass = g_object_cache->GetRenderPass( m_texture->GetFormat(), VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE); UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass, g_shader_cache->GetPassthroughVertexShader(), g_shader_cache->GetPassthroughGeometryShader(), TextureCache::GetInstance()->GetCopyShader()); VkRect2D region = { {dst_rect.left, dst_rect.top}, {static_cast<u32>(dst_rect.GetWidth()), static_cast<u32>(dst_rect.GetHeight())}}; draw.BeginRenderPass(m_framebuffer, region); draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler()); draw.DrawQuad(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight(), src_rect.left, src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(), static_cast<int>(src_texture->GetWidth()), static_cast<int>(src_texture->GetHeight())); draw.EndRenderPass(); // Ensure both textures remain in the SHADER_READ_ONLY layout so they can be bound. src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); }
void DXStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, AbstractTexture* dst, const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer, u32 dst_level) { _assert_(m_type == StagingTextureType::Upload); _assert_(src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()); _assert_(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= m_config.width && src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= m_config.height); _assert_(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= dst->GetConfig().width && dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= dst->GetConfig().height); if (IsMapped()) DXStagingTexture::Unmap(); CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1); D3D::context->CopySubresourceRegion( static_cast<const DXTexture*>(dst)->GetRawTexIdentifier()->GetTex(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetConfig().levels), static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex, 0, &src_box); }
void VKTexture::CopyRectangleFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer, u32 dst_level) { Texture2D* src_texture = static_cast<const VKTexture*>(src)->GetRawTexIdentifier(); _assert_msg_(VIDEO, static_cast<u32>(src_rect.GetWidth()) <= src_texture->GetWidth() && static_cast<u32>(src_rect.GetHeight()) <= src_texture->GetHeight(), "Source rect is too large for CopyRectangleFromTexture"); _assert_msg_(VIDEO, static_cast<u32>(dst_rect.GetWidth()) <= m_config.width && static_cast<u32>(dst_rect.GetHeight()) <= m_config.height, "Dest rect is too large for CopyRectangleFromTexture"); VkImageCopy image_copy = { {VK_IMAGE_ASPECT_COLOR_BIT, src_level, src_layer, src_texture->GetLayers()}, {src_rect.left, src_rect.top, 0}, {VK_IMAGE_ASPECT_COLOR_BIT, dst_level, dst_layer, m_config.layers}, {dst_rect.left, dst_rect.top, 0}, {static_cast<uint32_t>(src_rect.GetWidth()), static_cast<uint32_t>(src_rect.GetHeight()), 1}}; // Must be called outside of a render pass. StateTracker::GetInstance()->EndRenderPass(); src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkCmdCopyImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); // Ensure both textures remain in the SHADER_READ_ONLY layout so they can be bound. src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); }
void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer, u32 dst_level) { const DXTexture* srcentry = static_cast<const DXTexture*>(src); _assert_(src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()); D3D11_BOX src_box; src_box.left = src_rect.left; src_box.top = src_rect.top; src_box.right = src_rect.right; src_box.bottom = src_rect.bottom; src_box.front = 0; src_box.back = 1; D3D::context->CopySubresourceRegion( m_texture->GetTex(), D3D11CalcSubresource(dst_level, dst_layer, m_config.levels), dst_rect.left, dst_rect.top, 0, srcentry->m_texture->GetTex(), D3D11CalcSubresource(src_level, src_layer, srcentry->m_config.levels), &src_box); }
void DXStagingTexture::CopyFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect) { _assert_(m_type == StagingTextureType::Readback); _assert_(src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()); _assert_(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= src->GetConfig().width && src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= src->GetConfig().height); _assert_(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= m_config.width && dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= m_config.height); if (IsMapped()) DXStagingTexture::Unmap(); CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1); D3D::context->CopySubresourceRegion( m_tex, 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, static_cast<const DXTexture*>(src)->GetRawTexIdentifier()->GetTex(), D3D11CalcSubresource(src_level, src_layer, src->GetConfig().levels), &src_box); m_needs_flush = true; }
void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect, u32 layer, u32 level) { const DXTexture* srcentry = static_cast<const DXTexture*>(src); DEBUG_ASSERT(m_config.samples > 1 && m_config.width == srcentry->m_config.width && m_config.height == srcentry->m_config.height && m_config.samples == 1); DEBUG_ASSERT(rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) && rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height)); D3D::context->ResolveSubresource( m_d3d_texture, D3D11CalcSubresource(level, layer, m_config.levels), srcentry->m_d3d_texture, D3D11CalcSubresource(level, layer, srcentry->m_config.levels), GetDXGIFormatForHostFormat(m_config.format, false)); }
void TextureCache::CopyTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect) { _assert_msg_(VIDEO, static_cast<u32>(src_rect.GetWidth()) <= src_texture->GetWidth() && static_cast<u32>(src_rect.GetHeight()) <= src_texture->GetHeight(), "Source rect is too large for CopyRectangleFromTexture"); _assert_msg_(VIDEO, static_cast<u32>(dst_rect.GetWidth()) <= dst_texture->config.width && static_cast<u32>(dst_rect.GetHeight()) <= dst_texture->config.height, "Dest rect is too large for CopyRectangleFromTexture"); VkImageCopy image_copy = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_texture->GetLayers() }, // VkImageSubresourceLayers srcSubresource { src_rect.left, src_rect.top, 0 }, // VkOffset3D srcOffset { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, // VkImageSubresourceLayers dstSubresource dst_texture->config.layers }, { dst_rect.left, dst_rect.top, 0 }, // VkOffset3D dstOffset { static_cast<uint32_t>(src_rect.GetWidth()), static_cast<uint32_t>(src_rect.GetHeight()), 1 } // VkExtent3D extent }; // Must be called outside of a render pass. StateTracker::GetInstance()->EndRenderPass(); src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); dst_texture->GetTexture()->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkCmdCopyImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_texture->GetTexture()->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); }
void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride, u32 dst_height, Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect) { StateTracker::GetInstance()->EndRenderPass(); // Borrow framebuffer from EFB2RAM encoder. VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); m_encoding_render_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // Use fragment shader to convert RGBA to YUYV. // Use linear sampler for downscaling. This texture is in BGRA order, so the data is already in // the order the guest is expecting and we don't have to swap it at readback time. The width // is halved because we're using an RGBA8 texture, but the YUYV data is two bytes per pixel. u32 output_width = dst_width / 2; UtilityShaderDraw draw(command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_encoding_render_pass, g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, m_rgb_to_yuyv_shader); VkRect2D region = {{0, 0}, {output_width, dst_height}}; draw.BeginRenderPass(m_encoding_render_framebuffer, region); draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler()); draw.DrawQuad(0, 0, static_cast<int>(output_width), static_cast<int>(dst_height), src_rect.left, src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(), static_cast<int>(src_texture->GetWidth()), static_cast<int>(src_texture->GetHeight())); draw.EndRenderPass(); // Render pass transitions to TRANSFER_SRC. m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // Copy from encoding texture to download buffer. m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, output_width, dst_height, 0, 0); Util::ExecuteCurrentCommandsAndRestoreState(false, true); // Finally, copy to guest memory. This may have a different stride. m_encoding_download_texture->ReadTexels(0, 0, output_width, dst_height, dst_ptr, dst_stride); }
void TextureCache::TCacheEntry::CopyRectangleFromTexture( const TCacheEntryBase* source, const MathUtil::Rectangle<int> &srcrect, const MathUtil::Rectangle<int> &dstrect) { TCacheEntry* srcentry = (TCacheEntry*)source; if (srcrect.GetWidth() == dstrect.GetWidth() && srcrect.GetHeight() == dstrect.GetHeight()) { const D3D11_BOX *psrcbox = nullptr; D3D11_BOX srcbox; if (srcrect.left != 0 || srcrect.top != 0) { srcbox.left = srcrect.left; srcbox.top = srcrect.top; srcbox.right = srcrect.right; srcbox.bottom = srcrect.bottom; psrcbox = &srcbox; } D3D::context->CopySubresourceRegion( texture->GetTex(), 0, dstrect.left, dstrect.top, 0, srcentry->texture->GetTex(), 0, psrcbox); return; } else if (!config.rendertarget) { return; } g_renderer->ResetAPIState(); // reset any game specific settings const D3D11_VIEWPORT vp = CD3D11_VIEWPORT( float(dstrect.left), float(dstrect.top), float(dstrect.GetWidth()), float(dstrect.GetHeight())); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); D3D::context->RSSetViewports(1, &vp); D3D::SetLinearCopySampler(); D3D11_RECT srcRC; srcRC.left = srcrect.left; srcRC.right = srcrect.right; srcRC.top = srcrect.top; srcRC.bottom = srcrect.bottom; D3D::drawShadedTexQuad(srcentry->texture->GetSRV(), &srcRC, srcentry->config.width, srcentry->config.height, PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, 1.0, 0); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); }
void TextureCache::TCacheEntry::CopyRectangleFromTexture( const TCacheEntryBase* source, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { const TCacheEntry* srcentry = reinterpret_cast<const TCacheEntry*>(source); if (src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()) { D3D12_BOX srcbox; srcbox.left = src_rect.left; srcbox.top = src_rect.top; srcbox.right = src_rect.right; srcbox.bottom = src_rect.bottom; srcbox.front = 0; srcbox.back = srcentry->config.layers; if (static_cast<u32>(src_rect.GetHeight()) > config.height || static_cast<u32>(src_rect.GetWidth()) > config.width) { // To mimic D3D11 behavior, we're just going to drop the clear since it is invalid. // This invalid copy needs to be fixed above the Backend level. // On D3D12, instead of silently dropping this invalid clear, the runtime throws an exception // so we need to filter it out ourselves. return; } D3D12_TEXTURE_COPY_LOCATION dst_location = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0); D3D12_TEXTURE_COPY_LOCATION src_location = CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST); srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE); D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0, &src_location, &srcbox); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); return; } else if (!config.rendertarget) { return; } D3D::SetViewportAndScissor(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight()); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr); D3D::SetLinearCopySampler(); D3D12_RECT src_rc; src_rc.left = src_rect.left; src_rc.right = src_rect.right; src_rc.top = src_rect.top; src_rc.bottom = src_rect.bottom; D3D::DrawShadedTexQuad(srcentry->m_texture, &src_rc, srcentry->config.width, srcentry->config.height, StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled()); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE); D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12()); g_renderer->RestoreAPIState(); }
void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* source, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { const TCacheEntry* srcentry = reinterpret_cast<const TCacheEntry*>(source); if (src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()) { // These assertions should hold true unless the base code is passing us sizes too large, in // which case it should be fixed instead. _assert_msg_(VIDEO, static_cast<u32>(src_rect.GetWidth()) <= source->config.width && static_cast<u32>(src_rect.GetHeight()) <= source->config.height, "Source rect is too large for CopyRectangleFromTexture"); _assert_msg_(VIDEO, static_cast<u32>(dst_rect.GetWidth()) <= config.width && static_cast<u32>(dst_rect.GetHeight()) <= config.height, "Dest rect is too large for CopyRectangleFromTexture"); CD3DX12_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, srcentry->config.layers); D3D12_TEXTURE_COPY_LOCATION dst_location = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0); D3D12_TEXTURE_COPY_LOCATION src_location = CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST); srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE); D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0, &src_location, &src_box); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); return; } else if (!config.rendertarget) { return; } D3D::SetViewportAndScissor(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight()); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr); D3D::SetLinearCopySampler(); D3D12_RECT src_rc; src_rc.left = src_rect.left; src_rc.right = src_rect.right; src_rc.top = src_rect.top; src_rc.bottom = src_rect.bottom; D3D::DrawShadedTexQuad( srcentry->m_texture, &src_rc, srcentry->config.width, srcentry->config.height, StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled()); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); FramebufferManager::GetEFBColorTexture()->TransitionToResourceState( D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState( D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE); g_renderer->RestoreAPIState(); }
void TextureCache::TCacheEntry::CopyRectangleFromTexture( const TCacheEntryBase* source, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { TCacheEntry* srcentry = (TCacheEntry*)source; if (src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight()) { const D3D12_BOX *psrcbox = nullptr; D3D12_BOX srcbox; if (src_rect.left != 0 || src_rect.top != 0 || src_rect.GetWidth() != srcentry->config.width || src_rect.GetHeight() != srcentry->config.height) { srcbox.left = src_rect.left; srcbox.top = src_rect.top; srcbox.right = src_rect.right; srcbox.bottom = src_rect.bottom; srcbox.front = 0; srcbox.back = 1; psrcbox = &srcbox; } D3D12_TEXTURE_COPY_LOCATION dst = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0); D3D12_TEXTURE_COPY_LOCATION src = CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST); srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE); D3D::current_command_list->CopyTextureRegion(&dst, dst_rect.left, dst_rect.top, 0, &src, psrcbox); return; } else if (!config.rendertarget) { return; } const D3D12_VIEWPORT vp12 = { float(dst_rect.left), float(dst_rect.top), float(dst_rect.GetWidth()), float(dst_rect.GetHeight()), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH }; D3D::current_command_list->RSSetViewports(1, &vp12); m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr); D3D::SetLinearCopySampler(); D3D12_RECT srcRC; srcRC.left = src_rect.left; srcRC.right = src_rect.right; srcRC.top = src_rect.top; srcRC.bottom = src_rect.bottom; D3D::DrawShadedTexQuad(srcentry->m_texture, &srcRC, srcentry->config.width, srcentry->config.height, StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled()); FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE); D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12()); g_renderer->RestoreAPIState(); }