diff --git a/src/backend/dx11/shaders/copy.hlsl b/src/backend/dx11/shaders/copy.hlsl index c0bd27853fb..a239caf8661 100644 --- a/src/backend/dx11/shaders/copy.hlsl +++ b/src/backend/dx11/shaders/copy.hlsl @@ -1,15 +1,200 @@ -cbuffer BufferImageCopy : register(b0) { - uint2 BufferSize; - uint2 ImageOffset; +struct BufferCopy { + uint4 SrcDst; }; -StructuredBuffer CopySrc : register(t0); -RWTexture2D CopyDst : register(u0); +struct ImageCopy { + uint4 Src; + uint4 Dst; +}; + +struct BufferImageCopy { + // x=offset, yz=size + uint4 BufferVars; + uint4 ImageOffset; + uint4 ImageExtent; +}; + +cbuffer CopyConstants : register(b0) { + BufferCopy BufferCopies; + ImageCopy ImageCopies; + BufferImageCopy BufferImageCopies; +}; + +uint2 GetImageDst(uint3 dispatch_thread_id) +{ + return BufferImageCopies.ImageOffset.xy + dispatch_thread_id.xy; +} + +uint2 GetImageSrc(uint3 dispatch_thread_id) +{ + return BufferImageCopies.ImageOffset.xy + dispatch_thread_id.xy; +} + +uint GetBufferDst(uint3 dispatch_thread_id) +{ + return BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y; +} + +uint GetBufferSrc(uint3 dispatch_thread_id) +{ + return BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y; +} + +uint Uint4ToUint(uint4 data) +{ + data.x = min(data.x, 0x000000ff); + data.y = min(data.y, 0x000000ff); + data.z = min(data.z, 0x000000ff); + data.w = min(data.w, 0x000000ff); + + uint output = (data.x | + (data.y << 8) | + (data.z << 16) | + (data.w << 24)); + + return output; +} + +uint4 UintToUint4(uint data) +{ + return uint4((data & 0xff000000) >> 24, (data & 0xff0000) >> 16, (data & 0xff00) >> 8, data & 0xff); +} + +uint2 UintToUint2(uint data) +{ + return uint2((data >> 16) & 0x0000ffff, data & 0x0000ffff); +} + +uint Uint2ToUint(uint2 data) +{ + data.x = min(data.x, 0x0000ffff); + data.y = min(data.y, 0x0000ffff); + + uint output = (data.x | + (data.y << 16)); + + return output; +} + +// Buffers are always R32-aligned +StructuredBuffer BufferCopySrc : register(t0); +RWBuffer BufferCopyDst: register(u0); + +// R32 +Texture2D ImageCopySrcR32 : register(t0); +RWTexture2D ImageCopyDstR32 : register(u0); + +// TODO: correct, but slow +[numthreads(1, 1, 1)] +void cs_copy_buffer_image2d_r32(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint2 dst_idx = GetImageDst(dispatch_thread_id); + uint src_idx = GetBufferSrc(dispatch_thread_id); + + ImageCopyDstR32[dst_idx] = BufferCopySrc[src_idx]; +} + +[numthreads(1, 1, 1)] +void cs_copy_image2d_r32_buffer(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint dst_idx = GetBufferDst(dispatch_thread_id); + uint2 src_idx = GetImageSrc(dispatch_thread_id); + + BufferCopyDst[dst_idx] = ImageCopySrcR32[src_idx]; +} + +// R16G16 +Texture2D ImageCopySrcR16G16 : register(t0); +RWTexture2D ImageCopyDstR16G16 : register(u0); // TODO: correct, but slow [numthreads(1, 1, 1)] -void cs_copy_buffer_image_2d(uint3 dispatch_thread_id : SV_DispatchThreadID) { - uint2 idx = ImageOffset + dispatch_thread_id.xy; +void cs_copy_buffer_image2d_r16g16(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint2 dst_idx = GetImageDst(dispatch_thread_id); + uint src_idx = GetBufferSrc(dispatch_thread_id); + + ImageCopyDstR16G16[dst_idx] = UintToUint2(BufferCopySrc[src_idx]); +} + +[numthreads(1, 1, 1)] +void cs_copy_image2d_r16g16_buffer(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint dst_idx = GetBufferDst(dispatch_thread_id); + uint2 src_idx = GetImageSrc(dispatch_thread_id); + + BufferCopyDst[dst_idx] = Uint2ToUint(ImageCopySrcR16G16[src_idx].yx); +} + +// R16 +Texture2D ImageCopySrcR16 : register(t0); +RWTexture2D ImageCopyDstR16 : register(u0); + +[numthreads(1, 1, 1)] +void cs_copy_buffer_image2d_r16(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint src_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 2; + + uint2 data = UintToUint2(BufferCopySrc[src_idx]); + + ImageCopyDstR16[GetImageDst(uint3(2, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))] = data.y; + ImageCopyDstR16[GetImageDst(uint3(2, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))] = data.x; +} + +[numthreads(1, 1, 1)] +void cs_copy_image2d_r16_buffer(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint dst_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 2; + + uint upper = ImageCopySrcR16[GetImageSrc(uint3(2, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))]; + uint lower = ImageCopySrcR16[GetImageSrc(uint3(2, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))]; + uint data = Uint2ToUint(uint2(upper, lower)); + + BufferCopyDst[dst_idx] = data; +} + +// R8G8 +Texture2D ImageCopySrcR8G8 : register(t0); +RWTexture2D ImageCopyDstR8G8 : register(u0); + +[numthreads(1, 1, 1)] +void cs_copy_buffer_image2d_r8g8(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint src_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 2; + + uint4 data = UintToUint4(BufferCopySrc[src_idx]); + + ImageCopyDstR8G8[GetImageDst(uint3(2, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))] = data.xy; + ImageCopyDstR8G8[GetImageDst(uint3(2, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))] = data.zw; +} + +[numthreads(1, 1, 1)] +void cs_copy_image2d_r8g8_buffer(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint dst_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 2; + + uint2 lower = ImageCopySrcR8G8[GetImageSrc(uint3(2, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))].yx; + uint2 upper = ImageCopySrcR8G8[GetImageSrc(uint3(2, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))].yx; + uint data = Uint4ToUint(uint4(upper.x, upper.y, lower.x, lower.y)); + + BufferCopyDst[dst_idx] = data; +} + +// R8 +Texture2D ImageCopySrcR8 : register(t0); +RWTexture2D ImageCopyDstR8 : register(u0); + +[numthreads(1, 1, 1)] +void cs_copy_buffer_image2d_r8(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint src_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 4; + uint4 data = UintToUint4(BufferCopySrc[src_idx]); + + ImageCopyDstR8[GetImageDst(uint3(4, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))] = data.w; + ImageCopyDstR8[GetImageDst(uint3(4, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))] = data.z; + ImageCopyDstR8[GetImageDst(uint3(4, 1, 0) * dispatch_thread_id + uint3(2, 0, 0))] = data.y; + ImageCopyDstR8[GetImageDst(uint3(4, 1, 0) * dispatch_thread_id + uint3(3, 0, 0))] = data.x; +} + +[numthreads(1, 1, 1)] +void cs_copy_image2d_r8_buffer(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint dst_idx = BufferImageCopies.BufferVars.x + dispatch_thread_id.x + dispatch_thread_id.y * BufferImageCopies.BufferVars.y / 4; + + uint src_1 = ImageCopySrcR8[GetImageSrc(uint3(4, 1, 0) * dispatch_thread_id + uint3(0, 0, 0))]; + uint src_2 = ImageCopySrcR8[GetImageSrc(uint3(4, 1, 0) * dispatch_thread_id + uint3(1, 0, 0))]; + uint src_3 = ImageCopySrcR8[GetImageSrc(uint3(4, 1, 0) * dispatch_thread_id + uint3(2, 0, 0))]; + uint src_4 = ImageCopySrcR8[GetImageSrc(uint3(4, 1, 0) * dispatch_thread_id + uint3(3, 0, 0))]; - CopyDst[idx] = CopySrc[BufferSize.x + idx.x + idx.y * BufferSize.y]; + BufferCopyDst[dst_idx] = Uint4ToUint(uint4(src_1, src_2, src_3, src_4)); } diff --git a/src/backend/dx11/src/conv.rs b/src/backend/dx11/src/conv.rs index c91d4718255..a723b211be0 100644 --- a/src/backend/dx11/src/conv.rs +++ b/src/backend/dx11/src/conv.rs @@ -24,62 +24,84 @@ pub fn map_index_type(ty: IndexType) -> DXGI_FORMAT { } } -pub fn typeless_format(format: DXGI_FORMAT) -> Option { +pub fn typeless_format(format: DXGI_FORMAT) -> Option<(DXGI_FORMAT, DXGI_FORMAT)> { match format { DXGI_FORMAT_R8G8B8A8_UNORM | DXGI_FORMAT_R8G8B8A8_SNORM | DXGI_FORMAT_R8G8B8A8_UINT | DXGI_FORMAT_R8G8B8A8_SINT | - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB => Some(DXGI_FORMAT_R8G8B8A8_TYPELESS), + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB => Some((DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UINT)), // ?` DXGI_FORMAT_B8G8R8A8_UNORM | - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB => Some(DXGI_FORMAT_B8G8R8A8_TYPELESS), + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB => Some((DXGI_FORMAT_B8G8R8A8_TYPELESS, DXGI_FORMAT_R32_UINT)), DXGI_FORMAT_R8_UNORM | DXGI_FORMAT_R8_SNORM | DXGI_FORMAT_R8_UINT | - DXGI_FORMAT_R8_SINT => Some(DXGI_FORMAT_R8_TYPELESS), + DXGI_FORMAT_R8_SINT => Some((DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UINT)), DXGI_FORMAT_R8G8_UNORM | DXGI_FORMAT_R8G8_SNORM | DXGI_FORMAT_R8G8_UINT | - DXGI_FORMAT_R8G8_SINT => Some(DXGI_FORMAT_R8G8_TYPELESS), + DXGI_FORMAT_R8G8_SINT => Some((DXGI_FORMAT_R8G8_TYPELESS, DXGI_FORMAT_R8G8_UINT)), DXGI_FORMAT_R16_UNORM | DXGI_FORMAT_R16_SNORM | DXGI_FORMAT_R16_UINT | DXGI_FORMAT_R16_SINT | - DXGI_FORMAT_R16_FLOAT => Some(DXGI_FORMAT_R16_TYPELESS), + DXGI_FORMAT_R16_FLOAT => Some((DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UINT)), DXGI_FORMAT_R16G16_UNORM | DXGI_FORMAT_R16G16_SNORM | DXGI_FORMAT_R16G16_UINT | DXGI_FORMAT_R16G16_SINT | - DXGI_FORMAT_R16G16_FLOAT => Some(DXGI_FORMAT_R16G16_TYPELESS), + DXGI_FORMAT_R16G16_FLOAT => Some((DXGI_FORMAT_R16G16_TYPELESS, DXGI_FORMAT_R16G16_UINT)), DXGI_FORMAT_R16G16B16A16_UNORM | DXGI_FORMAT_R16G16B16A16_SNORM | DXGI_FORMAT_R16G16B16A16_UINT | DXGI_FORMAT_R16G16B16A16_SINT | - DXGI_FORMAT_R16G16B16A16_FLOAT => Some(DXGI_FORMAT_R16G16B16A16_TYPELESS), + DXGI_FORMAT_R16G16B16A16_FLOAT => Some((DXGI_FORMAT_R16G16B16A16_TYPELESS, DXGI_FORMAT_R16G16B16A16_UINT)), DXGI_FORMAT_D32_FLOAT | DXGI_FORMAT_R32_UINT | DXGI_FORMAT_R32_SINT | - DXGI_FORMAT_R32_FLOAT => Some(DXGI_FORMAT_R32_TYPELESS), + DXGI_FORMAT_R32_FLOAT => Some((DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_UINT)), DXGI_FORMAT_R32G32_UINT | DXGI_FORMAT_R32G32_SINT | - DXGI_FORMAT_R32G32_FLOAT => Some(DXGI_FORMAT_R32G32_TYPELESS), + DXGI_FORMAT_R32G32_FLOAT => Some((DXGI_FORMAT_R32G32_TYPELESS, DXGI_FORMAT_R32G32_UINT)), DXGI_FORMAT_R32G32B32_UINT | DXGI_FORMAT_R32G32B32_SINT | - DXGI_FORMAT_R32G32B32_FLOAT => Some(DXGI_FORMAT_R32G32B32_TYPELESS), + DXGI_FORMAT_R32G32B32_FLOAT => Some((DXGI_FORMAT_R32G32B32_TYPELESS, DXGI_FORMAT_R32G32B32_UINT)), DXGI_FORMAT_R32G32B32A32_UINT | DXGI_FORMAT_R32G32B32A32_SINT | - DXGI_FORMAT_R32G32B32A32_FLOAT => Some(DXGI_FORMAT_R32G32B32A32_TYPELESS), + DXGI_FORMAT_R32G32B32A32_FLOAT => Some((DXGI_FORMAT_R32G32B32A32_TYPELESS, DXGI_FORMAT_R32G32B32A32_UINT)), + + DXGI_FORMAT_BC1_UNORM | + DXGI_FORMAT_BC1_UNORM_SRGB => Some((DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_R32_UINT)), + + DXGI_FORMAT_BC2_UNORM | + DXGI_FORMAT_BC2_UNORM_SRGB => Some((DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_R32_UINT)), + + DXGI_FORMAT_BC3_UNORM | + DXGI_FORMAT_BC3_UNORM_SRGB => Some((DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_R32_UINT)), + + DXGI_FORMAT_BC4_UNORM | + DXGI_FORMAT_BC4_SNORM => Some((DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_R32_UINT)), + + DXGI_FORMAT_BC5_UNORM | + DXGI_FORMAT_BC5_SNORM => Some((DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_R32_UINT)), + + DXGI_FORMAT_BC6H_UF16 | + DXGI_FORMAT_BC6H_SF16 => Some((DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_R32_UINT)), + + // TODO: srgb craziness + DXGI_FORMAT_BC7_UNORM | + DXGI_FORMAT_BC7_UNORM_SRGB => Some((DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM)), /*R5g6b5Unorm => DXGI_FORMAT_B5G6R5_UNORM, R5g5b5a1Unorm => DXGI_FORMAT_B5G5R5A1_UNORM, diff --git a/src/backend/dx11/src/device.rs b/src/backend/dx11/src/device.rs index 1d4e043387f..04785cea565 100644 --- a/src/backend/dx11/src/device.rs +++ b/src/backend/dx11/src/device.rs @@ -18,9 +18,9 @@ use std::ptr; use { Backend, Buffer, BufferView, CommandPool, ComputePipeline, DescriptorPool, DescriptorSetLayout, - Fence, Framebuffer, GraphicsPipeline, Image, ImageView, InternalBuffer, Memory, PipelineLayout, - QueryPool, RenderPass, Sampler, Semaphore, ShaderModule, Surface, Swapchain, UnboundBuffer, - UnboundImage, ViewInfo, + Fence, Framebuffer, GraphicsPipeline, Image, ImageView, InternalBuffer, InternalImage, Memory, + PipelineLayout, QueryPool, RenderPass, Sampler, Semaphore, ShaderModule, Surface, Swapchain, + UnboundBuffer, UnboundImage, ViewInfo, }; use {conv, internal, shader}; @@ -29,19 +29,23 @@ pub struct Device { raw: ComPtr, pub(crate) context: ComPtr, memory_properties: hal::MemoryProperties, - pub(crate) internal: internal::BufferImageCopy + pub(crate) internal: internal::Internal } unsafe impl Send for Device { } unsafe impl Sync for Device { } impl Device { + pub fn as_raw(&self) -> *mut d3d11::ID3D11Device { + self.raw.as_raw() + } + pub fn new(device: ComPtr, context: ComPtr, memory_properties: hal::MemoryProperties) -> Self { Device { raw: device.clone(), context, memory_properties, - internal: internal::BufferImageCopy::new(device) + internal: internal::Internal::new(device) } } @@ -320,22 +324,22 @@ impl hal::Device for Device { mem_type: hal::MemoryTypeId, size: u64, ) -> Result { - let host_buffer = if mem_type.0 == 1 { + let working_buffer = if mem_type.0 == 1 { let desc = d3d11::D3D11_BUFFER_DESC { - ByteWidth: size as _, + ByteWidth: 65535, Usage: d3d11::D3D11_USAGE_STAGING, BindFlags: 0, - CPUAccessFlags: d3d11::D3D11_CPU_ACCESS_WRITE, + CPUAccessFlags: d3d11::D3D11_CPU_ACCESS_READ | d3d11::D3D11_CPU_ACCESS_WRITE, MiscFlags:0, StructureByteStride: 0, }; - let mut host_buffer = ptr::null_mut(); + let mut working_buffer = ptr::null_mut(); let hr = unsafe { self.raw.CreateBuffer( &desc, ptr::null_mut(), - &mut host_buffer as *mut *mut _ as *mut *mut _ + &mut working_buffer as *mut *mut _ as *mut *mut _ ) }; @@ -343,7 +347,7 @@ impl hal::Device for Device { return Err(device::OutOfMemory); } - Some(unsafe { ComPtr::from_raw(host_buffer) }) + Some(unsafe { ComPtr::from_raw(working_buffer) }) } else { None }; @@ -351,9 +355,11 @@ impl hal::Device for Device { Ok(Memory { properties: self.memory_properties.memory_types[mem_type.0].properties, size, - flushes: RefCell::new(Vec::new()), + mapped_ptr: RefCell::new(None), + host_visible: Some(RefCell::new(Vec::with_capacity(size as usize))), + working_buffer, local_buffers: RefCell::new(Vec::new()), - host_buffer + local_images: RefCell::new(Vec::new()), }) } @@ -368,7 +374,8 @@ impl hal::Device for Device { } fn destroy_command_pool(&self, _pool: CommandPool) { - unimplemented!() + // TODO: + // unimplemented!() } fn create_render_pass<'a, IA, IS, ID>( @@ -614,9 +621,41 @@ impl hal::Device for Device { None }; + let uav = if unbound_buffer.usage.contains(buffer::Usage::TRANSFER_DST) { + let mut desc = unsafe { mem::zeroed::() }; + desc.Format = dxgiformat::DXGI_FORMAT_R32_UINT; + desc.ViewDimension = d3d11::D3D11_UAV_DIMENSION_BUFFER; + unsafe { + *desc.u.Buffer_mut() = d3d11::D3D11_BUFFER_UAV { + FirstElement: 0, + NumElements: unbound_buffer.size as u32 / 4, + Flags: 0 + }; + }; + + let mut uav = ptr::null_mut(); + let hr = unsafe { + self.raw.CreateUnorderedAccessView( + raw.as_raw() as *mut _, + &desc, + &mut uav as *mut *mut _ as *mut *mut _ + ) + }; + + if !winerror::SUCCEEDED(hr) { + // TODO: better errors + return Err(device::BindError::WrongMemory); + } + + Some(uav) + } else { + None + }; + let buffer = InternalBuffer { raw: raw.into_raw(), - srv + srv, + uav, }; let range = offset..unbound_buffer.size; @@ -721,7 +760,7 @@ impl hal::Device for Device { }; let dxgi_format = conv::map_format(image.format).unwrap(); - let typeless_format = conv::typeless_format(dxgi_format).unwrap(); + let (typeless_format, typed_raw_format) = conv::typeless_format(dxgi_format).unwrap(); let (resource, levels) = match image.kind { image::Kind::D2(width, height, layers, _) => { @@ -762,9 +801,10 @@ impl hal::Device for Device { _ => unimplemented!() }; + // TODO: view dimensions let uav = if image.usage.contains(image::Usage::TRANSFER_DST) { let mut desc = unsafe { mem::zeroed::() }; - desc.Format = dxgiformat::DXGI_FORMAT_R32_UINT; + desc.Format = typed_raw_format; desc.ViewDimension = d3d11::D3D11_UAV_DIMENSION_TEXTURE2D; let mut uav = ptr::null_mut(); @@ -779,13 +819,41 @@ impl hal::Device for Device { if !winerror::SUCCEEDED(hr) { // TODO: better errors return Err(device::BindError::WrongMemory); - } else { - Some(unsafe { ComPtr::from_raw(uav) }) } + + Some(unsafe { ComPtr::from_raw(uav) }) } else { None }; + let srv = if image.usage.contains(image::Usage::TRANSFER_SRC) { + let mut desc = unsafe { mem::zeroed::() }; + desc.Format = typed_raw_format; + desc.ViewDimension = d3dcommon::D3D11_SRV_DIMENSION_TEXTURE2D; + // TODO: + *unsafe{ desc.u.Texture2D_mut() } = d3d11::D3D11_TEX2D_SRV { + MostDetailedMip: 0, + MipLevels: 1, + }; + + let mut srv = ptr::null_mut(); + let hr = unsafe { + self.raw.CreateShaderResourceView( + resource, + &desc, + &mut srv as *mut *mut _ as *mut *mut _ + ) + }; + + if !winerror::SUCCEEDED(hr) { + // TODO: better errors + return Err(device::BindError::WrongMemory); + } + + Some(unsafe { ComPtr::from_raw(srv) }) + } else { + None + }; let rtv = if image.usage.contains(image::Usage::COLOR_ATTACHMENT) { let mut rtv = ptr::null_mut(); @@ -799,24 +867,30 @@ impl hal::Device for Device { if !winerror::SUCCEEDED(hr) { return Err(device::BindError::WrongMemory); - } else { - Some(unsafe { ComPtr::from_raw(rtv) }) } + + Some(unsafe { ComPtr::from_raw(rtv) }) } else { None }; + let internal = InternalImage { + raw: resource, + srv, + uav, + rtv, + }; + Ok(Image { - resource: resource, kind: image.kind, usage: image.usage, storage_flags: image.flags, dxgi_format, + typed_raw_format, bytes_per_block: bytes_per_block, block_dim: block_dim, num_levels: levels as _, - uav, - rtv //unsafe { ComPtr::from_raw(rtv) } + internal, }) } @@ -829,7 +903,7 @@ impl hal::Device for Device { range: image::SubresourceRange, ) -> Result { let info = ViewInfo { - resource: image.resource, + resource: image.internal.raw, kind: image.kind, flags: image.storage_flags, view_kind, @@ -984,23 +1058,11 @@ impl hal::Device for Device { where R: RangeArg, { - assert_eq!(memory.host_buffer.is_some(), true); + if let Some(ref host_visible) = memory.host_visible { + let ptr = host_visible.borrow_mut().as_mut_ptr(); + memory.mapped_ptr.replace(Some(ptr)); - let buffer = memory.host_buffer.clone().unwrap(); - let mut mapped = unsafe { mem::zeroed::() }; - let hr = unsafe { - self.context.Map( - buffer.as_raw() as _, - 0, - // TODO: - d3d11::D3D11_MAP_WRITE, - 0, - &mut mapped - ) - }; - - if winerror::SUCCEEDED(hr) { - Ok(unsafe { mapped.pData.offset(*range.start().unwrap_or(&0) as isize) as _ }) + Ok(unsafe { ptr.offset(*range.start().unwrap_or(&0) as isize) }) } else { // TODO: better error Err(mapping::Error::InvalidAccess) @@ -1008,59 +1070,17 @@ impl hal::Device for Device { } fn unmap_memory(&self, memory: &Memory) { - assert_eq!(memory.host_buffer.is_some(), true); - let buffer = memory.host_buffer.clone().unwrap(); + assert_eq!(memory.host_visible.is_some(), true); + let buffer = memory.host_visible.clone().unwrap(); - unsafe { + /*unsafe { self.context.Unmap( buffer.as_raw() as _, 0, ); - } - - fn intersection(a: &Range, b: &Range) -> Option> { - let min = if a.start < b.start { a } else { b }; - let max = if min == a { b } else { a }; - - if min.end < max.start { - None - } else { - let end = if min.end < max.end { min.end } else { max.end }; - Some(max.start..end) - } - } + }*/ - // go through every range we wrote to - for range in memory.flushes.borrow().iter() { - // and for every resource whose "virtual address" in our imaginary - // heap intersects; we copy from our host visible buffer to the - // corresponding dx11 resource - for &(ref buffer_range, ref buffer) in memory.local_buffers.borrow().iter() { - if let Some(range) = intersection(&range, &buffer_range) { - unsafe { - self.context.CopySubresourceRegion( - buffer.raw as _, - 0, - 0, - 0, - 0, - memory.host_buffer.clone().unwrap().as_raw() as _, - 0, - &d3d11::D3D11_BOX { - left: range.start as _, - top: 0, - front: 0, - right: buffer_range.end as _, - bottom: 1, - back: 1, - } - ); - } - } - } - } - - memory.flushes.borrow_mut().clear(); + memory.mapped_ptr.replace(None); } fn flush_mapped_memory_ranges<'a, I, R>(&self, ranges: I) @@ -1069,12 +1089,13 @@ impl hal::Device for Device { I::Item: Borrow<(&'a Memory, R)>, R: RangeArg, { - // we can't copy while mapped, so store the ranges for later + + // go through every range we wrote to for range in ranges.into_iter() { let &(memory, ref range) = range.borrow(); - let range = *range.start().unwrap_or(&0)..*range.end().unwrap_or(&memory.size); + let range = memory.resolve(range); - memory.flush(range); + memory.flush(&self.context, range); } } @@ -1084,7 +1105,13 @@ impl hal::Device for Device { I::Item: Borrow<(&'a Memory, R)>, R: RangeArg, { - unimplemented!() + // go through every range we want to read from + for range in ranges.into_iter() { + let &(memory, ref range) = range.borrow(); + let range = *range.start().unwrap_or(&0)..*range.end().unwrap_or(&memory.size); + + memory.invalidate(&self.context, range); + } } fn create_semaphore(&self) -> Semaphore { @@ -1163,7 +1190,8 @@ impl hal::Device for Device { } fn destroy_image(&self, image: Image) { - unimplemented!() + // TODO: + // unimplemented!() } fn destroy_image_view(&self, _view: ImageView) { @@ -1182,7 +1210,7 @@ impl hal::Device for Device { } fn destroy_fence(&self, _fence: Fence) { - unimplemented!() + // unimplemented!() } fn destroy_semaphore(&self, _semaphore: Semaphore) { @@ -1301,18 +1329,24 @@ impl hal::Device for Device { let kind = image::Kind::D2(surface.width, surface.height, 1, 1); + let internal = InternalImage { + raw: resource, + srv: None, + uav: None, + rtv: Some(unsafe { ComPtr::from_raw(rtv) }) + }; + Image { - resource, kind, usage: config.image_usage, storage_flags: image::StorageFlags::empty(), // NOTE: not the actual format of the backbuffer(s) + typed_raw_format: dxgiformat::DXGI_FORMAT_UNKNOWN, dxgi_format: format, bytes_per_block, block_dim, num_levels: 1, - uav: None, - rtv: Some(unsafe { ComPtr::from_raw(rtv) }) + internal } }).collect(); diff --git a/src/backend/dx11/src/internal.rs b/src/backend/dx11/src/internal.rs index 0b97f34ad98..2e435af98bc 100644 --- a/src/backend/dx11/src/internal.rs +++ b/src/backend/dx11/src/internal.rs @@ -1,6 +1,7 @@ use hal::pso::{Stage}; use hal::command; +use winapi::shared::dxgiformat; use winapi::shared::winerror; use winapi::um::d3d11; use wio::com::ComPtr; @@ -10,36 +11,79 @@ use std::{mem, ptr}; use spirv_cross; use shader; +#[repr(C)] +struct BufferCopy { + src: u32, + dst: u32, + _padding: [u32; 2] +} + +#[repr(C)] +struct ImageCopy { + src: [u32; 4], + dst: [u32; 4], +} + +#[repr(C)] +struct BufferImageCopy { + buffer_offset: u32, + buffer_size: [u32; 2], + _padding: u32, + image_offset: [u32; 4], + image_extent: [u32; 4], +} + #[repr(C)] struct BufferImageCopyInfo { - data: [u32; 4], + buffer: BufferCopy, + image: ImageCopy, + buffer_image: BufferImageCopy, } #[derive(Clone)] -pub struct BufferImageCopy { - cs: ComPtr, +pub struct Internal { + cs_copy_image2d_r32_buffer: ComPtr, + cs_copy_image2d_r16g16_buffer: ComPtr, + cs_copy_image2d_r16_buffer: ComPtr, + cs_copy_image2d_r8g8_buffer: ComPtr, + cs_copy_image2d_r8_buffer: ComPtr, + + cs_copy_buffer_image2d_r32: ComPtr, + cs_copy_buffer_image2d_r16g16: ComPtr, + cs_copy_buffer_image2d_r16: ComPtr, + cs_copy_buffer_image2d_r8g8: ComPtr, + cs_copy_buffer_image2d_r8: ComPtr, + copy_info: ComPtr, } -impl BufferImageCopy { - pub fn new(device: ComPtr) -> Self { - let cs = { - let shader_src = include_bytes!("../shaders/copy.hlsl"); - let bytecode = unsafe { ComPtr::from_raw(shader::compile_hlsl_shader(Stage::Compute, spirv_cross::hlsl::ShaderModel::V5_0, "cs_copy_buffer_image_2d", shader_src).unwrap()) }; - let mut shader = ptr::null_mut(); - let hr = unsafe { - device.CreateComputeShader( - bytecode.GetBufferPointer(), - bytecode.GetBufferSize(), - ptr::null_mut(), - &mut shader as *mut *mut _ as *mut *mut _ - ) - }; - assert_eq!(true, winerror::SUCCEEDED(hr)); +fn compile(device: ComPtr, entrypoint: &str) -> ComPtr { + let shader_src = include_bytes!("../shaders/copy.hlsl"); + let bytecode = unsafe { + ComPtr::from_raw(shader::compile_hlsl_shader( + Stage::Compute, + spirv_cross::hlsl::ShaderModel::V5_0, + entrypoint, + shader_src + ).unwrap()) + }; - unsafe { ComPtr::from_raw(shader) } - }; + let mut shader = ptr::null_mut(); + let hr = unsafe { + device.CreateComputeShader( + bytecode.GetBufferPointer(), + bytecode.GetBufferSize(), + ptr::null_mut(), + &mut shader as *mut *mut _ as *mut *mut _ + ) + }; + assert_eq!(true, winerror::SUCCEEDED(hr)); + unsafe { ComPtr::from_raw(shader) } +} + +impl Internal { + pub fn new(device: ComPtr) -> Self { let copy_info = { let desc = d3d11::D3D11_BUFFER_DESC { ByteWidth: mem::size_of::() as _, @@ -63,13 +107,52 @@ impl BufferImageCopy { unsafe { ComPtr::from_raw(buffer) } }; - BufferImageCopy { - cs, + Internal { + cs_copy_image2d_r32_buffer: compile(device.clone(), "cs_copy_image2d_r32_buffer"), + cs_copy_image2d_r16g16_buffer: compile(device.clone(), "cs_copy_image2d_r16g16_buffer"), + cs_copy_image2d_r16_buffer: compile(device.clone(), "cs_copy_image2d_r16_buffer"), + cs_copy_image2d_r8g8_buffer: compile(device.clone(), "cs_copy_image2d_r8g8_buffer"), + cs_copy_image2d_r8_buffer: compile(device.clone(), "cs_copy_image2d_r8_buffer"), + + cs_copy_buffer_image2d_r32: compile(device.clone(), "cs_copy_buffer_image2d_r32"), + cs_copy_buffer_image2d_r16g16: compile(device.clone(), "cs_copy_buffer_image2d_r16g16"), + cs_copy_buffer_image2d_r16: compile(device.clone(), "cs_copy_buffer_image2d_r16"), + cs_copy_buffer_image2d_r8g8: compile(device.clone(), "cs_copy_buffer_image2d_r8g8"), + cs_copy_buffer_image2d_r8: compile(device.clone(), "cs_copy_buffer_image2d_r8"), copy_info } } - fn update_buffer(&mut self, context: ComPtr, info: command::BufferImageCopy) { + fn update_buffer(&mut self, context: ComPtr, info: command::BufferCopy) { + let mut mapped = unsafe { mem::zeroed::() }; + let hr = unsafe { + context.Map( + self.copy_info.as_raw() as _, + 0, + d3d11::D3D11_MAP_WRITE_DISCARD, + 0, + &mut mapped + ) + }; + + unsafe { ptr::copy(&BufferImageCopyInfo { + buffer: BufferCopy { + src: info.src as _, + dst: info.dst as _, + _padding: [0u32; 2] + }, + .. mem::zeroed() + }, mem::transmute(mapped.pData), 1) }; + + unsafe { + context.Unmap( + self.copy_info.as_raw() as _, + 0, + ); + } + } + + fn update_image(&mut self, context: ComPtr, info: command::ImageCopy) { let mut mapped = unsafe { mem::zeroed::() }; let hr = unsafe { context.Map( @@ -81,16 +164,44 @@ impl BufferImageCopy { ) }; - let info_struct = BufferImageCopyInfo { - data: [ - info.buffer_offset as u32, - info.buffer_width as u32, - info.image_offset.x as u32, - info.image_offset.y as u32, - ], + unsafe { ptr::copy(&BufferImageCopyInfo { + image: ImageCopy { + src: [info.src_offset.x as _, info.src_offset.y as _, info.src_offset.z as _, 0], + dst: [info.dst_offset.x as _, info.dst_offset.y as _, info.dst_offset.z as _, 0], + }, + .. mem::zeroed() + }, mem::transmute(mapped.pData), 1) }; + + unsafe { + context.Unmap( + self.copy_info.as_raw() as _, + 0, + ); + } + } + + fn update_buffer_image(&mut self, context: ComPtr, info: command::BufferImageCopy) { + let mut mapped = unsafe { mem::zeroed::() }; + let hr = unsafe { + context.Map( + self.copy_info.as_raw() as _, + 0, + d3d11::D3D11_MAP_WRITE_DISCARD, + 0, + &mut mapped + ) }; - unsafe { ptr::copy(&info_struct, mem::transmute(mapped.pData), 1) }; + unsafe { ptr::copy(&BufferImageCopyInfo { + buffer_image: BufferImageCopy { + buffer_offset: info.buffer_offset as _, + buffer_size: [info.buffer_width, info.buffer_height], + _padding: 0, + image_offset: [info.image_offset.x as _, info.image_offset.y as _, info.image_offset.z as _, 0], + image_extent: [info.image_extent.width, info.image_extent.height, info.image_extent.depth, 0], + }, + .. mem::zeroed() + }, mem::transmute(mapped.pData), 1) }; unsafe { context.Unmap( @@ -100,22 +211,77 @@ impl BufferImageCopy { } } - pub fn copy_2d(&mut self, + fn find_image_to_buffer_shader(&self, format: dxgiformat::DXGI_FORMAT) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)> { + use dxgiformat::*; + + match format { + DXGI_FORMAT_R32_UINT => Some((self.cs_copy_image2d_r32_buffer.as_raw(), 1, 1)), + DXGI_FORMAT_R16G16_UINT => Some((self.cs_copy_image2d_r16g16_buffer.as_raw(), 1, 1)), + DXGI_FORMAT_R16_UINT => Some((self.cs_copy_image2d_r16_buffer.as_raw(), 2, 1)), + DXGI_FORMAT_R8G8_UINT => Some((self.cs_copy_image2d_r8g8_buffer.as_raw(), 2, 1)), + DXGI_FORMAT_R8_UINT => Some((self.cs_copy_image2d_r8_buffer.as_raw(), 4, 1)), + _ => None + } + } + + fn find_buffer_to_image_shader(&self, format: dxgiformat::DXGI_FORMAT) -> Option<(*mut d3d11::ID3D11ComputeShader, u32, u32)> { + use dxgiformat::*; + + match format { + DXGI_FORMAT_R32_UINT => Some((self.cs_copy_buffer_image2d_r32.as_raw(), 1, 1)), + DXGI_FORMAT_R16G16_UINT => Some((self.cs_copy_buffer_image2d_r16g16.as_raw(), 1, 1)), + DXGI_FORMAT_R16_UINT => Some((self.cs_copy_buffer_image2d_r16.as_raw(), 2, 1)), + DXGI_FORMAT_R8G8_UINT => Some((self.cs_copy_buffer_image2d_r8g8.as_raw(), 2, 1)), + DXGI_FORMAT_R8_UINT => Some((self.cs_copy_buffer_image2d_r8.as_raw(), 4, 1)), + _ => None + } + } + + pub fn copy_image_2d_buffer(&mut self, + context: ComPtr, + image: ComPtr, + image_format: dxgiformat::DXGI_FORMAT, + buffer: *mut d3d11::ID3D11UnorderedAccessView, + info: command::BufferImageCopy) { + self.update_buffer_image(context.clone(), info.clone()); + let (shader, stride_x, stride_y) = self.find_image_to_buffer_shader(image_format).unwrap(); + + unsafe { + context.CSSetShader(shader, ptr::null_mut(), 0); + context.CSSetConstantBuffers(0, 1, &self.copy_info.as_raw()); + context.CSSetShaderResources(0, 1, &image.as_raw()); + context.CSSetUnorderedAccessViews(0, 1, &buffer, ptr::null_mut()); + + context.Dispatch( + info.image_extent.width / stride_x, + info.image_extent.height / stride_y, + 1 + ); + + // unbind external resources + context.CSSetShaderResources(0, 1, [ptr::null_mut(); 1].as_ptr()); + context.CSSetUnorderedAccessViews(0, 1, [ptr::null_mut(); 1].as_ptr(), ptr::null_mut()); + } + } + + pub fn copy_buffer_image_2d(&mut self, context: ComPtr, buffer: *mut d3d11::ID3D11ShaderResourceView, image: ComPtr, + image_format: dxgiformat::DXGI_FORMAT, info: command::BufferImageCopy) { - self.update_buffer(context.clone(), info.clone()); + self.update_buffer_image(context.clone(), info.clone()); + let (shader, stride_x, stride_y) = self.find_buffer_to_image_shader(image_format).unwrap(); unsafe { - context.CSSetShader(self.cs.as_raw(), ptr::null_mut(), 0); + context.CSSetShader(shader, ptr::null_mut(), 0); context.CSSetConstantBuffers(0, 1, &self.copy_info.as_raw()); context.CSSetShaderResources(0, 1, &buffer); context.CSSetUnorderedAccessViews(0, 1, &image.as_raw(), ptr::null_mut()); context.Dispatch( - info.image_extent.width, - info.image_extent.height, + info.image_extent.width / stride_x, + info.image_extent.height / stride_y, 1 ); diff --git a/src/backend/dx11/src/lib.rs b/src/backend/dx11/src/lib.rs index 5efb469db80..3290cc7a916 100644 --- a/src/backend/dx11/src/lib.rs +++ b/src/backend/dx11/src/lib.rs @@ -46,8 +46,10 @@ mod device; -#[derive(Clone, Debug)] +#[derive(Clone, Derivative)] +#[derivative(Debug)] pub(crate) struct ViewInfo { + #[derivative(Debug="ignore")] resource: *mut d3d11::ID3D11Resource, kind: image::Kind, flags: image::StorageFlags, @@ -696,7 +698,7 @@ impl hal::queue::RawCommandQueue for CommandQueue { pub struct CommandBuffer { // TODO: better way of sharing #[derivative(Debug="ignore")] - internal: internal::BufferImageCopy, + internal: internal::Internal, #[derivative(Debug="ignore")] context: ComPtr, #[derivative(Debug="ignore")] @@ -707,7 +709,7 @@ unsafe impl Send for CommandBuffer {} unsafe impl Sync for CommandBuffer {} impl CommandBuffer { - fn create_deferred(device: ComPtr, internal: internal::BufferImageCopy) -> Self { + fn create_deferred(device: ComPtr, internal: internal::Internal) -> Self { let mut context: *mut d3d11::ID3D11DeviceContext = ptr::null_mut(); let hr = unsafe { device.CreateDeferredContext(0, &mut context as *mut *mut _ as *mut *mut _) @@ -814,7 +816,7 @@ impl hal::command::RawCommandBuffer for CommandBuffer { let _sub = subresource_range.borrow(); unsafe { self.context.ClearRenderTargetView( - image.rtv.clone().unwrap().as_raw(), + image.internal.rtv.clone().unwrap().as_raw(), &color.float32 ); } @@ -1016,7 +1018,29 @@ impl hal::command::RawCommandBuffer for CommandBuffer { T: IntoIterator, T::Item: Borrow, { - unimplemented!() + for region in regions.into_iter() { + let info = region.borrow(); + + unsafe { + self.context.CopySubresourceRegion( + dst.internal.raw as _, + 0, + info.dst as _, + 0, + 0, + src.internal.raw as _, + 0, + &d3d11::D3D11_BOX { + left: info.src as _, + top: 0, + front: 0, + right: (info.src + info.size) as _, + bottom: 1, + back: 1, + } + ); + } + } } fn copy_image(&mut self, src: &Image, _: image::Layout, dst: &Image, _: image::Layout, regions: T) @@ -1024,7 +1048,30 @@ impl hal::command::RawCommandBuffer for CommandBuffer { T: IntoIterator, T::Item: Borrow, { - unimplemented!() + for region in regions.into_iter() { + let info = region.borrow(); + + // TODO: subresources + unsafe { + self.context.CopySubresourceRegion( + dst.internal.raw as _, + 0, + info.dst_offset.x as _, + info.dst_offset.y as _, + info.dst_offset.z as _, + src.internal.raw as _, + 0, + &d3d11::D3D11_BOX { + left: info.src_offset.x as _, + top: info.src_offset.y as _, + front: info.src_offset.z as _, + right: info.extent.width as _, + bottom: info.extent.height as _, + back: info.extent.depth as _, + } + ); + } + } } fn copy_buffer_to_image(&mut self, buffer: &Buffer, image: &Image, _: image::Layout, regions: T) @@ -1034,11 +1081,13 @@ impl hal::command::RawCommandBuffer for CommandBuffer { { assert_eq!(buffer.internal.srv.is_some(), true); + // TODO: more than 2D for copy in regions.into_iter() { - self.internal.copy_2d( + self.internal.copy_buffer_image_2d( self.context.clone(), buffer.internal.srv.unwrap(), - image.uav.clone().unwrap(), + image.internal.uav.clone().unwrap(), + image.typed_raw_format, copy.borrow().clone() ); } @@ -1049,7 +1098,17 @@ impl hal::command::RawCommandBuffer for CommandBuffer { T: IntoIterator, T::Item: Borrow, { - unimplemented!() + assert_eq!(buffer.internal.uav.is_some(), true); + + for copy in regions.into_iter() { + self.internal.copy_image_2d_buffer( + self.context.clone(), + image.internal.srv.clone().unwrap(), + image.typed_raw_format, + buffer.internal.uav.unwrap(), + copy.borrow().clone() + ); + } } fn draw(&mut self, vertices: Range, instances: Range) { @@ -1119,44 +1178,153 @@ impl hal::command::RawCommandBuffer for CommandBuffer { // Since we dont have any heaps to work with directly, everytime we bind a // buffer/image to memory we allocate a dx11 resource and assign it a range. // -// `HOST_VISIBLE` memory gets a staging buffer which covers the entire memory +// `HOST_VISIBLE` memory gets a `Vec` which covers the entire memory // range. This forces us to only expose non-coherent memory, as this -// abstraction acts as a "cache" since the staging buffer is disjoint from all -// the dx11 resources we store in the struct. +// abstraction acts as a "cache" since the "staging buffer" vec is disjoint +// from all the dx11 resources we store in the struct. #[derive(Derivative)] #[derivative(Debug)] pub struct Memory { properties: memory::Properties, size: u64, - // stores flushed ranges inbetween mappings - flushes: RefCell>>, + mapped_ptr: RefCell>, + + // staging buffer covering the whole memory region, if it's HOST_VISIBLE + host_visible: Option>>, + + #[derivative(Debug="ignore")] + working_buffer: Option>, // list of all buffers bound to this memory #[derivative(Debug="ignore")] local_buffers: RefCell, InternalBuffer)>>, - // staging buffer covering the whole memory region, if it's HOST_VISIBLE + // list of all images bound to this memory #[derivative(Debug="ignore")] - host_buffer: Option>, + local_images: RefCell, InternalImage)>>, } unsafe impl Send for Memory {} unsafe impl Sync for Memory {} +fn intersection(a: &Range, b: &Range) -> Option> { + let min = if a.start < b.start { a } else { b }; + let max = if min == a { b } else { a }; + + if min.end < max.start { + None + } else { + let end = if min.end < max.end { min.end } else { max.end }; + Some(max.start..end) + } +} + +// TODO: implement flush/invalidate for bound images as well impl Memory { - pub fn flush(&self, range: Range) { - self.flushes.borrow_mut().push(range); + pub fn resolve>(&self, range: &R) -> Range { + *range.start().unwrap_or(&0) .. *range.end().unwrap_or(&self.size) } pub fn bind_buffer(&self, range: Range, buffer: InternalBuffer) { self.local_buffers.borrow_mut().push((range, buffer)); } + + pub fn flush(&self, context: &ComPtr, range: Range) { + for &(ref buffer_range, ref buffer) in self.local_buffers.borrow().iter() { + if let Some(range) = intersection(&range, &buffer_range) { + unsafe { + let src = self.mapped_ptr.borrow().unwrap(); + + context.UpdateSubresource( + buffer.raw as _, + 0, + &d3d11::D3D11_BOX { + left: (range.start - buffer_range.start) as _, + top: 0, + front: 0, + right: (range.end - buffer_range.start) as _, + bottom: 1, + back: 1, + }, + src.offset(range.start as isize) as _, + 0, + 0 + ); + } + } + } + } + + fn map(&self, context: &ComPtr) -> *mut u8 { + assert_eq!(self.working_buffer.is_some(), true); + + unsafe { + let mut map = mem::zeroed(); + let hr = context.Map( + self.working_buffer.clone().unwrap().as_raw() as _, + 0, + d3d11::D3D11_MAP_READ, + 0, + &mut map + ); + + assert_eq!(hr, winerror::S_OK); + + map.pData as _ + } + } + + fn unmap(&self, context: &ComPtr) { + unsafe { + context.Unmap( + self.working_buffer.clone().unwrap().as_raw() as _, + 0, + ); + } + } + + pub fn invalidate(&self, context: &ComPtr, range: Range) { + for &(ref buffer_range, ref buffer) in self.local_buffers.borrow().iter() { + if let Some(range) = intersection(&range, &buffer_range) { + unsafe { + + // upload to staging buffer + context.CopySubresourceRegion( + self.working_buffer.clone().unwrap().as_raw() as _, + 0, + 0, + 0, + 0, + buffer.raw as _, + 0, + &d3d11::D3D11_BOX { + left: range.start as _, + top: 0, + front: 0, + right: range.end as _, + bottom: 1, + back: 1, + } + ); + + // TODO: handle memory larger than our hardcoded 1<<15 + // staging buffer + + // copy over to our vec + let dst = self.mapped_ptr.borrow().unwrap().offset(range.start as isize); + let src = self.map(&context); + ptr::copy(src, dst, (range.end - range.start) as usize); + self.unmap(&context); + } + } + } + } } pub struct CommandPool { device: ComPtr, - internal: internal::BufferImageCopy, + internal: internal::Internal, } unsafe impl Send for CommandPool {} @@ -1174,7 +1342,8 @@ impl hal::pool::RawCommandPool for CommandPool { } unsafe fn free(&mut self, _cbufs: Vec) { - unimplemented!() + // TODO: + // unimplemented!() } } @@ -1216,7 +1385,8 @@ pub struct UnboundBuffer { #[derive(Clone)] pub struct InternalBuffer { raw: *mut d3d11::ID3D11Buffer, - srv: Option<*mut d3d11::ID3D11ShaderResourceView> + srv: Option<*mut d3d11::ID3D11ShaderResourceView>, + uav: Option<*mut d3d11::ID3D11UnorderedAccessView> } #[derive(Derivative)] @@ -1247,15 +1417,24 @@ pub struct UnboundImage { #[derive(Derivative)] #[derivative(Debug)] pub struct Image { - #[derivative(Debug="ignore")] - resource: *mut d3d11::ID3D11Resource, kind: image::Kind, usage: image::Usage, storage_flags: image::StorageFlags, dxgi_format: dxgiformat::DXGI_FORMAT, + typed_raw_format: dxgiformat::DXGI_FORMAT, bytes_per_block: u8, block_dim: (u8, u8), num_levels: image::Level, + internal: InternalImage, +} + +#[derive(Derivative)] +#[derivative(Debug)] +pub struct InternalImage { + #[derivative(Debug="ignore")] + raw: *mut d3d11::ID3D11Resource, + #[derivative(Debug="ignore")] + srv: Option>, #[derivative(Debug="ignore")] uav: Option>, #[derivative(Debug="ignore")]