1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-11-29 19:24:10 +01:00

[d3d11] Fixed buffer bindings with non-zero offsets

This commit is contained in:
Philip Rebohle 2017-12-14 19:07:08 +01:00
parent 6de6421dfd
commit 9827ace3b0
10 changed files with 74 additions and 159 deletions

View File

@ -9,8 +9,9 @@ namespace dxvk {
D3D11Buffer::D3D11Buffer(
D3D11Device* pDevice,
const D3D11_BUFFER_DESC* pDesc)
: m_device (pDevice),
m_desc (*pDesc) {
: m_device (pDevice),
m_desc (*pDesc),
m_buffer (CreateBuffer(pDesc)) {
}
@ -62,7 +63,7 @@ namespace dxvk {
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedSubresource) {
const Rc<DxvkBuffer> buffer = GetDXVKBuffer();
const Rc<DxvkBuffer> buffer = m_buffer;
if (buffer->mapPtr(0) == nullptr) {
Logger::err("D3D11: Cannot map a device-local buffer");
@ -122,8 +123,13 @@ namespace dxvk {
}
Rc<DxvkBuffer> D3D11Buffer::GetDXVKBuffer() {
return m_buffer;
DxvkBufferSlice D3D11Buffer::GetCurrentBufferSlice() const {
return DxvkBufferSlice(m_buffer, 0, m_desc.ByteWidth);
}
DxvkBufferSlice D3D11Buffer::GetInitialBufferSlice() const {
return DxvkBufferSlice(m_buffer, 0, m_desc.ByteWidth);
}

View File

@ -11,8 +11,17 @@ namespace dxvk {
class D3D11DeviceContext;
class D3D11Buffer : public D3D11DeviceChild<ID3D11Buffer> {
class D3D11BufferStorage {
public:
private:
};
class D3D11Buffer : public D3D11DeviceChild<ID3D11Buffer> {
static constexpr VkDeviceSize BufferSliceAlignment = 64;
public:
D3D11Buffer(
@ -46,14 +55,15 @@ namespace dxvk {
void Unmap(
D3D11DeviceContext* pContext);
Rc<DxvkBuffer> GetDXVKBuffer();
DxvkBufferSlice GetCurrentBufferSlice() const;
DxvkBufferSlice GetInitialBufferSlice() const;
private:
Com<D3D11Device> m_device;
D3D11_BUFFER_DESC m_desc;
const Com<D3D11Device> m_device;
const D3D11_BUFFER_DESC m_desc;
Rc<DxvkBuffer> m_buffer;
Rc<DxvkBuffer> m_buffer;
Rc<DxvkBuffer> CreateBuffer(
const D3D11_BUFFER_DESC* pDesc) const;

View File

@ -395,23 +395,28 @@ namespace dxvk {
pDstResource->GetType(&resourceType);
if (resourceType == D3D11_RESOURCE_DIMENSION_BUFFER) {
Com<IDXGIBufferResourcePrivate> bufferResource;
pDstResource->QueryInterface(
__uuidof(IDXGIBufferResourcePrivate),
reinterpret_cast<void**>(&bufferResource));
const auto bufferResource = static_cast<D3D11Buffer*>(pDstResource);
const auto bufferSlice = bufferResource->GetCurrentBufferSlice();
VkDeviceSize offset = 0;
VkDeviceSize size = VK_WHOLE_SIZE;
VkDeviceSize size = bufferSlice.bufferRange();
if (pDstBox != nullptr) {
offset = pDstBox->left;
size = pDstBox->right - pDstBox->left;
}
m_context->updateBuffer(
bufferResource->GetDXVKBuffer(),
offset, size, pSrcData);
if (offset + size > bufferSlice.bufferRange()) {
Logger::err("D3D11: UpdateSubresource: Buffer size out of bounds");
return;
}
if (size != 0) {
m_context->updateBuffer(
bufferSlice.buffer(),
bufferSlice.bufferOffset() + offset,
size, pSrcData);
}
} else {
Logger::err("D3D11DeviceContext::UpdateSubresource: Images not yet supported");
}
@ -628,18 +633,20 @@ namespace dxvk {
binding.stride = pStrides[i];
}
DxvkBufferSlice dxvkBinding;
DxvkBufferSlice bufferSlice;
if (binding.buffer != nullptr) {
Rc<DxvkBuffer> dxvkBuffer = binding.buffer->GetDXVKBuffer();
const DxvkBufferSlice baseSlice =
binding.buffer->GetCurrentBufferSlice();
dxvkBinding = DxvkBufferSlice(
dxvkBuffer, binding.offset,
dxvkBuffer->info().size - binding.offset);
bufferSlice = DxvkBufferSlice(
baseSlice.buffer(),
baseSlice.bufferOffset() + binding.offset,
baseSlice.bufferRange() - binding.offset);
}
m_context->bindVertexBuffer(
StartSlot + i, dxvkBinding,
StartSlot + i, bufferSlice,
binding.stride);
}
}
@ -655,17 +662,18 @@ namespace dxvk {
binding.format = Format;
m_state.ia.indexBuffer = binding;
DxvkBufferSlice dxvkBinding;
DxvkBufferSlice bufferSlice;
if (binding.buffer != nullptr) {
Rc<DxvkBuffer> dxvkBuffer = binding.buffer->GetDXVKBuffer();
const DxvkBufferSlice baseSlice =
binding.buffer->GetCurrentBufferSlice();
dxvkBinding = DxvkBufferSlice(
dxvkBuffer, binding.offset,
dxvkBuffer->info().size - binding.offset);
bufferSlice = DxvkBufferSlice(
baseSlice.buffer(),
baseSlice.bufferOffset() + binding.offset,
baseSlice.bufferRange() - binding.offset);
}
// As in Vulkan, the index format can be either a 32-bit
// unsigned integer or a 16-bit unsigned integer, no other
// formats are allowed.
@ -680,7 +688,7 @@ namespace dxvk {
}
m_context->bindIndexBuffer(
dxvkBinding, indexType);
bufferSlice, indexType);
}
@ -1462,13 +1470,10 @@ namespace dxvk {
pBindings->at(StartSlot + i) = buffer;
// Figure out which part of the buffer to bind
DxvkBufferSlice bindingInfo;
DxvkBufferSlice bufferSlice;
if (buffer != nullptr) {
bindingInfo = DxvkBufferSlice(
buffer->GetDXVKBuffer(),
0, VK_WHOLE_SIZE);
}
if (buffer != nullptr)
bufferSlice = buffer->GetCurrentBufferSlice();
// Bind buffer to the DXVK resource slot
const VkPipelineBindPoint bindPoint
@ -1481,7 +1486,7 @@ namespace dxvk {
StartSlot + i);
m_context->bindResourceBuffer(
bindPoint, slotId, bindingInfo);
bindPoint, slotId, bufferSlice);
}
}
}

View File

@ -1147,14 +1147,17 @@ namespace dxvk {
void D3D11Device::InitBuffer(
D3D11Buffer* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
const Rc<DxvkBuffer> buffer = pBuffer->GetDXVKBuffer();
const DxvkBufferSlice bufferSlice
= pBuffer->GetCurrentBufferSlice();
if (pInitialData != nullptr) {
std::lock_guard<std::mutex> lock(m_resourceInitMutex);;
m_resourceInitContext->beginRecording(
m_dxvkDevice->createCommandList());
m_resourceInitContext->updateBuffer(
buffer, 0, buffer->info().size,
bufferSlice.buffer(),
bufferSlice.bufferOffset(),
bufferSlice.bufferRange(),
pInitialData->pSysMem);
m_dxvkDevice->submitCommandList(
m_resourceInitContext->endRecording(),

View File

@ -14,6 +14,7 @@
#include "../util/util_enum.h"
#include "../util/util_error.h"
#include "../util/util_math.h"
#include "../util/util_string.h"
#include <dxgi1_2.h>

View File

@ -57,55 +57,6 @@ namespace dxvk {
m_layer = pLayer;
}
DxgiBufferResource::DxgiBufferResource(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkBufferCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags)
: Base(pDevice, usageFlags) {
m_buffer = pDevice->GetDXVKDevice()->createBuffer(
*pCreateInfo, memoryFlags);
}
DxgiBufferResource::~DxgiBufferResource() {
}
HRESULT STDMETHODCALLTYPE DxgiBufferResource::QueryInterface(REFIID riid, void** ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
COM_QUERY_IFACE(riid, ppvObject, IDXGIObject);
COM_QUERY_IFACE(riid, ppvObject, IDXGIDeviceSubObject);
COM_QUERY_IFACE(riid, ppvObject, IDXGIResource);
COM_QUERY_IFACE(riid, ppvObject, IDXGIBufferResourcePrivate);
if (m_layer != nullptr)
return m_layer->QueryInterface(riid, ppvObject);
Logger::err("DxgiBufferResource::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DxgiBufferResource::GetParent(REFIID riid, void** ppParent) {
Logger::err("DxgiBufferResource::GetParent: Unknown interface query");
return E_NOINTERFACE;
}
Rc<DxvkBuffer> STDMETHODCALLTYPE DxgiBufferResource::GetDXVKBuffer() {
return m_buffer;
}
void STDMETHODCALLTYPE DxgiBufferResource::SetResourceLayer(IUnknown* pLayer) {
m_layer = pLayer;
}
}
@ -127,21 +78,4 @@ extern "C" {
}
}
DLLEXPORT HRESULT __stdcall DXGICreateBufferResourcePrivate(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkBufferCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags,
IDXGIBufferResourcePrivate** ppResource) {
try {
*ppResource = dxvk::ref(new dxvk::DxgiBufferResource(
pDevice, pCreateInfo, memoryFlags, usageFlags));
return S_OK;
} catch (const dxvk::DxvkError& e) {
dxvk::Logger::err(e.message());
return DXGI_ERROR_UNSUPPORTED;
}
}
}

View File

@ -100,45 +100,6 @@ namespace dxvk {
IUnknown* m_layer = nullptr;
};
/**
* \brief Buffer resource
*
* Stores a DXVK buffer and provides a method to retrieve
* it. D3D buffers will be backed by a buffer resource.
*/
class DxgiBufferResource : public DxgiResource<IDXGIBufferResourcePrivate> {
using Base = DxgiResource<IDXGIBufferResourcePrivate>;
public:
DxgiBufferResource(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkBufferCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags);
~DxgiBufferResource();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void **ppvObject) final;
HRESULT STDMETHODCALLTYPE GetParent(
REFIID riid,
void **ppParent) final;
Rc<DxvkBuffer> STDMETHODCALLTYPE GetDXVKBuffer() final;
void STDMETHODCALLTYPE SetResourceLayer(
IUnknown* pLayer) final;
private:
Rc<DxvkBuffer> m_buffer;
IUnknown* m_layer = nullptr;
};
}
@ -152,11 +113,4 @@ extern "C" {
UINT usageFlags,
IDXGIImageResourcePrivate** ppResource);
DLLEXPORT HRESULT __stdcall DXGICreateBufferResourcePrivate(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkBufferCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags,
IDXGIBufferResourcePrivate** ppResource);
}

View File

@ -176,7 +176,7 @@ namespace dxvk {
m_offset(rangeOffset),
m_length(rangeLength) { }
Rc<DxvkResource> resource() const {
Rc<DxvkBuffer> buffer() const {
return m_buffer;
}

View File

@ -446,9 +446,6 @@ namespace dxvk {
const void* data) {
this->renderPassEnd();
if (size == VK_WHOLE_SIZE)
size = buffer->info().size - offset;
if (size != 0) {
// Vulkan specifies that small amounts of data (up to 64kB)
// can be copied to a buffer directly. Anything larger than
@ -907,7 +904,7 @@ namespace dxvk {
m_state.vi.indexBuffer.bufferOffset(),
m_state.vi.indexType);
m_cmd->trackResource(
m_state.vi.indexBuffer.resource());
m_state.vi.indexBuffer.buffer());
}
}
}
@ -925,7 +922,7 @@ namespace dxvk {
if (handle != VK_NULL_HANDLE) {
m_cmd->cmdBindVertexBuffers(i, 1, &handle, &offset);
m_cmd->trackResource(vbo.resource());
m_cmd->trackResource(vbo.buffer());
}
}
}

View File

@ -9,4 +9,9 @@ namespace dxvk {
return n;
}
template<typename T>
T align(T what, T to) {
return (what + to - 1) & ~(to - 1);
}
}