/*-------------------------------------------
	main関数
--------------------------------------------*/
int wmain(int argc, WCHAR* argv[])
{
	HRESULT hr;

	// ロケールを設定
	_wsetlocale(LC_ALL, L"Japanese");

	// **********************************************************
	// Direct3D11デバイスの作成
	hr = CreateDevice();

	// **********************************************************
	// コンピュート・シェーダの作成
	if (SUCCEEDED(hr))
		hr = CreateShader();

	// **********************************************************
	// 定数バッファの作成
	if (SUCCEEDED(hr))
		hr = CreateCBuffer();

	// **********************************************************
	// リソースの作成
	if (SUCCEEDED(hr))
		hr = CreateResource();

	// **********************************************************
	// シェーダ リソース ビューの作成
	if (SUCCEEDED(hr))
		hr = CreateSRV();

	// **********************************************************
	// アンオーダード・アクセス・ビューの作成
	if (SUCCEEDED(hr))
		hr = CreateUAV();

	// **********************************************************
	// コンピュート・シェーダを使った演算
	if (SUCCEEDED(hr))
		ComputeShader();

	// **********************************************************
	// 開放
	SAFE_RELEASE(g_pUAV[1]);
	SAFE_RELEASE(g_pUAV[0]);
	SAFE_RELEASE(g_pSRV[1]);
	SAFE_RELEASE(g_pSRV[0]);
	SAFE_RELEASE(g_pReadBackBuffer);
	SAFE_RELEASE(g_pBuffer[1]);
	SAFE_RELEASE(g_pBuffer[0]);
	SAFE_RELEASE(g_pCBuffer);
	SAFE_RELEASE(g_pComputeShader);
	SAFE_RELEASE(g_pImmediateContext);
	SAFE_RELEASE(g_pD3DDevice);

	return 0;
}
FUnorderedAccessViewRHIRef FD3D12DynamicRHI::RHICreateUnorderedAccessView(FStructuredBufferRHIParamRef StructuredBufferRHI, bool bUseUAVCounter, bool bAppendBuffer)
{
	FD3D12StructuredBuffer*  StructuredBuffer = FD3D12DynamicRHI::ResourceCast(StructuredBufferRHI);

	FD3D12ResourceLocation& Location = StructuredBuffer->ResourceLocation;

	const D3D12_RESOURCE_DESC& BufferDesc = Location.GetResource()->GetDesc();

	const uint32 BufferUsage = StructuredBuffer->GetUsage();
	const bool bByteAccessBuffer = (BufferUsage & BUF_ByteAddressBuffer) != 0;
	const bool bStructuredBuffer = !bByteAccessBuffer;
	check(bByteAccessBuffer != bStructuredBuffer); // You can't have a structured buffer that allows raw views

	D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};
	UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
	UAVDesc.Format = DXGI_FORMAT_UNKNOWN;

	uint32 EffectiveStride = StructuredBuffer->GetStride();

	if (bByteAccessBuffer)
	{
		UAVDesc.Format  = DXGI_FORMAT_R32_TYPELESS;
		EffectiveStride = 4;
	}

	else if (BufferUsage & BUF_DrawIndirect)
	{
		UAVDesc.Format  = DXGI_FORMAT_R32_UINT;
		EffectiveStride = 4;
	}
	UAVDesc.Buffer.FirstElement = Location.GetOffsetFromBaseOfResource() / EffectiveStride;
	UAVDesc.Buffer.NumElements  = Location.GetSize() / EffectiveStride;
	UAVDesc.Buffer.StructureByteStride = bStructuredBuffer ? EffectiveStride : 0;
	UAVDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;

	UAVDesc.Buffer.CounterOffsetInBytes = 0;

	const bool bNeedsCounterResource = bAppendBuffer | bUseUAVCounter;

	if (bByteAccessBuffer)
	{
		UAVDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
	}

	return CreateUAV(UAVDesc, StructuredBuffer, bNeedsCounterResource);
}
FUnorderedAccessViewRHIRef FD3D12DynamicRHI::RHICreateUnorderedAccessView(FTextureRHIParamRef TextureRHI, uint32 MipLevel)
{
	FD3D12TextureBase* Texture = GetD3D12TextureFromRHITexture(TextureRHI);

	D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};

	const DXGI_FORMAT PlatformResourceFormat = (DXGI_FORMAT)GPixelFormats[TextureRHI->GetFormat()].PlatformFormat;
	UAVDesc.Format = FindShaderResourceDXGIFormat(PlatformResourceFormat, false);

	if (TextureRHI->GetTexture3D() != NULL)
	{
		FD3D12Texture3D* Texture3D = (FD3D12Texture3D*)Texture;
		UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
		UAVDesc.Texture3D.MipSlice = MipLevel;
		UAVDesc.Texture3D.FirstWSlice = 0;
		UAVDesc.Texture3D.WSize = Texture3D->GetSizeZ() >> MipLevel;

		return CreateUAV(UAVDesc, Texture3D, false);
	}
void BufferD3D11Impl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, IBufferView **ppView, bool bIsDefaultView )
{
    VERIFY( ppView != nullptr, "Null pointer provided" );
    if( !ppView )return;
    VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );

    *ppView = nullptr;

    try
    {
        auto *pDeviceD3D11Impl = ValidatedCast<RenderDeviceD3D11Impl>(GetDevice());
        auto &BuffViewAllocator = pDeviceD3D11Impl->GetBuffViewObjAllocator();
        VERIFY( &BuffViewAllocator == &m_dbgBuffViewAllocator, "Buff view allocator does not match allocator provided at buffer initialization" );

        BufferViewDesc ViewDesc = OrigViewDesc;
        if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS )
        {
            CComPtr<ID3D11UnorderedAccessView> pUAV;
            CreateUAV( ViewDesc, &pUAV );
            *ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewD3D11Impl instance",  BufferViewD3D11Impl, bIsDefaultView ? this : nullptr)
                                ( pDeviceD3D11Impl, ViewDesc, this, pUAV, bIsDefaultView );
        }
        else if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
        {
			CComPtr<ID3D11ShaderResourceView> pSRV;
            CreateSRV( ViewDesc, &pSRV );
            *ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewD3D11Impl instance",  BufferViewD3D11Impl, bIsDefaultView ? this : nullptr)
                                (pDeviceD3D11Impl, ViewDesc, this, pSRV, bIsDefaultView );
        }

        if( !bIsDefaultView && *ppView )
            (*ppView)->AddRef();
    }
    catch( const std::runtime_error & )
    {
        const auto *ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
        LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name, "\"" );
    }
}
void BufferD3D12Impl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, IBufferView **ppView, bool bIsDefaultView )
{
    VERIFY( ppView != nullptr, "Null pointer provided" );
    if( !ppView )return;
    VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );

    *ppView = nullptr;

    try
    {
        auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
        auto &BuffViewAllocator = pDeviceD3D12Impl->GetBuffViewObjAllocator();
        VERIFY( &BuffViewAllocator == &m_dbgBuffViewAllocator, "Buff view allocator does not match allocator provided at buffer initialization" );

        BufferViewDesc ViewDesc = OrigViewDesc;
        if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS )
        {
            auto UAVHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
            CreateUAV( ViewDesc, UAVHandleAlloc.GetCpuHandle() );
            *ppView = NEW(BuffViewAllocator, "BufferViewD3D12Impl instance", BufferViewD3D12Impl, GetDevice(), ViewDesc, this, std::move(UAVHandleAlloc), bIsDefaultView );
        }
        else if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
        {
			auto SRVHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
            CreateSRV( ViewDesc, SRVHandleAlloc.GetCpuHandle() );
            *ppView = NEW(BuffViewAllocator, "BufferViewD3D12Impl instance", BufferViewD3D12Impl, GetDevice(), ViewDesc, this, std::move(SRVHandleAlloc), bIsDefaultView );
        }

        if( !bIsDefaultView && *ppView )
            (*ppView)->AddRef();
    }
    catch( const std::runtime_error & )
    {
        const auto *ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
        LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name, "\"" )
    }
}