// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #if GRAPHICS_API_DIRECTX11 #include "GPUBufferDX11.h" #include "../RenderToolsDX.h" #include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Threading/Threading.h" GPUBufferDX11::GPUBufferDX11(GPUDeviceDX11* device, const StringView& name) : GPUResourceDX11(device, name) { } GPUBufferView* GPUBufferDX11::View() const { return (GPUBufferView*)&_view; } void* GPUBufferDX11::Map(GPUResourceMapMode mode) { if (!IsInMainThread()) _device->Locker.Lock(); D3D11_MAPPED_SUBRESOURCE map; map.pData = nullptr; D3D11_MAP mapType; switch (mode) { case GPUResourceMapMode::Read: mapType = D3D11_MAP_READ; break; case GPUResourceMapMode::Write: mapType = D3D11_MAP_WRITE_DISCARD; break; case GPUResourceMapMode::ReadWrite: mapType = D3D11_MAP_READ_WRITE; break; default: CRASH; return nullptr; } const HRESULT result = _device->GetIM()->Map(_resource, 0, mapType, 0, &map); LOG_DIRECTX_RESULT(result); return map.pData; } void GPUBufferDX11::Unmap() { _device->GetIM()->Unmap(_resource, 0); if (!IsInMainThread()) _device->Locker.Unlock(); } bool GPUBufferDX11::OnInit() { bool useSRV = IsShaderResource(); bool useUAV = IsUnorderedAccess(); // Create buffer description D3D11_BUFFER_DESC bufferDesc; bufferDesc.ByteWidth = _desc.Size; bufferDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage); bufferDesc.BindFlags = 0; bufferDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage); bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; // if (_desc.Flags & GPUBufferFlags::VertexBuffer) bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER; if (_desc.Flags & GPUBufferFlags::IndexBuffer) bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER; if (useSRV) bufferDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; if (useUAV) bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; // if (_desc.Flags & GPUBufferFlags::Argument) bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; if (_desc.Flags & GPUBufferFlags::RawBuffer) bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; if (_desc.Flags & GPUBufferFlags::Structured) { bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; bufferDesc.StructureByteStride = _desc.Stride; } // Create resource D3D11_SUBRESOURCE_DATA data; if (_desc.InitData) { data.pSysMem = _desc.InitData; data.SysMemPitch = bufferDesc.ByteWidth; data.SysMemSlicePitch = 0; } VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateBuffer(&bufferDesc, _desc.InitData ? &data : nullptr, &_resource)); // Set state DX_SET_DEBUG_NAME(_resource, GetName()); _memoryUsage = _desc.Size; int32 numElements = _desc.GetElementsCount(); // Create views if (useSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; if (_desc.Flags & GPUBufferFlags::RawBuffer) { srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; srvDesc.BufferEx.FirstElement = 0; srvDesc.BufferEx.NumElements = numElements; srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; } else { if (_desc.Flags & GPUBufferFlags::Structured) srvDesc.Format = DXGI_FORMAT_UNKNOWN; else srvDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(_desc.Format, false)); srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; srvDesc.Buffer.FirstElement = 0; srvDesc.Buffer.NumElements = numElements; } ID3D11ShaderResourceView* srv; VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srvDesc, &srv)); _view.SetSRV(srv); } if (useUAV) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uavDesc.Buffer.FirstElement = 0; uavDesc.Buffer.NumElements = numElements; uavDesc.Buffer.Flags = 0; if (_desc.Flags & GPUBufferFlags::RawBuffer) uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW; if (_desc.Flags & GPUBufferFlags::Append) uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_APPEND; if (_desc.Flags & GPUBufferFlags::Counter) uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_COUNTER; if (_desc.Flags & GPUBufferFlags::Structured) uavDesc.Format = DXGI_FORMAT_UNKNOWN; else uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format)); ID3D11UnorderedAccessView* uav; VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateUnorderedAccessView(_resource, &uavDesc, &uav)); _view.SetUAV(uav); } return false; } void GPUBufferDX11::OnReleaseGPU() { _view.Release(); DX_SAFE_RELEASE_CHECK(_resource, 0); // Base GPUBuffer::OnReleaseGPU(); } #endif