diff --git a/src/util/d3d12_device.cpp b/src/util/d3d12_device.cpp index ed9b1edc0..101241b56 100644 --- a/src/util/d3d12_device.cpp +++ b/src/util/d3d12_device.cpp @@ -2228,7 +2228,7 @@ void D3D12Device::UnbindTextureBuffer(D3D12TextureBuffer* buf) m_dirty_flags |= DIRTY_FLAG_TEXTURES; } -void D3D12Device::RenderTextureMipmap(D3D12Texture* texture, u32 dst_level, u32 dst_width, u32 dst_height, +void D3D12Device::RenderTextureMipmap(D3D12Texture* texture, u32 layer, u32 dst_level, u32 dst_width, u32 dst_height, u32 src_level, u32 src_width, u32 src_height) { ComPtr& pipeline = m_mipmap_render_pipelines[static_cast(texture->GetFormat())]; @@ -2304,29 +2304,46 @@ void D3D12Device::RenderTextureMipmap(D3D12Texture* texture, u32 dst_level, u32 } // Setup views. This will be a partial view for the SRV. - const D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {.Format = texture->GetDXGIFormat(), - .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D, - .Texture2D = {.MipSlice = dst_level, .PlaneSlice = 0}}; + const D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = + (texture->GetLayers() > 1) ? + D3D12_RENDER_TARGET_VIEW_DESC{ + .Format = texture->GetDXGIFormat(), + .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY, + .Texture2DArray = {.MipSlice = dst_level, .FirstArraySlice = layer, .ArraySize = 1, .PlaneSlice = 0}} : + D3D12_RENDER_TARGET_VIEW_DESC{.Format = texture->GetDXGIFormat(), + .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D, + .Texture2D = {.MipSlice = dst_level, .PlaneSlice = 0}}; m_device->CreateRenderTargetView(texture->GetResource(), &rtv_desc, rtv_handle); - const D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = { - .Format = texture->GetDXGIFormat(), - .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D, - .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, - .Texture2D = {.MostDetailedMip = src_level, .MipLevels = 1, .PlaneSlice = 0, .ResourceMinLODClamp = 0.0f}}; + const D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = + (texture->GetLayers() > 1) ? + D3D12_SHADER_RESOURCE_VIEW_DESC{.Format = texture->GetDXGIFormat(), + .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY, + .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, + .Texture2DArray = {.MostDetailedMip = src_level, + .MipLevels = 1, + .FirstArraySlice = layer, + .ArraySize = 1, + .PlaneSlice = 0, + .ResourceMinLODClamp = 0.0f}} : + D3D12_SHADER_RESOURCE_VIEW_DESC{ + .Format = texture->GetDXGIFormat(), + .ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D, + .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, + .Texture2D = {.MostDetailedMip = src_level, .MipLevels = 1, .PlaneSlice = 0, .ResourceMinLODClamp = 0.0f}}; m_device->CreateShaderResourceView(texture->GetResource(), &srv_desc, srv_handle); // *now* we don't have to worry about running out of anything. ID3D12GraphicsCommandList4* cmdlist = GetCommandList(); if (texture->GetResourceState() != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) { - texture->TransitionSubresourceToState(cmdlist, src_level, texture->GetResourceState(), - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + texture->TransitionSubresourceToState(cmdlist, texture->CalculateSubresource(layer, src_level), + texture->GetResourceState(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); } if (texture->GetResourceState() != D3D12_RESOURCE_STATE_RENDER_TARGET) { - texture->TransitionSubresourceToState(cmdlist, dst_level, texture->GetResourceState(), - D3D12_RESOURCE_STATE_RENDER_TARGET); + texture->TransitionSubresourceToState(cmdlist, texture->CalculateSubresource(layer, dst_level), + texture->GetResourceState(), D3D12_RESOURCE_STATE_RENDER_TARGET); } const D3D12_RENDER_PASS_RENDER_TARGET_DESC rt_desc = { @@ -2351,13 +2368,13 @@ void D3D12Device::RenderTextureMipmap(D3D12Texture* texture, u32 dst_level, u32 if (texture->GetResourceState() != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) { - texture->TransitionSubresourceToState(cmdlist, src_level, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - texture->GetResourceState()); + texture->TransitionSubresourceToState(cmdlist, texture->CalculateSubresource(layer, src_level), + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, texture->GetResourceState()); } if (texture->GetResourceState() != D3D12_RESOURCE_STATE_RENDER_TARGET) { - texture->TransitionSubresourceToState(cmdlist, dst_level, D3D12_RESOURCE_STATE_RENDER_TARGET, - texture->GetResourceState()); + texture->TransitionSubresourceToState(cmdlist, texture->CalculateSubresource(layer, dst_level), + D3D12_RESOURCE_STATE_RENDER_TARGET, texture->GetResourceState()); } // Must destroy after current cmdlist. diff --git a/src/util/d3d12_device.h b/src/util/d3d12_device.h index 6be77fb72..4677c47ee 100644 --- a/src/util/d3d12_device.h +++ b/src/util/d3d12_device.h @@ -198,8 +198,8 @@ public: void UnbindTexture(D3D12Texture* tex); void UnbindTextureBuffer(D3D12TextureBuffer* buf); - void RenderTextureMipmap(D3D12Texture* texture, u32 dst_level, u32 dst_width, u32 dst_height, u32 src_level, - u32 src_width, u32 src_height); + void RenderTextureMipmap(D3D12Texture* texture, u32 layer, u32 dst_level, u32 dst_width, u32 dst_height, + u32 src_level, u32 src_width, u32 src_height); protected: bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, @@ -271,8 +271,8 @@ private: Error* error); bool CreateDSVDescriptor(ID3D12Resource* resource, u32 samples, DXGI_FORMAT format, D3D12DescriptorHandle* dh, Error* error); - bool CreateUAVDescriptor(ID3D12Resource* resource, u32 samples, DXGI_FORMAT format, D3D12DescriptorHandle* dh, - Error* error); + bool CreateUAVDescriptor(ID3D12Resource* resource, u32 layers, u32 samples, DXGI_FORMAT format, + D3D12DescriptorHandle* dh, Error* error); bool IsRenderTargetBound(const GPUTexture* tex) const; diff --git a/src/util/d3d12_texture.cpp b/src/util/d3d12_texture.cpp index 32c14b936..ec00c7466 100644 --- a/src/util/d3d12_texture.cpp +++ b/src/util/d3d12_texture.cpp @@ -50,7 +50,7 @@ std::unique_ptr D3D12Device::CreateTexture(u32 width, u32 height, u3 desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; desc.Width = width; desc.Height = height; - desc.DepthOrArraySize = 1; + desc.DepthOrArraySize = static_cast(layers); desc.MipLevels = static_cast(levels); desc.Format = fm.resource_format; desc.SampleDesc.Count = samples; @@ -161,7 +161,7 @@ std::unique_ptr D3D12Device::CreateTexture(u32 width, u32 height, u3 if ((flags & GPUTexture::Flags::AllowBindAsImage) != GPUTexture::Flags::None) { - if (!CreateUAVDescriptor(resource.Get(), samples, fm.srv_format, &uav_descriptor, error)) + if (!CreateUAVDescriptor(resource.Get(), layers, samples, fm.srv_format, &uav_descriptor, error)) { if (write_descriptor_type != D3D12Texture::WriteDescriptorType::None) m_descriptor_heap_manager.Free(&write_descriptor); @@ -264,7 +264,7 @@ bool D3D12Device::CreateDSVDescriptor(ID3D12Resource* resource, u32 samples, DXG return true; } -bool D3D12Device::CreateUAVDescriptor(ID3D12Resource* resource, u32 samples, DXGI_FORMAT format, +bool D3D12Device::CreateUAVDescriptor(ID3D12Resource* resource, u32 layers, u32 samples, DXGI_FORMAT format, D3D12DescriptorHandle* dh, Error* error) { if (!m_descriptor_heap_manager.Allocate(dh)) @@ -274,7 +274,12 @@ bool D3D12Device::CreateUAVDescriptor(ID3D12Resource* resource, u32 samples, DXG } DebugAssert(samples == 1); - const D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {format, D3D12_UAV_DIMENSION_TEXTURE2D, {}}; + const D3D12_UNORDERED_ACCESS_VIEW_DESC desc = + (layers > 1) ? D3D12_UNORDERED_ACCESS_VIEW_DESC{.Format = format, + .ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY, + .Texture2DArray = {0u, 0u, layers, 0u}} : + D3D12_UNORDERED_ACCESS_VIEW_DESC{ + .Format = format, .ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D, .Texture2D = {}}; m_device->CreateUnorderedAccessView(resource, nullptr, &desc, dh->cpu_handle); return true; } @@ -576,8 +581,8 @@ void D3D12Texture::GenerateMipmaps() const u32 dst_width = std::max(m_width >> dst_level, 1u); const u32 dst_height = std::max(m_height >> dst_level, 1u); - D3D12Device::GetInstance().RenderTextureMipmap(this, dst_level, dst_width, dst_height, src_level, src_width, - src_height); + D3D12Device::GetInstance().RenderTextureMipmap(this, layer, dst_level, dst_width, dst_height, src_level, + src_width, src_height); } }