diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 4e559e42..05a940cc 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1259,6 +1259,8 @@ namespace dxvk { std::array viewports; std::array 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); diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 105cf091..7ff225b7 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -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 buffer = pBuffer->GetDXVKBuffer(); + + if (pInitialData != nullptr) { + std::lock_guard 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 diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index c703ce48..4c5ba348 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -244,6 +244,9 @@ namespace dxvk { Com m_context; + std::mutex m_resourceInitMutex; + Rc m_resourceInitContext; + D3D11StateObjectSet 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( diff --git a/src/d3d11/d3d11_shader.cpp b/src/d3d11/d3d11_shader.cpp index 69d6d045..1c9dca61 100644 --- a/src/d3d11/d3d11_shader.cpp +++ b/src/d3d11/d3d11_shader.cpp @@ -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(), diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index aa98f7b2..d9bf4a82 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -208,6 +208,7 @@ namespace dxvk { std::vector extOptional = { }; std::vector extRequired = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_MAINTENANCE1_EXTENSION_NAME, }; const vk::NameSet extensionsAvailable diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 67d7eac6..63bfba04 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -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, diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index ab72142d..5ba73218 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -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, diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index c4bc95e9..678715cc 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -335,6 +335,34 @@ namespace dxvk { } + void DxvkContext::updateBuffer( + const Rc& 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, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index db5bcb57..7dac9faf 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -235,6 +235,21 @@ namespace dxvk { const Rc& 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& buffer, + VkDeviceSize offset, + VkDeviceSize size, + const void* data); + /** * \brief Sets viewports * diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 50b9d1f0..0029f063 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -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;