diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index b05406830..e0809ddee 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -62,7 +62,7 @@ namespace dxvk { const D3D11_BUFFER_DESC* pDesc) const { DxvkBufferCreateInfo info; info.size = pDesc->ByteWidth; - info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; info.access = VK_ACCESS_TRANSFER_READ_BIT diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index d6d5098e1..b44dabf82 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -138,6 +138,12 @@ namespace dxvk { this->CSSetSamplers(i, 1, &sampler); } + for (uint32_t i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++) { + ID3D11UnorderedAccessView* uav = nullptr; + + this->CSSetUnorderedAccessViews(i, 1, &uav, nullptr); + } + this->OMSetRenderTargets(0, nullptr, nullptr); this->OMSetBlendState(nullptr, nullptr, D3D11_DEFAULT_SAMPLE_MASK); this->OMSetDepthStencilState(nullptr, 0); @@ -328,7 +334,35 @@ namespace dxvk { void STDMETHODCALLTYPE D3D11DeviceContext::CopyResource( ID3D11Resource* pDstResource, ID3D11Resource* pSrcResource) { - Logger::err("D3D11DeviceContext::CopyResource: Not implemented"); + D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + + pDstResource->GetType(&dstResourceDim); + pSrcResource->GetType(&srcResourceDim); + + if (dstResourceDim != srcResourceDim) { + Logger::err("D3D11DeviceContext: CopyResource: Mismatched resource types"); + return; + } + + if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto dstBuffer = static_cast(pDstResource)->GetBufferSlice(); + auto srcBuffer = static_cast(pSrcResource)->GetBufferSlice(); + + if (dstBuffer.length() != srcBuffer.length()) { + Logger::err("D3D11DeviceContext: CopyResource: Mismatched buffer size"); + return; + } + + m_context->copyBuffer( + dstBuffer.buffer(), + dstBuffer.offset(), + srcBuffer.buffer(), + srcBuffer.offset(), + srcBuffer.length()); + } else { + Logger::err("D3D11DeviceContext::CopyResource: Images not supported"); + } } @@ -1299,7 +1333,15 @@ namespace dxvk { UINT NumUAVs, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, const UINT* pUAVInitialCounts) { - Logger::err("D3D11DeviceContext::CSSetUnorderedAccessViews: Not implemented"); + // TODO implement append-consume buffers + if (pUAVInitialCounts != nullptr) + Logger::err("D3D11DeviceContext: pUAVInitialCounts not supported"); + + this->BindUnorderedAccessViews( + DxbcProgramType::ComputeShader, + m_state.cs.unorderedAccessViews, + StartSlot, NumUAVs, + ppUnorderedAccessViews); } @@ -1696,7 +1738,6 @@ namespace dxvk { if (resView != nullptr) { // Figure out what we have to bind based on the resource type if (resView->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) { - // TODO support raw and structured buffers m_context->bindResourceTexelBuffer( slotId + i, resView->GetDXVKBufferView()); } else { @@ -1714,6 +1755,42 @@ namespace dxvk { } + void D3D11DeviceContext::BindUnorderedAccessViews( + DxbcProgramType ShaderStage, + D3D11UnorderedAccessBindings& Bindings, + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews) { + const uint32_t slotId = computeResourceSlotId( + ShaderStage, DxbcBindingType::UnorderedAccessView, + StartSlot); + + for (uint32_t i = 0; i < NumUAVs; i++) { + auto uav = static_cast(ppUnorderedAccessViews[i]); + + if (Bindings[StartSlot + i] != uav) { + Bindings[StartSlot + i] = uav; + + if (uav != nullptr) { + // Figure out what we have to bind based on the resource type + if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) { + m_context->bindResourceTexelBuffer( + slotId + i, uav->GetDXVKBufferView()); + } else { + m_context->bindResourceImage( + slotId + i, uav->GetDXVKImageView()); + } + } else { + // When unbinding a resource, it doesn't really matter if + // the resource type is correct, so we'll just bind a null + // image to the given resource slot + m_context->bindResourceImage(slotId + i, nullptr); + } + } + } + } + + void D3D11DeviceContext::ApplyViewportState() { // We cannot set less than one viewport in Vulkan, and // rendering with no active viewport is illegal anyway. diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index e228641b7..6f2b2d291 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -584,6 +584,13 @@ namespace dxvk { UINT NumResources, ID3D11ShaderResourceView* const* ppResources); + void BindUnorderedAccessViews( + DxbcProgramType ShaderStage, + D3D11UnorderedAccessBindings& Bindings, + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews); + void ApplyViewportState(); }; diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 89c363254..1fc43cae0 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -314,8 +314,68 @@ namespace dxvk { ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAView) { - Logger::err("D3D11Device::CreateUnorderedAccessView: Not implemented"); - return E_NOTIMPL; + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + // The description is optional. If omitted, we'll create + // a view that covers all subresources of the image. + D3D11_UNORDERED_ACCESS_VIEW_DESC desc; + + if (pDesc == nullptr) { + if (FAILED(GetUnorderedAccessViewDescFromResource(pResource, &desc))) + return E_INVALIDARG; + } else { + desc = *pDesc; + } + + if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto resource = static_cast(pResource); + + D3D11_BUFFER_DESC resourceDesc; + resource->GetDesc(&resourceDesc); + + DxvkBufferViewCreateInfo viewInfo; + + if (desc.Buffer.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) { + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = sizeof(uint32_t) * desc.Buffer.FirstElement; + viewInfo.rangeLength = sizeof(uint32_t) * desc.Buffer.NumElements; + } else if (desc.Format == DXGI_FORMAT_UNKNOWN) { + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = resourceDesc.StructureByteStride * desc.Buffer.FirstElement; + viewInfo.rangeLength = resourceDesc.StructureByteStride * desc.Buffer.NumElements; + } else { + // Typed buffer view - must use an uncompressed color format + viewInfo.format = m_dxgiAdapter->LookupFormat( + desc.Format, DxgiFormatMode::Color).format; + + const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format); + viewInfo.rangeOffset = formatInfo->elementSize * desc.Buffer.FirstElement; + viewInfo.rangeLength = formatInfo->elementSize * desc.Buffer.NumElements; + + if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) { + Logger::err("D3D11Device: Compressed formats for buffer views not supported"); + return E_INVALIDARG; + } + } + + if (ppUAView == nullptr) + return S_FALSE; + + try { + *ppUAView = ref(new D3D11UnorderedAccessView( + this, pResource, desc, + m_dxvkDevice->createBufferView( + resource->GetBufferSlice().buffer(), viewInfo))); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } else { + Logger::err("D3D11Device::CreateUnorderedAccessView: Images not supported yet"); + return E_NOTIMPL; + } } @@ -1352,6 +1412,7 @@ namespace dxvk { HRESULT D3D11Device::GetUnorderedAccessViewDescFromResource( ID3D11Resource* pResource, D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) { + Logger::err("D3D11Device::GetUnorderedAccessViewDescFromResource: Not implemented"); return E_NOTIMPL; }