[d3d11] Implemented small buffer uploads

This commit is contained in:
Philip Rebohle 2017-12-07 18:51:41 +01:00
parent 2a2e179b91
commit 27e63cbdc6
10 changed files with 104 additions and 2 deletions

View File

@ -1259,6 +1259,8 @@ namespace dxvk {
std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
// FIXME compute proper viewport coordinates (vertical origin).
// D3D11's coordinate system has its origin in the bottom left.
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
const D3D11_VIEWPORT& vp = m_state.rs.viewports.at(i);

View File

@ -33,6 +33,7 @@ namespace dxvk {
m_presentDevice->SetDeviceLayer(this);
m_context = new D3D11DeviceContext(this, m_dxvkDevice);
m_resourceInitContext = m_dxvkDevice->createContext();
}
@ -131,6 +132,8 @@ namespace dxvk {
*ppBuffer = ref(new D3D11Buffer(
this, buffer.ptr(), *pDesc));
InitBuffer(buffer.ptr(), pInitialData);
}
return S_OK;
@ -373,7 +376,7 @@ namespace dxvk {
// Create vertex input binding description.
VkVertexInputBindingDescription binding;
binding.binding = pInputElementDescs[i].InputSlot;
binding.stride = 0;
binding.stride = 12;
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) {
@ -808,6 +811,25 @@ namespace dxvk {
}
void D3D11Device::InitBuffer(
IDXGIBufferResourcePrivate* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
const Rc<DxvkBuffer> buffer = pBuffer->GetDXVKBuffer();
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,
pInitialData->pSysMem);
m_dxvkDevice->submitCommandList(
m_resourceInitContext->endRecording(),
nullptr, nullptr);
}
}
VkPipelineStageFlags D3D11Device::GetEnabledShaderStages() const {
VkPipelineStageFlags enabledShaderPipelineStages
= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT

View File

@ -244,6 +244,9 @@ namespace dxvk {
Com<ID3D11DeviceContext> m_context;
std::mutex m_resourceInitMutex;
Rc<DxvkContext> m_resourceInitContext;
D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
HRESULT CreateShaderModule(
@ -252,6 +255,10 @@ namespace dxvk {
size_t BytecodeLength,
ID3D11ClassLinkage* pClassLinkage);
void InitBuffer(
IDXGIBufferResourcePrivate* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData);
VkPipelineStageFlags GetEnabledShaderStages() const;
VkMemoryPropertyFlags GetMemoryFlagsForUsage(

View File

@ -42,6 +42,7 @@ namespace dxvk {
// If requested by the user, dump both the raw DXBC
// shader and the compiled SPIR-V module to a file.
const std::string dumpPath = GetEnvVar(L"DXVK_SHADER_DUMP_PATH");
const std::string readPath = GetEnvVar(L"DXVK_SHADER_READ_PATH");
if (dumpPath.size() != 0) {
const std::string baseName = str::format(dumpPath, "/",
@ -55,6 +56,16 @@ namespace dxvk {
std::ios_base::binary | std::ios_base::trunc));
}
if (readPath.size() != 0) {
const std::string baseName = str::format(readPath, "/",
ConstructFileName(ComputeShaderHash(pShaderBytecode, BytecodeLength),
module.version().type()));
spirvCode = SpirvCodeBuffer(std::ifstream(
str::format(baseName, ".spv"),
std::ios_base::binary));
}
m_shader = pDevice->GetDXVKDevice()->createShader(
module.version().shaderStage(),
resourceSlots.size(),

View File

@ -208,6 +208,7 @@ namespace dxvk {
std::vector<const char*> extOptional = { };
std::vector<const char*> extRequired = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
};
const vk::NameSet extensionsAvailable

View File

@ -260,6 +260,16 @@ namespace dxvk {
}
void DxvkCommandList::cmdUpdateBuffer(
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void* pData) {
m_vkd->vkCmdUpdateBuffer(m_buffer,
dstBuffer, dstOffset, dataSize, pData);
}
void DxvkCommandList::cmdSetScissor(
uint32_t firstScissor,
uint32_t scissorCount,

View File

@ -154,6 +154,12 @@ namespace dxvk {
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
void cmdUpdateBuffer(
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void* pData);
void cmdSetScissor(
uint32_t firstScissor,
uint32_t scissorCount,

View File

@ -335,6 +335,34 @@ namespace dxvk {
}
void DxvkContext::updateBuffer(
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize size,
const void* data) {
if (size == 0)
return;
if (size <= 65536) {
m_cmd->cmdUpdateBuffer(
buffer->handle(),
offset, size, data);
} else {
// TODO implement
Logger::err("DxvkContext::updateBuffer: Large updates not yet supported");
}
m_barriers.accessBuffer(
buffer, offset, size,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
buffer->info().stages,
buffer->info().access);
m_barriers.recordCommands(m_cmd);
}
void DxvkContext::setViewports(
uint32_t viewportCount,
const VkViewport* viewports,

View File

@ -235,6 +235,21 @@ namespace dxvk {
const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources);
/**
* \brief Updates a buffer
*
* Copies data from the host into a buffer.
* \param [in] buffer Destination buffer
* \param [in] offset Offset of sub range to update
* \param [in] size Length of sub range to update
* \param [in] data Data to upload
*/
void updateBuffer(
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize size,
const void* data);
/**
* \brief Sets viewports
*

View File

@ -108,7 +108,7 @@ namespace dxvk {
vpInfo.viewportCount = state.viewportCount;
vpInfo.pViewports = nullptr;
vpInfo.scissorCount = state.viewportCount;
vpInfo.pViewports = nullptr;
vpInfo.pScissors = nullptr;
VkPipelineDynamicStateCreateInfo dsInfo;
dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;