From a47ebd6ed5120c40325aa6341c282ddcdda34834 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 20 Nov 2017 15:35:29 +0100 Subject: [PATCH] [dxvk] Proper blend state and viewport state setup --- src/dxvk/dxvk_buffer.h | 4 +- src/dxvk/dxvk_cmdlist.cpp | 18 +++++ src/dxvk/dxvk_cmdlist.h | 10 +++ src/dxvk/dxvk_constant_state.cpp | 19 ++++- src/dxvk/dxvk_constant_state.h | 3 +- src/dxvk/dxvk_context.cpp | 42 +++++++++-- src/dxvk/dxvk_context.h | 12 +++ src/dxvk/dxvk_device.cpp | 7 ++ src/dxvk/dxvk_device.h | 11 +++ src/dxvk/dxvk_recorder.h | 10 +++ src/dxvk/dxvk_renderpass.cpp | 2 +- src/spirv/spirv_code_buffer.cpp | 6 ++ src/spirv/spirv_code_buffer.h | 1 + tests/dxvk/test_dxvk_triangle.cpp | 120 +++++++++++++++++++++++++++++- 14 files changed, 251 insertions(+), 14 deletions(-) diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index 780bf358..b08ea3d8 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -110,7 +110,9 @@ namespace dxvk { } VkBuffer bufferHandle() const { - return m_buffer->handle(); + return m_buffer != nullptr + ? m_buffer->handle() + : VK_NULL_HANDLE; } size_t bufferOffset() const { diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 3d8c2717..4161fb6c 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -201,4 +201,22 @@ namespace dxvk { imageMemoryBarrierCount, pImageMemoryBarriers); } + + void DxvkCommandList::cmdSetScissor( + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* scissors) { + m_vkd->vkCmdSetScissor(m_buffer, + firstScissor, scissorCount, scissors); + } + + + void DxvkCommandList::cmdSetViewport( + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* viewports) { + m_vkd->vkCmdSetViewport(m_buffer, + firstViewport, viewportCount, viewports); + } + } \ No newline at end of file diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index ef59f2bf..0de8b0d6 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -128,6 +128,16 @@ namespace dxvk { uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) final; + void cmdSetScissor( + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* scissors) final; + + void cmdSetViewport( + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* viewports) final; + private: Rc m_vkd; diff --git a/src/dxvk/dxvk_constant_state.cpp b/src/dxvk/dxvk_constant_state.cpp index 1a960d02..16e95c41 100644 --- a/src/dxvk/dxvk_constant_state.cpp +++ b/src/dxvk/dxvk_constant_state.cpp @@ -91,11 +91,26 @@ namespace dxvk { VkLogicOp logicOp, uint32_t attachmentCount, const VkPipelineColorBlendAttachmentState* attachmentState) { - m_attachments.resize(attachmentCount); - + // Copy the provided blend states into the array for (uint32_t i = 0; i < attachmentCount; i++) m_attachments.at(i) = attachmentState[i]; + // Use default values for the remaining attachments + for (uint32_t i = attachmentCount; i < m_attachments.size(); i++) { + m_attachments.at(i).blendEnable = VK_FALSE; + m_attachments.at(i).srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + m_attachments.at(i).dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + m_attachments.at(i).colorBlendOp = VK_BLEND_OP_ADD; + m_attachments.at(i).srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + m_attachments.at(i).dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + m_attachments.at(i).alphaBlendOp = VK_BLEND_OP_ADD; + m_attachments.at(i).colorWriteMask = + VK_COLOR_COMPONENT_R_BIT + | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + } + m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; m_info.pNext = nullptr; m_info.flags = 0; diff --git a/src/dxvk/dxvk_constant_state.h b/src/dxvk/dxvk_constant_state.h index 054b93c3..ef566140 100644 --- a/src/dxvk/dxvk_constant_state.h +++ b/src/dxvk/dxvk_constant_state.h @@ -152,7 +152,8 @@ namespace dxvk { private: - std::vector m_attachments; + std::array m_attachments; VkPipelineColorBlendStateCreateInfo m_info; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 4b311ec3..aafbf07f 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -133,6 +133,10 @@ namespace dxvk { firstVertex, firstInstance); this->commitGraphicsState(); + + m_cmd->cmdDraw( + vertexCount, instanceCount, + firstVertex, firstInstance); } @@ -146,6 +150,30 @@ namespace dxvk { firstIndex, vertexOffset, firstInstance); this->commitGraphicsState(); + + m_cmd->cmdDrawIndexed( + indexCount, instanceCount, + firstIndex, vertexOffset, + firstInstance); + } + + + void DxvkContext::setViewports( + uint32_t viewportCount, + const VkViewport* viewports, + const VkRect2D* scissorRects) { + if (m_state.vp.viewportCount != viewportCount) { + m_state.vp.viewportCount = viewportCount; + m_state.flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + for (uint32_t i = 0; i < viewportCount; i++) { + m_state.vp.viewports.at(i) = viewports[i]; + m_state.vp.scissorRects.at(i) = scissorRects[i]; + } + + m_cmd->cmdSetViewport(0, viewportCount, viewports); + m_cmd->cmdSetScissor (0, viewportCount, scissorRects); } @@ -281,12 +309,14 @@ namespace dxvk { if (m_state.flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) { m_state.flags.clr(DxvkContextFlag::GpDirtyIndexBuffer); - m_cmd->cmdBindIndexBuffer( - m_state.vi.indexBuffer.bufferHandle(), - m_state.vi.indexBuffer.bufferOffset(), - VK_INDEX_TYPE_UINT32); - m_cmd->trackResource( - m_state.vi.indexBuffer.resource()); + if (m_state.vi.indexBuffer.bufferHandle() != VK_NULL_HANDLE) { + m_cmd->cmdBindIndexBuffer( + m_state.vi.indexBuffer.bufferHandle(), + m_state.vi.indexBuffer.bufferOffset(), + VK_INDEX_TYPE_UINT32); + m_cmd->trackResource( + m_state.vi.indexBuffer.resource()); + } } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index c3ff8489..954dd21e 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -126,6 +126,18 @@ namespace dxvk { uint32_t vertexOffset, uint32_t firstInstance); + /** + * \brief Sets viewports + * + * \param [in] viewportCount Number of viewports + * \param [in] viewports The viewports + * \param [in] scissorRects Schissor rectangles + */ + void setViewports( + uint32_t viewportCount, + const VkViewport* viewports, + const VkRect2D* scissorRects); + /** * \brief Sets input assembly state * \param [in] state New state object diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index 611d7c28..c116fb27 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -79,6 +79,13 @@ namespace dxvk { } + Rc DxvkDevice::createShader( + VkShaderStageFlagBits stage, + const SpirvCodeBuffer& code) { + return new DxvkShader(m_vkd, stage, code); + } + + Rc DxvkDevice::createSwapchain( const Rc& surface, const DxvkSwapchainProperties& properties) { diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 217c41b0..455f907a 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -125,6 +125,17 @@ namespace dxvk { */ Rc createSemaphore(); + /** + * \brief Creates a shader module + * + * \param [in] stage Shader stage + * \param [in] code Shader code + * \returns New shader module + */ + Rc createShader( + VkShaderStageFlagBits stage, + const SpirvCodeBuffer& code); + /** * \brief Creates a swap chain * diff --git a/src/dxvk/dxvk_recorder.h b/src/dxvk/dxvk_recorder.h index 05c42f36..8f37076c 100644 --- a/src/dxvk/dxvk_recorder.h +++ b/src/dxvk/dxvk_recorder.h @@ -85,6 +85,16 @@ namespace dxvk { uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) = 0; + virtual void cmdSetScissor( + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* scissors) = 0; + + virtual void cmdSetViewport( + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* viewports) = 0; + }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 45f0dbe8..54bbec4d 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -47,7 +47,7 @@ namespace dxvk { TRACE(this, initialLayout, finalLayout); std::vector attachments; - VkAttachmentReference depthRef; + VkAttachmentReference depthRef; std::array colorRef; // Render passes may not require the previous diff --git a/src/spirv/spirv_code_buffer.cpp b/src/spirv/spirv_code_buffer.cpp index 4baa2b28..5d1e4965 100644 --- a/src/spirv/spirv_code_buffer.cpp +++ b/src/spirv/spirv_code_buffer.cpp @@ -9,6 +9,12 @@ namespace dxvk { SpirvCodeBuffer::~SpirvCodeBuffer() { } + SpirvCodeBuffer::SpirvCodeBuffer(uint32_t size, const uint32_t* data) { + m_code.resize(size); + std::memcpy(m_code.data(), data, size * sizeof(uint32_t)); + } + + SpirvCodeBuffer::SpirvCodeBuffer(std::istream&& stream) { stream.ignore(std::numeric_limits::max()); std::streamsize length = stream.gcount(); diff --git a/src/spirv/spirv_code_buffer.h b/src/spirv/spirv_code_buffer.h index 1e6e0368..5bfc681b 100644 --- a/src/spirv/spirv_code_buffer.h +++ b/src/spirv/spirv_code_buffer.h @@ -21,6 +21,7 @@ namespace dxvk { public: SpirvCodeBuffer(); + SpirvCodeBuffer(uint32_t size, const uint32_t* data); SpirvCodeBuffer(std::istream&& stream); ~SpirvCodeBuffer(); diff --git a/tests/dxvk/test_dxvk_triangle.cpp b/tests/dxvk/test_dxvk_triangle.cpp index 3441784b..1bba8991 100644 --- a/tests/dxvk/test_dxvk_triangle.cpp +++ b/tests/dxvk/test_dxvk_triangle.cpp @@ -11,6 +11,56 @@ using namespace dxvk; +const uint32_t vsCode[] = { + 0x07230203,0x00010000,0x00080001,0x00000024,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000001b,0x00030003, + 0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000,0x00060005,0x0000000b, + 0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x0000000b,0x00000000,0x505f6c67, + 0x7469736f,0x006e6f69,0x00070006,0x0000000b,0x00000001,0x505f6c67,0x746e696f,0x657a6953, + 0x00000000,0x00070006,0x0000000b,0x00000002,0x435f6c67,0x4470696c,0x61747369,0x0065636e, + 0x00070006,0x0000000b,0x00000003,0x435f6c67,0x446c6c75,0x61747369,0x0065636e,0x00030005, + 0x0000000d,0x00000000,0x00060005,0x0000001b,0x565f6c67,0x65747265,0x646e4978,0x00007865, + 0x00050005,0x0000001e,0x65646e69,0x6c626178,0x00000065,0x00050048,0x0000000b,0x00000000, + 0x0000000b,0x00000000,0x00050048,0x0000000b,0x00000001,0x0000000b,0x00000001,0x00050048, + 0x0000000b,0x00000002,0x0000000b,0x00000003,0x00050048,0x0000000b,0x00000003,0x0000000b, + 0x00000004,0x00030047,0x0000000b,0x00000002,0x00040047,0x0000001b,0x0000000b,0x0000002a, + 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, + 0x00040017,0x00000007,0x00000006,0x00000004,0x00040015,0x00000008,0x00000020,0x00000000, + 0x0004002b,0x00000008,0x00000009,0x00000001,0x0004001c,0x0000000a,0x00000006,0x00000009, + 0x0006001e,0x0000000b,0x00000007,0x00000006,0x0000000a,0x0000000a,0x00040020,0x0000000c, + 0x00000003,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000003,0x00040015,0x0000000e, + 0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x0004002b,0x00000008, + 0x00000010,0x00000003,0x0004001c,0x00000011,0x00000007,0x00000010,0x0004002b,0x00000006, + 0x00000012,0x00000000,0x0004002b,0x00000006,0x00000013,0x3f000000,0x0004002b,0x00000006, + 0x00000014,0x3f800000,0x0007002c,0x00000007,0x00000015,0x00000012,0x00000013,0x00000012, + 0x00000014,0x0004002b,0x00000006,0x00000016,0xbf000000,0x0007002c,0x00000007,0x00000017, + 0x00000013,0x00000016,0x00000012,0x00000014,0x0007002c,0x00000007,0x00000018,0x00000016, + 0x00000016,0x00000012,0x00000014,0x0006002c,0x00000011,0x00000019,0x00000015,0x00000017, + 0x00000018,0x00040020,0x0000001a,0x00000001,0x0000000e,0x0004003b,0x0000001a,0x0000001b, + 0x00000001,0x00040020,0x0000001d,0x00000007,0x00000011,0x00040020,0x0000001f,0x00000007, + 0x00000007,0x00040020,0x00000022,0x00000003,0x00000007,0x00050036,0x00000002,0x00000004, + 0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x0000001d,0x0000001e,0x00000007, + 0x0004003d,0x0000000e,0x0000001c,0x0000001b,0x0003003e,0x0000001e,0x00000019,0x00050041, + 0x0000001f,0x00000020,0x0000001e,0x0000001c,0x0004003d,0x00000007,0x00000021,0x00000020, + 0x00050041,0x00000022,0x00000023,0x0000000d,0x0000000f,0x0003003e,0x00000023,0x00000021, + 0x000100fd,0x00010038 +}; + +const uint32_t fsCode[] = { + 0x07230203,0x00010000,0x00080001,0x0000000c,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004, + 0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000, + 0x00040005,0x00000009,0x6f6c6f63,0x00000072,0x00040047,0x00000009,0x0000001e,0x00000000, + 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, + 0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007, + 0x0004003b,0x00000008,0x00000009,0x00000003,0x0004002b,0x00000006,0x0000000a,0x3f800000, + 0x0007002c,0x00000007,0x0000000b,0x0000000a,0x0000000a,0x0000000a,0x0000000a,0x00050036, + 0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0003003e,0x00000009, + 0x0000000b,0x000100fd,0x00010038 +}; + class TriangleApp { public: @@ -28,6 +78,50 @@ public: })), m_dxvkContext (m_dxvkDevice->createContext()), m_dxvkCommandList (m_dxvkDevice->createCommandList()) { + + m_dxvkContext->setInputAssemblyState( + new DxvkInputAssemblyState( + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + VK_FALSE)); + m_dxvkContext->setInputLayout( + new DxvkInputLayout(0, nullptr, 0, nullptr)); + m_dxvkContext->setRasterizerState( + new DxvkRasterizerState( + VK_FALSE, VK_FALSE, + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_COUNTER_CLOCKWISE, + VK_FALSE, 0.0f, 0.0f, 0.0f, + 1.0f)); + m_dxvkContext->setMultisampleState( + new DxvkMultisampleState( + VK_SAMPLE_COUNT_1_BIT, 0xFFFFFFFF, + VK_FALSE, VK_FALSE, VK_FALSE, 1.0f)); + m_dxvkContext->setDepthStencilState( + new DxvkDepthStencilState( + VK_FALSE, VK_FALSE, VK_FALSE, VK_FALSE, + VK_COMPARE_OP_ALWAYS, + VkStencilOpState(), + VkStencilOpState(), + 0.0f, 1.0f)); + m_dxvkContext->setBlendState( + new DxvkBlendState( + VK_FALSE, VK_LOGIC_OP_COPY, + 0, nullptr)); + + m_dxvkVertexShader = m_dxvkDevice->createShader( + VK_SHADER_STAGE_VERTEX_BIT, + SpirvCodeBuffer(_countof(vsCode), vsCode)); + m_dxvkFragmentShader = m_dxvkDevice->createShader( + VK_SHADER_STAGE_FRAGMENT_BIT, + SpirvCodeBuffer(_countof(fsCode), fsCode)); + + m_dxvkContext->bindShader( + VK_SHADER_STAGE_VERTEX_BIT, + m_dxvkVertexShader); + m_dxvkContext->bindShader( + VK_SHADER_STAGE_FRAGMENT_BIT, + m_dxvkFragmentShader); } ~TriangleApp() { @@ -44,12 +138,28 @@ public: m_dxvkContext->beginRecording(m_dxvkCommandList); m_dxvkContext->bindFramebuffer(fb); + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = 640.0f; + viewport.height = 480.0f; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset.x = 0; + scissor.offset.y = 0; + scissor.extent.width = 640; + scissor.extent.height = 480; + + m_dxvkContext->setViewports(1, &viewport, &scissor); + VkClearAttachment clearAttachment; clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; clearAttachment.colorAttachment = 0; - clearAttachment.clearValue.color.float32[0] = 1.0f; - clearAttachment.clearValue.color.float32[1] = 1.0f; - clearAttachment.clearValue.color.float32[2] = 1.0f; + clearAttachment.clearValue.color.float32[0] = 0.0f; + clearAttachment.clearValue.color.float32[1] = 0.0f; + clearAttachment.clearValue.color.float32[2] = 0.0f; clearAttachment.clearValue.color.float32[3] = 1.0f; VkClearRect clearArea; @@ -60,6 +170,7 @@ public: m_dxvkContext->clearRenderTarget( clearAttachment, clearArea); + m_dxvkContext->draw(3, 1, 0, 0); m_dxvkContext->endRecording(); auto fence = m_dxvkDevice->submitCommandList( @@ -78,6 +189,9 @@ private: Rc m_dxvkContext; Rc m_dxvkCommandList; + Rc m_dxvkVertexShader; + Rc m_dxvkFragmentShader; + }; LRESULT CALLBACK WindowProc(HWND hWnd,