diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
| commit | 3570c7f03a2aa90aa634f96c0af1969af610f14d (patch) | |
| tree | 4252e03c0e853ba7cffe022937698c854ad0eaa9 /Source/Core/VideoBackends/D3D12/TextureCache.cpp | |
| parent | 2115e8a4a6814e32107b5205ff5c95bbd3c6e99c (diff) | |
Reformat all the things. Have fun with merge conflicts.
Diffstat (limited to 'Source/Core/VideoBackends/D3D12/TextureCache.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/D3D12/TextureCache.cpp | 892 |
1 files changed, 454 insertions, 438 deletions
diff --git a/Source/Core/VideoBackends/D3D12/TextureCache.cpp b/Source/Core/VideoBackends/D3D12/TextureCache.cpp index 4b235d1037..ffedeeeadc 100644 --- a/Source/Core/VideoBackends/D3D12/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D12/TextureCache.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "VideoBackends/D3D12/TextureCache.h" #include "VideoBackends/D3D12/D3DBase.h" #include "VideoBackends/D3D12/D3DCommandListManager.h" #include "VideoBackends/D3D12/D3DDescriptorHeapManager.h" @@ -12,7 +13,6 @@ #include "VideoBackends/D3D12/FramebufferManager.h" #include "VideoBackends/D3D12/PSTextureEncoder.h" #include "VideoBackends/D3D12/StaticShaderCache.h" -#include "VideoBackends/D3D12/TextureCache.h" #include "VideoBackends/D3D12/TextureEncoder.h" #include "VideoCommon/ImageWrite.h" #include "VideoCommon/LookUpTables.h" @@ -21,7 +21,6 @@ namespace DX12 { - static std::unique_ptr<TextureEncoder> s_encoder = nullptr; static std::unique_ptr<D3DStreamBuffer> s_efb_copy_stream_buffer = nullptr; @@ -32,287 +31,288 @@ static size_t s_texture_cache_entry_readback_buffer_size = 0; TextureCache::TCacheEntry::~TCacheEntry() { - m_texture->Release(); + m_texture->Release(); } void TextureCache::TCacheEntry::Bind(unsigned int stage) { - // Textures bound as group in TextureCache::BindTextures method. + // Textures bound as group in TextureCache::BindTextures method. } bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) { - u32 level_width = std::max(config.width >> level, 1u); - u32 level_height = std::max(config.height >> level, 1u); - size_t level_pitch = D3D::AlignValue(level_width * sizeof(u32), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - size_t required_readback_buffer_size = level_pitch * level_height; - - // Check if the current readback buffer is large enough - if (required_readback_buffer_size > s_texture_cache_entry_readback_buffer_size) - { - // Reallocate the buffer with the new size. Safe to immediately release because we're the only user and we block until completion. - if (s_texture_cache_entry_readback_buffer) - s_texture_cache_entry_readback_buffer->Release(); - - s_texture_cache_entry_readback_buffer_size = required_readback_buffer_size; - CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(s_texture_cache_entry_readback_buffer_size), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(&s_texture_cache_entry_readback_buffer))); - } - - m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE); - - D3D12_TEXTURE_COPY_LOCATION dst_location = {}; - dst_location.pResource = s_texture_cache_entry_readback_buffer; - dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - dst_location.PlacedFootprint.Offset = 0; - dst_location.PlacedFootprint.Footprint.Depth = 1; - dst_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - dst_location.PlacedFootprint.Footprint.Width = level_width; - dst_location.PlacedFootprint.Footprint.Height = level_height; - dst_location.PlacedFootprint.Footprint.RowPitch = static_cast<UINT>(level_pitch); - - D3D12_TEXTURE_COPY_LOCATION src_location = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), level); - - D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, nullptr); - - D3D::command_list_mgr->ExecuteQueuedWork(true); - - // Map readback buffer and save to file. - void* readback_texture_map; - D3D12_RANGE read_range = { 0, required_readback_buffer_size }; - CheckHR(s_texture_cache_entry_readback_buffer->Map(0, &read_range, &readback_texture_map)); - - bool saved = TextureToPng( - static_cast<u8*>(readback_texture_map), - dst_location.PlacedFootprint.Footprint.RowPitch, - filename, - dst_location.PlacedFootprint.Footprint.Width, - dst_location.PlacedFootprint.Footprint.Height - ); - - D3D12_RANGE write_range = {}; - s_texture_cache_entry_readback_buffer->Unmap(0, &write_range); - return saved; + u32 level_width = std::max(config.width >> level, 1u); + u32 level_height = std::max(config.height >> level, 1u); + size_t level_pitch = + D3D::AlignValue(level_width * sizeof(u32), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); + size_t required_readback_buffer_size = level_pitch * level_height; + + // Check if the current readback buffer is large enough + if (required_readback_buffer_size > s_texture_cache_entry_readback_buffer_size) + { + // Reallocate the buffer with the new size. Safe to immediately release because we're the only + // user and we block until completion. + if (s_texture_cache_entry_readback_buffer) + s_texture_cache_entry_readback_buffer->Release(); + + s_texture_cache_entry_readback_buffer_size = required_readback_buffer_size; + CheckHR(D3D::device12->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK), D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(s_texture_cache_entry_readback_buffer_size), + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_PPV_ARGS(&s_texture_cache_entry_readback_buffer))); + } + + m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE); + + D3D12_TEXTURE_COPY_LOCATION dst_location = {}; + dst_location.pResource = s_texture_cache_entry_readback_buffer; + dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + dst_location.PlacedFootprint.Offset = 0; + dst_location.PlacedFootprint.Footprint.Depth = 1; + dst_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dst_location.PlacedFootprint.Footprint.Width = level_width; + dst_location.PlacedFootprint.Footprint.Height = level_height; + dst_location.PlacedFootprint.Footprint.RowPitch = static_cast<UINT>(level_pitch); + + D3D12_TEXTURE_COPY_LOCATION src_location = + CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), level); + + D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, nullptr); + + D3D::command_list_mgr->ExecuteQueuedWork(true); + + // Map readback buffer and save to file. + void* readback_texture_map; + D3D12_RANGE read_range = {0, required_readback_buffer_size}; + CheckHR(s_texture_cache_entry_readback_buffer->Map(0, &read_range, &readback_texture_map)); + + bool saved = TextureToPng(static_cast<u8*>(readback_texture_map), + dst_location.PlacedFootprint.Footprint.RowPitch, filename, + dst_location.PlacedFootprint.Footprint.Width, + dst_location.PlacedFootprint.Footprint.Height); + + D3D12_RANGE write_range = {}; + s_texture_cache_entry_readback_buffer->Unmap(0, &write_range); + return saved; } -void TextureCache::TCacheEntry::CopyRectangleFromTexture( - const TCacheEntryBase* source, - const MathUtil::Rectangle<int>& src_rect, - const MathUtil::Rectangle<int>& dst_rect) +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(); + 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::Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level) + unsigned int expanded_width, unsigned int level) { - unsigned int src_pitch = 4 * expanded_width; - D3D::ReplaceRGBATexture2D(m_texture->GetTex12(), TextureCache::temp, width, height, src_pitch, level, m_texture->GetResourceUsageState()); + unsigned int src_pitch = 4 * expanded_width; + D3D::ReplaceRGBATexture2D(m_texture->GetTex12(), TextureCache::temp, width, height, src_pitch, + level, m_texture->GetResourceUsageState()); } TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config) { - if (config.rendertarget) - { - D3DTexture2D* texture = D3DTexture2D::Create(config.width, config.height, - TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, - DXGI_FORMAT_R8G8B8A8_UNORM, 1, config.layers); + if (config.rendertarget) + { + D3DTexture2D* texture = + D3DTexture2D::Create(config.width, config.height, + TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, + DXGI_FORMAT_R8G8B8A8_UNORM, 1, config.layers); - TCacheEntry* entry = new TCacheEntry(config, texture); + TCacheEntry* entry = new TCacheEntry(config, texture); - entry->m_texture_srv_cpu_handle = texture->GetSRV12CPU(); - entry->m_texture_srv_gpu_handle = texture->GetSRV12GPU(); - entry->m_texture_srv_gpu_handle_cpu_shadow = texture->GetSRV12GPUCPUShadow(); + entry->m_texture_srv_cpu_handle = texture->GetSRV12CPU(); + entry->m_texture_srv_gpu_handle = texture->GetSRV12GPU(); + entry->m_texture_srv_gpu_handle_cpu_shadow = texture->GetSRV12GPUCPUShadow(); - return entry; - } - else - { - ID3D12Resource* texture_resource = nullptr; - - D3D12_RESOURCE_DESC texture_resource_desc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, - config.width, config.height, 1, config.levels); - - CheckHR( - D3D::device12->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC(texture_resource_desc), - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - nullptr, - IID_PPV_ARGS(&texture_resource) - ) - ); - - D3DTexture2D* texture = new D3DTexture2D( - texture_resource, - TEXTURE_BIND_FLAG_SHADER_RESOURCE, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_UNKNOWN, - false, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE - ); - - TCacheEntry* const entry = new TCacheEntry( - config, texture - ); - - entry->m_texture_srv_cpu_handle = texture->GetSRV12CPU(); - entry->m_texture_srv_gpu_handle = texture->GetSRV12GPU(); - entry->m_texture_srv_gpu_handle_cpu_shadow = texture->GetSRV12GPUCPUShadow(); - - // EXISTINGD3D11TODO: better debug names - D3D::SetDebugObjectName12(entry->m_texture->GetTex12(), "a texture of the TextureCache"); - - SAFE_RELEASE(texture_resource); - - return entry; - } -} + return entry; + } + else + { + ID3D12Resource* texture_resource = nullptr; -void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_format, const EFBRectangle& srcRect, - bool scale_by_half, unsigned int cbuf_id, const float* colmat) -{ - // When copying at half size, in multisampled mode, resolve the color/depth buffer first. - // This is because multisampled texture reads go through Load, not Sample, and the linear - // filter is ignored. - bool multisampled = (g_ActiveConfig.iMultisamples > 1); - D3DTexture2D* efb_tex = (src_format == PEControl::Z24) ? - FramebufferManager::GetEFBDepthTexture() : - FramebufferManager::GetEFBColorTexture(); - if (multisampled && scale_by_half) - { - multisampled = false; - efb_tex = (src_format == PEControl::Z24) ? - FramebufferManager::GetResolvedEFBDepthTexture() : - FramebufferManager::GetResolvedEFBColorTexture(); - } - - // set transformation - if (s_efb_copy_last_cbuf_id != cbuf_id) - { - s_efb_copy_stream_buffer->AllocateSpaceInBuffer(28 * sizeof(float), 256); - - memcpy(s_efb_copy_stream_buffer->GetCPUAddressOfCurrentAllocation(), colmat, 28 * sizeof(float)); - - s_efb_copy_last_cbuf_id = cbuf_id; - } - - // stretch picture with increased internal resolution - D3D::SetViewportAndScissor(0, 0, config.width, config.height); + D3D12_RESOURCE_DESC texture_resource_desc = CD3DX12_RESOURCE_DESC::Tex2D( + DXGI_FORMAT_R8G8B8A8_UNORM, config.width, config.height, 1, config.levels); - D3D::current_command_list->SetGraphicsRootConstantBufferView(DESCRIPTOR_TABLE_PS_CBVONE, s_efb_copy_stream_buffer->GetGPUAddressOfCurrentAllocation()); - D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PS_CBV, true); + CheckHR(D3D::device12->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC(texture_resource_desc), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + nullptr, IID_PPV_ARGS(&texture_resource))); - const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); - // EXISTINGD3D11TODO: try targetSource.asRECT(); - const D3D12_RECT sourcerect = CD3DX12_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); + D3DTexture2D* texture = + new D3DTexture2D(texture_resource, TEXTURE_BIND_FLAG_SHADER_RESOURCE, DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - // Use linear filtering if (bScaleByHalf), use point filtering otherwise - if (scale_by_half) - D3D::SetLinearCopySampler(); - else - D3D::SetPointCopySampler(); + TCacheEntry* const entry = new TCacheEntry(config, texture); - // Make sure we don't draw with the texture set as both a source and target. - // (This can happen because we don't unbind textures when we free them.) + entry->m_texture_srv_cpu_handle = texture->GetSRV12CPU(); + entry->m_texture_srv_gpu_handle = texture->GetSRV12GPU(); + entry->m_texture_srv_gpu_handle_cpu_shadow = texture->GetSRV12GPUCPUShadow(); - m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); - D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr); + // EXISTINGD3D11TODO: better debug names + D3D::SetDebugObjectName12(entry->m_texture->GetTex12(), "a texture of the TextureCache"); - // Create texture copy - D3D::DrawShadedTexQuad( - efb_tex, - &sourcerect, - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight(), - (src_format == PEControl::Z24) ? StaticShaderCache::GetDepthMatrixPixelShader(multisampled) : StaticShaderCache::GetColorMatrixPixelShader(multisampled), - StaticShaderCache::GetSimpleVertexShader(), - StaticShaderCache::GetSimpleVertexShaderInputLayout(), - StaticShaderCache::GetCopyGeometryShader(), - 1.0f, 0, DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled() - ); + SAFE_RELEASE(texture_resource); - 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); + return entry; + } +} - g_renderer->RestoreAPIState(); +void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_format, + const EFBRectangle& srcRect, bool scale_by_half, + unsigned int cbuf_id, const float* colmat) +{ + // When copying at half size, in multisampled mode, resolve the color/depth buffer first. + // This is because multisampled texture reads go through Load, not Sample, and the linear + // filter is ignored. + bool multisampled = (g_ActiveConfig.iMultisamples > 1); + D3DTexture2D* efb_tex = (src_format == PEControl::Z24) ? + FramebufferManager::GetEFBDepthTexture() : + FramebufferManager::GetEFBColorTexture(); + if (multisampled && scale_by_half) + { + multisampled = false; + efb_tex = (src_format == PEControl::Z24) ? FramebufferManager::GetResolvedEFBDepthTexture() : + FramebufferManager::GetResolvedEFBColorTexture(); + } + + // set transformation + if (s_efb_copy_last_cbuf_id != cbuf_id) + { + s_efb_copy_stream_buffer->AllocateSpaceInBuffer(28 * sizeof(float), 256); + + memcpy(s_efb_copy_stream_buffer->GetCPUAddressOfCurrentAllocation(), colmat, + 28 * sizeof(float)); + + s_efb_copy_last_cbuf_id = cbuf_id; + } + + // stretch picture with increased internal resolution + D3D::SetViewportAndScissor(0, 0, config.width, config.height); + + D3D::current_command_list->SetGraphicsRootConstantBufferView( + DESCRIPTOR_TABLE_PS_CBVONE, s_efb_copy_stream_buffer->GetGPUAddressOfCurrentAllocation()); + D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PS_CBV, true); + + const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); + // EXISTINGD3D11TODO: try targetSource.asRECT(); + const D3D12_RECT sourcerect = + CD3DX12_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); + + // Use linear filtering if (bScaleByHalf), use point filtering otherwise + if (scale_by_half) + D3D::SetLinearCopySampler(); + else + D3D::SetPointCopySampler(); + + // Make sure we don't draw with the texture set as both a source and target. + // (This can happen because we don't unbind textures when we free them.) + + m_texture->TransitionToResourceState(D3D::current_command_list, + D3D12_RESOURCE_STATE_RENDER_TARGET); + D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr); + + // Create texture copy + D3D::DrawShadedTexQuad( + efb_tex, &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), + (src_format == PEControl::Z24) ? StaticShaderCache::GetDepthMatrixPixelShader(multisampled) : + StaticShaderCache::GetColorMatrixPixelShader(multisampled), + StaticShaderCache::GetSimpleVertexShader(), + StaticShaderCache::GetSimpleVertexShaderInputLayout(), + StaticShaderCache::GetCopyGeometryShader(), 1.0f, 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::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf) +void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, + const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { - s_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf); + s_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, + srcFormat, srcRect, isIntensity, scaleByHalf); } static const constexpr char s_palette_shader_hlsl[] = -R"HLSL( + R"HLSL( sampler samp0 : register(s0); Texture2DArray Tex0 : register(t0); Buffer<uint> Tex1 : register(t1); @@ -391,232 +391,248 @@ void main( } )HLSL"; -void TextureCache::ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) +void TextureCache::ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, + void* palette, TlutFormat format) { - const unsigned int palette_buffer_allocation_size = 512; - m_palette_stream_buffer->AllocateSpaceInBuffer(palette_buffer_allocation_size, 256); - memcpy(m_palette_stream_buffer->GetCPUAddressOfCurrentAllocation(), palette, palette_buffer_allocation_size); - - // stretch picture with increased internal resolution - D3D::SetViewportAndScissor(0, 0, unconverted->config.width, unconverted->config.height); - - // D3D12: Because the second SRV slot is occupied by this buffer, and an arbitrary texture occupies the first SRV slot, - // we need to allocate temporary space out of our descriptor heap, place the palette SRV in the second slot, then copy the - // existing texture's descriptor into the first slot. - - // First, allocate the (temporary) space in the descriptor heap. - D3D12_CPU_DESCRIPTOR_HANDLE srv_group_cpu_handle[2] = {}; - D3D12_GPU_DESCRIPTOR_HANDLE srv_group_gpu_handle[2] = {}; - D3D::gpu_descriptor_heap_mgr->AllocateGroup(srv_group_cpu_handle, 2, srv_group_gpu_handle, nullptr, true); - - srv_group_cpu_handle[1].ptr = srv_group_cpu_handle[0].ptr + D3D::resource_descriptor_size; - - // Now, create the palette SRV at the appropriate offset. - D3D12_SHADER_RESOURCE_VIEW_DESC palette_buffer_srv_desc = { - DXGI_FORMAT_R16_UINT, // DXGI_FORMAT Format; - D3D12_SRV_DIMENSION_BUFFER, // D3D12_SRV_DIMENSION ViewDimension; - D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING // UINT Shader4ComponentMapping; - }; - - // Each 'element' is two bytes since format is R16. - palette_buffer_srv_desc.Buffer.FirstElement = m_palette_stream_buffer->GetOffsetOfCurrentAllocation() / sizeof(u16); - palette_buffer_srv_desc.Buffer.NumElements = 256; - - D3D::device12->CreateShaderResourceView(m_palette_stream_buffer->GetBuffer(), &palette_buffer_srv_desc, srv_group_cpu_handle[1]); - - // Now, copy the existing texture's descriptor into the new temporary location. - static_cast<TCacheEntry*>(unconverted)->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - D3D::device12->CopyDescriptorsSimple( - 1, - srv_group_cpu_handle[0], - static_cast<TCacheEntry*>(unconverted)->m_texture->GetSRV12GPUCPUShadow(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - - // Finally, bind our temporary location. - D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, srv_group_gpu_handle[0]); - - // D3D11EXISTINGTODO: Add support for C14X2 format. (Different multiplier, more palette entries.) - - // D3D12: See TextureCache::TextureCache() - because there are only two possible buffer contents here, - // just pre-populate the data in two parts of the same upload heap. - if ((unconverted->format & 0xf) == GX_TF_I4) - { - D3D::current_command_list->SetGraphicsRootConstantBufferView(DESCRIPTOR_TABLE_PS_CBVONE, m_palette_uniform_buffer->GetGPUVirtualAddress()); - } - else - { - D3D::current_command_list->SetGraphicsRootConstantBufferView(DESCRIPTOR_TABLE_PS_CBVONE, m_palette_uniform_buffer->GetGPUVirtualAddress() + 256); - } - - D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PS_CBV, true); - - const D3D12_RECT source_rect = CD3DX12_RECT(0, 0, unconverted->config.width, unconverted->config.height); - - D3D::SetPointCopySampler(); - - // Make sure we don't draw with the texture set as both a source and target. - // (This can happen because we don't unbind textures when we free them.) - - static_cast<TCacheEntry*>(entry)->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); - D3D::current_command_list->OMSetRenderTargets(1, &static_cast<TCacheEntry*>(entry)->m_texture->GetRTV12(), FALSE, nullptr); - - // Create texture copy - D3D::DrawShadedTexQuad( - static_cast<TCacheEntry*>(unconverted)->m_texture, - &source_rect, unconverted->config.width, - unconverted->config.height, - m_palette_pixel_shaders[format], - StaticShaderCache::GetSimpleVertexShader(), - StaticShaderCache::GetSimpleVertexShaderInputLayout(), - StaticShaderCache::GetCopyGeometryShader(), - 1.0f, - 0, - DXGI_FORMAT_R8G8B8A8_UNORM, - true, - static_cast<TCacheEntry*>(entry)->m_texture->GetMultisampled() - ); - - static_cast<TCacheEntry*>(entry)->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(); + const unsigned int palette_buffer_allocation_size = 512; + m_palette_stream_buffer->AllocateSpaceInBuffer(palette_buffer_allocation_size, 256); + memcpy(m_palette_stream_buffer->GetCPUAddressOfCurrentAllocation(), palette, + palette_buffer_allocation_size); + + // stretch picture with increased internal resolution + D3D::SetViewportAndScissor(0, 0, unconverted->config.width, unconverted->config.height); + + // D3D12: Because the second SRV slot is occupied by this buffer, and an arbitrary texture + // occupies the first SRV slot, + // we need to allocate temporary space out of our descriptor heap, place the palette SRV in the + // second slot, then copy the + // existing texture's descriptor into the first slot. + + // First, allocate the (temporary) space in the descriptor heap. + D3D12_CPU_DESCRIPTOR_HANDLE srv_group_cpu_handle[2] = {}; + D3D12_GPU_DESCRIPTOR_HANDLE srv_group_gpu_handle[2] = {}; + D3D::gpu_descriptor_heap_mgr->AllocateGroup(srv_group_cpu_handle, 2, srv_group_gpu_handle, + nullptr, true); + + srv_group_cpu_handle[1].ptr = srv_group_cpu_handle[0].ptr + D3D::resource_descriptor_size; + + // Now, create the palette SRV at the appropriate offset. + D3D12_SHADER_RESOURCE_VIEW_DESC palette_buffer_srv_desc = { + DXGI_FORMAT_R16_UINT, // DXGI_FORMAT Format; + D3D12_SRV_DIMENSION_BUFFER, // D3D12_SRV_DIMENSION ViewDimension; + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING // UINT Shader4ComponentMapping; + }; + + // Each 'element' is two bytes since format is R16. + palette_buffer_srv_desc.Buffer.FirstElement = + m_palette_stream_buffer->GetOffsetOfCurrentAllocation() / sizeof(u16); + palette_buffer_srv_desc.Buffer.NumElements = 256; + + D3D::device12->CreateShaderResourceView(m_palette_stream_buffer->GetBuffer(), + &palette_buffer_srv_desc, srv_group_cpu_handle[1]); + + // Now, copy the existing texture's descriptor into the new temporary location. + static_cast<TCacheEntry*>(unconverted) + ->m_texture->TransitionToResourceState(D3D::current_command_list, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + D3D::device12->CopyDescriptorsSimple( + 1, srv_group_cpu_handle[0], + static_cast<TCacheEntry*>(unconverted)->m_texture->GetSRV12GPUCPUShadow(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + // Finally, bind our temporary location. + D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, + srv_group_gpu_handle[0]); + + // D3D11EXISTINGTODO: Add support for C14X2 format. (Different multiplier, more palette entries.) + + // D3D12: See TextureCache::TextureCache() - because there are only two possible buffer contents + // here, + // just pre-populate the data in two parts of the same upload heap. + if ((unconverted->format & 0xf) == GX_TF_I4) + { + D3D::current_command_list->SetGraphicsRootConstantBufferView( + DESCRIPTOR_TABLE_PS_CBVONE, m_palette_uniform_buffer->GetGPUVirtualAddress()); + } + else + { + D3D::current_command_list->SetGraphicsRootConstantBufferView( + DESCRIPTOR_TABLE_PS_CBVONE, m_palette_uniform_buffer->GetGPUVirtualAddress() + 256); + } + + D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PS_CBV, true); + + const D3D12_RECT source_rect = + CD3DX12_RECT(0, 0, unconverted->config.width, unconverted->config.height); + + D3D::SetPointCopySampler(); + + // Make sure we don't draw with the texture set as both a source and target. + // (This can happen because we don't unbind textures when we free them.) + + static_cast<TCacheEntry*>(entry)->m_texture->TransitionToResourceState( + D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET); + D3D::current_command_list->OMSetRenderTargets( + 1, &static_cast<TCacheEntry*>(entry)->m_texture->GetRTV12(), FALSE, nullptr); + + // Create texture copy + D3D::DrawShadedTexQuad( + static_cast<TCacheEntry*>(unconverted)->m_texture, &source_rect, unconverted->config.width, + unconverted->config.height, m_palette_pixel_shaders[format], + StaticShaderCache::GetSimpleVertexShader(), + StaticShaderCache::GetSimpleVertexShaderInputLayout(), + StaticShaderCache::GetCopyGeometryShader(), 1.0f, 0, DXGI_FORMAT_R8G8B8A8_UNORM, true, + static_cast<TCacheEntry*>(entry)->m_texture->GetMultisampled()); + + static_cast<TCacheEntry*>(entry)->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(); } D3D12_SHADER_BYTECODE GetConvertShader12(std::string& Type) { - std::string shader = "#define DECODE DecodePixel_"; - shader.append(Type); - shader.append("\n"); - shader.append(s_palette_shader_hlsl); + std::string shader = "#define DECODE DecodePixel_"; + shader.append(Type); + shader.append("\n"); + shader.append(s_palette_shader_hlsl); - ID3DBlob* blob = nullptr; - D3D::CompilePixelShader(shader, &blob); + ID3DBlob* blob = nullptr; + D3D::CompilePixelShader(shader, &blob); - return { blob->GetBufferPointer(), blob->GetBufferSize() }; + return {blob->GetBufferPointer(), blob->GetBufferSize()}; } TextureCache::TextureCache() { - s_encoder = std::make_unique<PSTextureEncoder>(); - s_encoder->Init(); + s_encoder = std::make_unique<PSTextureEncoder>(); + s_encoder->Init(); - s_efb_copy_stream_buffer = std::make_unique<D3DStreamBuffer>(1024 * 1024, 1024 * 1024, nullptr); - s_efb_copy_last_cbuf_id = UINT_MAX; + s_efb_copy_stream_buffer = std::make_unique<D3DStreamBuffer>(1024 * 1024, 1024 * 1024, nullptr); + s_efb_copy_last_cbuf_id = UINT_MAX; - s_texture_cache_entry_readback_buffer = nullptr; - s_texture_cache_entry_readback_buffer_size = 0; + s_texture_cache_entry_readback_buffer = nullptr; + s_texture_cache_entry_readback_buffer_size = 0; - m_palette_pixel_shaders[GX_TL_IA8] = GetConvertShader12(std::string("IA8")); - m_palette_pixel_shaders[GX_TL_RGB565] = GetConvertShader12(std::string("RGB565")); - m_palette_pixel_shaders[GX_TL_RGB5A3] = GetConvertShader12(std::string("RGB5A3")); + m_palette_pixel_shaders[GX_TL_IA8] = GetConvertShader12(std::string("IA8")); + m_palette_pixel_shaders[GX_TL_RGB565] = GetConvertShader12(std::string("RGB565")); + m_palette_pixel_shaders[GX_TL_RGB5A3] = GetConvertShader12(std::string("RGB5A3")); - m_palette_stream_buffer = std::make_unique<D3DStreamBuffer>(sizeof(u16) * 256 * 1024, sizeof(u16) * 256 * 1024 * 16, nullptr); + m_palette_stream_buffer = std::make_unique<D3DStreamBuffer>( + sizeof(u16) * 256 * 1024, sizeof(u16) * 256 * 1024 * 16, nullptr); - // Right now, there are only two variants of palette_uniform data. So, we'll just create an upload heap to permanently store both of these. - CheckHR( - D3D::device12->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(((16 + 255) & ~255) * 2), // Constant Buffers have to be 256b aligned. "* 2" to create for two sets of data. - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(&m_palette_uniform_buffer) - ) - ); + // Right now, there are only two variants of palette_uniform data. So, we'll just create an upload + // heap to permanently store both of these. + CheckHR(D3D::device12->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer( + ((16 + 255) & ~255) * + 2), // Constant Buffers have to be 256b aligned. "* 2" to create for two sets of data. + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, IID_PPV_ARGS(&m_palette_uniform_buffer))); - D3D::SetDebugObjectName12(m_palette_uniform_buffer, "a constant buffer used in TextureCache::ConvertTexture"); + D3D::SetDebugObjectName12(m_palette_uniform_buffer, + "a constant buffer used in TextureCache::ConvertTexture"); - // Temporarily repurpose m_palette_stream_buffer as a copy source to populate initial data here. - m_palette_stream_buffer->AllocateSpaceInBuffer(256 * 2, 256); + // Temporarily repurpose m_palette_stream_buffer as a copy source to populate initial data here. + m_palette_stream_buffer->AllocateSpaceInBuffer(256 * 2, 256); - u8* upload_heap_data_location = reinterpret_cast<u8*>(m_palette_stream_buffer->GetCPUAddressOfCurrentAllocation()); + u8* upload_heap_data_location = + reinterpret_cast<u8*>(m_palette_stream_buffer->GetCPUAddressOfCurrentAllocation()); - memset(upload_heap_data_location, 0, 256 * 2); + memset(upload_heap_data_location, 0, 256 * 2); - float paramsFormatZero[4] = { 15.f }; - float paramsFormatNonzero[4] = { 255.f }; + float paramsFormatZero[4] = {15.f}; + float paramsFormatNonzero[4] = {255.f}; - memcpy(upload_heap_data_location, paramsFormatZero, sizeof(paramsFormatZero)); - memcpy(upload_heap_data_location + 256, paramsFormatNonzero, sizeof(paramsFormatNonzero)); + memcpy(upload_heap_data_location, paramsFormatZero, sizeof(paramsFormatZero)); + memcpy(upload_heap_data_location + 256, paramsFormatNonzero, sizeof(paramsFormatNonzero)); - D3D::current_command_list->CopyBufferRegion(m_palette_uniform_buffer, 0, m_palette_stream_buffer->GetBuffer(), m_palette_stream_buffer->GetOffsetOfCurrentAllocation(), 256 * 2); + D3D::current_command_list->CopyBufferRegion( + m_palette_uniform_buffer, 0, m_palette_stream_buffer->GetBuffer(), + m_palette_stream_buffer->GetOffsetOfCurrentAllocation(), 256 * 2); - DX12::D3D::ResourceBarrier(D3D::current_command_list, m_palette_uniform_buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, 0); + DX12::D3D::ResourceBarrier(D3D::current_command_list, m_palette_uniform_buffer, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, 0); } TextureCache::~TextureCache() { - s_encoder->Shutdown(); - s_encoder.reset(); + s_encoder->Shutdown(); + s_encoder.reset(); - s_efb_copy_stream_buffer.reset(); + s_efb_copy_stream_buffer.reset(); - if (s_texture_cache_entry_readback_buffer) - { - // Safe to destroy the readback buffer immediately, as the only time it's used is blocked until completion. - s_texture_cache_entry_readback_buffer->Release(); - s_texture_cache_entry_readback_buffer = nullptr; - s_texture_cache_entry_readback_buffer_size = 0; - } + if (s_texture_cache_entry_readback_buffer) + { + // Safe to destroy the readback buffer immediately, as the only time it's used is blocked until + // completion. + s_texture_cache_entry_readback_buffer->Release(); + s_texture_cache_entry_readback_buffer = nullptr; + s_texture_cache_entry_readback_buffer_size = 0; + } - D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_palette_uniform_buffer); + D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_palette_uniform_buffer); } void TextureCache::BindTextures() { - unsigned int last_texture = 0; - for (unsigned int i = 0; i < 8; ++i) - { - if (bound_textures[i] != nullptr) - { - last_texture = i; - } - } - - if (last_texture == 0 && bound_textures[0] != nullptr) - { - DX12::D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, reinterpret_cast<TCacheEntry*>(bound_textures[0])->m_texture_srv_gpu_handle); - return; - } - - // If more than one texture, allocate space for group. - D3D12_CPU_DESCRIPTOR_HANDLE s_group_base_texture_cpu_handle; - D3D12_GPU_DESCRIPTOR_HANDLE s_group_base_texture_gpu_handle; - DX12::D3D::gpu_descriptor_heap_mgr->AllocateGroup(&s_group_base_texture_cpu_handle, 8, &s_group_base_texture_gpu_handle, nullptr, true); - - for (unsigned int stage = 0; stage < 8; stage++) - { - if (bound_textures[stage] != nullptr) - { - D3D12_CPU_DESCRIPTOR_HANDLE textureDestDescriptor; - textureDestDescriptor.ptr = s_group_base_texture_cpu_handle.ptr + stage * D3D::resource_descriptor_size; - - DX12::D3D::device12->CopyDescriptorsSimple( - 1, - textureDestDescriptor, - reinterpret_cast<TCacheEntry*>(bound_textures[stage])->m_texture_srv_gpu_handle_cpu_shadow, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } - else - { - D3D12_CPU_DESCRIPTOR_HANDLE nullDestDescriptor; - nullDestDescriptor.ptr = s_group_base_texture_cpu_handle.ptr + stage * D3D::resource_descriptor_size; - - DX12::D3D::device12->CopyDescriptorsSimple( - 1, - nullDestDescriptor, - DX12::D3D::null_srv_cpu_shadow, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } - } - - // Actually bind the textures. - DX12::D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, s_group_base_texture_gpu_handle); + unsigned int last_texture = 0; + for (unsigned int i = 0; i < 8; ++i) + { + if (bound_textures[i] != nullptr) + { + last_texture = i; + } + } + + if (last_texture == 0 && bound_textures[0] != nullptr) + { + DX12::D3D::current_command_list->SetGraphicsRootDescriptorTable( + DESCRIPTOR_TABLE_PS_SRV, + reinterpret_cast<TCacheEntry*>(bound_textures[0])->m_texture_srv_gpu_handle); + return; + } + + // If more than one texture, allocate space for group. + D3D12_CPU_DESCRIPTOR_HANDLE s_group_base_texture_cpu_handle; + D3D12_GPU_DESCRIPTOR_HANDLE s_group_base_texture_gpu_handle; + DX12::D3D::gpu_descriptor_heap_mgr->AllocateGroup( + &s_group_base_texture_cpu_handle, 8, &s_group_base_texture_gpu_handle, nullptr, true); + + for (unsigned int stage = 0; stage < 8; stage++) + { + if (bound_textures[stage] != nullptr) + { + D3D12_CPU_DESCRIPTOR_HANDLE textureDestDescriptor; + textureDestDescriptor.ptr = + s_group_base_texture_cpu_handle.ptr + stage * D3D::resource_descriptor_size; + + DX12::D3D::device12->CopyDescriptorsSimple( + 1, textureDestDescriptor, reinterpret_cast<TCacheEntry*>(bound_textures[stage]) + ->m_texture_srv_gpu_handle_cpu_shadow, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + else + { + D3D12_CPU_DESCRIPTOR_HANDLE nullDestDescriptor; + nullDestDescriptor.ptr = + s_group_base_texture_cpu_handle.ptr + stage * D3D::resource_descriptor_size; + + DX12::D3D::device12->CopyDescriptorsSimple(1, nullDestDescriptor, + DX12::D3D::null_srv_cpu_shadow, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + } + + // Actually bind the textures. + DX12::D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, + s_group_base_texture_gpu_handle); } - } |
