From 5c9ea3ede3782692a43a21f50959e0bcc1f8bee8 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 28 Sep 2016 12:16:19 +0200 Subject: [PATCH] libs/vkd3d: Implement d3d12_device_CreateGraphicsPipelineState(). --- include/d3d12.idl | 2 + libs/vkd3d/device.c | 12 +- libs/vkd3d/state.c | 406 ++++++++++++++++++++++++++++++++++--- libs/vkd3d/vkd3d_private.h | 36 +++- 4 files changed, 429 insertions(+), 27 deletions(-) diff --git a/include/d3d12.idl b/include/d3d12.idl index d4051e96..c2531fc1 100644 --- a/include/d3d12.idl +++ b/include/d3d12.idl @@ -26,6 +26,7 @@ import "dxgibase.h"; #include "unknown.idl" +const UINT D3D12_APPEND_ALIGNED_ELEMENT = 0xffffffff; const UINT D3D12_DEFAULT_DEPTH_BIAS = 0; cpp_quote("#define D3D12_DEFAULT_DEPTH_BIAS_CLAMP (0.0f)") cpp_quote("#define D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS (0.0f)") @@ -37,6 +38,7 @@ const UINT D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32; const UINT D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES = 0xffffffff; const UINT D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT = 8; const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256; +const UINT D3D12_VS_INPUT_REGISTER_COUNT = 32; [uuid(8BA5FB08-5195-40E2-AC58-0D989C3A0102), object, local, pointer_default(unique)] interface ID3D10Blob : IUnknown diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 0a41f5f7..c850579f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -580,10 +580,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Devic static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device *iface, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state) { - FIXME("iface %p, desc %p, riid %s, pipeline_state %p stub!\n", + struct d3d12_device *device = impl_from_ID3D12Device(iface); + struct d3d12_pipeline_state *object; + HRESULT hr; + + TRACE("iface %p, desc %p, riid %s, pipeline_state %p.\n", iface, desc, debugstr_guid(riid), pipeline_state); - return E_NOTIMPL; + if (FAILED(hr = d3d12_pipeline_state_create_graphics(device, desc, &object))) + return hr; + + return return_interface((IUnknown *)&object->ID3D12PipelineState_iface, + &IID_ID3D12PipelineState, riid, pipeline_state); } static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device *iface, diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 0b1b55e0..95fa8657 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1,5 +1,6 @@ /* * Copyright 2016 Józef Kucia for CodeWeavers + * Copyright 2016 Henri Verbeet for CodeWeavers * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -254,8 +255,20 @@ static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState { struct d3d12_device *device = state->device; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + unsigned int i; - VK_CALL(vkDestroyPipeline(device->vk_device, state->vk_pipeline, NULL)); + if (state->vk_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) + { + for (i = 0; i < state->u.graphics.stage_count; ++i) + { + VK_CALL(vkDestroyShaderModule(device->vk_device, state->u.graphics.stages[i].module, NULL)); + } + VK_CALL(vkDestroyRenderPass(device->vk_device, state->u.graphics.render_pass, NULL)); + } + else if (state->vk_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) + { + VK_CALL(vkDestroyPipeline(device->vk_device, state->u.compute.vk_pipeline, NULL)); + } vkd3d_free(state); @@ -339,15 +352,42 @@ struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12Pipeline return impl_from_ID3D12PipelineState(iface); } +static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelineShaderStageCreateInfo *stage_desc, + enum VkShaderStageFlagBits stage, const D3D12_SHADER_BYTECODE *code) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct VkShaderModuleCreateInfo shader_desc; + VkResult vr; + + stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage_desc->pNext = NULL; + stage_desc->flags = 0; + stage_desc->stage = stage; + stage_desc->pName = "main"; + stage_desc->pSpecializationInfo = NULL; + + shader_desc.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_desc.pNext = NULL; + shader_desc.flags = 0; + shader_desc.codeSize = code->BytecodeLength; + shader_desc.pCode = code->pShaderBytecode; + if ((vr = VK_CALL(vkCreateShaderModule(device->vk_device, &shader_desc, NULL, &stage_desc->module))) < 0) + { + WARN("Failed to create Vulkan shader module, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } + + return S_OK; +} + static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *state, struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; struct d3d12_root_signature *root_signature; VkComputePipelineCreateInfo pipeline_info; - VkShaderModuleCreateInfo shader_info; - VkShaderModule shader; VkResult vr; + HRESULT hr; state->ID3D12PipelineState_iface.lpVtbl = &d3d12_pipeline_state_vtbl; state->refcount = 1; @@ -358,41 +398,25 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st return E_INVALIDARG; } - shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_info.pNext = NULL; - shader_info.flags = 0; - shader_info.codeSize = desc->CS.BytecodeLength; - shader_info.pCode = desc->CS.pShaderBytecode; - - if ((vr = VK_CALL(vkCreateShaderModule(device->vk_device, &shader_info, NULL, &shader)))) - { - WARN("Failed to create Vulkan shader module, vr %d.\n", vr); - return hresult_from_vk_result(vr); - } - pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; pipeline_info.pNext = NULL; pipeline_info.flags = 0; - pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_info.stage.pNext = NULL; - pipeline_info.stage.flags = 0; - pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - pipeline_info.stage.module = shader; - pipeline_info.stage.pName = "main"; - pipeline_info.stage.pSpecializationInfo = NULL; + if (FAILED(hr = create_shader_stage(device, &pipeline_info.stage, VK_SHADER_STAGE_COMPUTE_BIT, &desc->CS))) + return hr; pipeline_info.layout = root_signature->vk_pipeline_layout; pipeline_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_info.basePipelineIndex = -1; vr = VK_CALL(vkCreateComputePipelines(device->vk_device, VK_NULL_HANDLE, - 1, &pipeline_info, NULL, &state->vk_pipeline)); - VK_CALL(vkDestroyShaderModule(device->vk_device, shader, NULL)); + 1, &pipeline_info, NULL, &state->u.compute.vk_pipeline)); + VK_CALL(vkDestroyShaderModule(device->vk_device, pipeline_info.stage.module, NULL)); if (vr) { WARN("Failed to create Vulkan compute pipeline, vr %d.\n", vr); return hresult_from_vk_result(vr); } + state->vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; state->device = device; ID3D12Device_AddRef(&device->ID3D12Device_iface); @@ -420,3 +444,337 @@ HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device, return S_OK; } + +static enum VkPolygonMode vk_polygon_mode_from_d3d12(D3D12_FILL_MODE mode) +{ + switch (mode) + { + case D3D12_FILL_MODE_WIREFRAME: + return VK_POLYGON_MODE_LINE; + case D3D12_FILL_MODE_SOLID: + return VK_POLYGON_MODE_FILL; + default: + FIXME("Unhandled fill mode %#x.\n", mode); + return VK_POLYGON_MODE_FILL; + } +} + +static enum VkCullModeFlagBits vk_cull_mode_from_d3d12(D3D12_CULL_MODE mode) +{ + switch (mode) + { + case D3D12_CULL_MODE_NONE: + return VK_CULL_MODE_NONE; + case D3D12_CULL_MODE_FRONT: + return VK_CULL_MODE_FRONT_BIT; + case D3D12_CULL_MODE_BACK: + return VK_CULL_MODE_BACK_BIT; + default: + FIXME("Unhandled cull mode %#x.\n", mode); + return VK_CULL_MODE_NONE; + } +} + +static void rs_desc_from_d3d12(struct VkPipelineRasterizationStateCreateInfo *vk_desc, + const D3D12_RASTERIZER_DESC *d3d12_desc) +{ + vk_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + vk_desc->pNext = NULL; + vk_desc->flags = 0; + vk_desc->depthClampEnable = !d3d12_desc->DepthClipEnable; + vk_desc->rasterizerDiscardEnable = VK_FALSE; + vk_desc->polygonMode = vk_polygon_mode_from_d3d12(d3d12_desc->FillMode); + vk_desc->cullMode = vk_cull_mode_from_d3d12(d3d12_desc->CullMode); + vk_desc->frontFace = d3d12_desc->FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; + vk_desc->depthBiasEnable = VK_TRUE; + vk_desc->depthBiasConstantFactor = d3d12_desc->DepthBias; + vk_desc->depthBiasClamp = d3d12_desc->DepthBiasClamp; + vk_desc->depthBiasSlopeFactor = d3d12_desc->SlopeScaledDepthBias; + vk_desc->lineWidth = 1.0f; + + if (d3d12_desc->MultisampleEnable) + FIXME("Ignoring MultisampleEnable %#x.\n", d3d12_desc->MultisampleEnable); + if (d3d12_desc->AntialiasedLineEnable) + FIXME("Ignoring AntialiasedLineEnable %#x.\n", d3d12_desc->AntialiasedLineEnable); + if (d3d12_desc->ForcedSampleCount) + FIXME("Ignoring ForcedSampleCount %#x.\n", d3d12_desc->ForcedSampleCount); + if (d3d12_desc->ConservativeRaster) + FIXME("Ignoring ConservativeRaster %#x.\n", d3d12_desc->ConservativeRaster); +} + +static enum VkBlendFactor vk_blend_factor_from_d3d12(D3D12_BLEND blend, bool alpha) +{ + switch (blend) + { + case D3D12_BLEND_ZERO: + return VK_BLEND_FACTOR_ZERO; + case D3D12_BLEND_ONE: + return VK_BLEND_FACTOR_ONE; + case D3D12_BLEND_SRC_COLOR: + return VK_BLEND_FACTOR_SRC_COLOR; + case D3D12_BLEND_INV_SRC_COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + case D3D12_BLEND_SRC_ALPHA: + return VK_BLEND_FACTOR_SRC_ALPHA; + case D3D12_BLEND_INV_SRC_ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case D3D12_BLEND_DEST_ALPHA: + return VK_BLEND_FACTOR_DST_ALPHA; + case D3D12_BLEND_INV_DEST_ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + case D3D12_BLEND_DEST_COLOR: + return VK_BLEND_FACTOR_DST_COLOR; + case D3D12_BLEND_INV_DEST_COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + case D3D12_BLEND_SRC_ALPHA_SAT: + return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; + case D3D12_BLEND_BLEND_FACTOR: + if (alpha) + return VK_BLEND_FACTOR_CONSTANT_ALPHA; + return VK_BLEND_FACTOR_CONSTANT_COLOR; + case D3D12_BLEND_INV_BLEND_FACTOR: + if (alpha) + return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; + return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; + case D3D12_BLEND_SRC1_COLOR: + return VK_BLEND_FACTOR_SRC1_COLOR; + case D3D12_BLEND_INV_SRC1_COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; + case D3D12_BLEND_SRC1_ALPHA: + return VK_BLEND_FACTOR_SRC1_ALPHA; + case D3D12_BLEND_INV_SRC1_ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; + default: + FIXME("Unhandled blend %#x.\n", blend); + return VK_BLEND_FACTOR_ZERO; + } +} + +static enum VkBlendOp vk_blend_op_from_d3d12(D3D12_BLEND_OP op) +{ + switch (op) + { + case D3D12_BLEND_OP_ADD: + return VK_BLEND_OP_ADD; + case D3D12_BLEND_OP_SUBTRACT: + return VK_BLEND_OP_SUBTRACT; + case D3D12_BLEND_OP_REV_SUBTRACT: + return VK_BLEND_OP_REVERSE_SUBTRACT; + case D3D12_BLEND_OP_MIN: + return VK_BLEND_OP_MIN; + case D3D12_BLEND_OP_MAX: + return VK_BLEND_OP_MAX; + default: + FIXME("Unhandled blend op %#x.\n", op); + return VK_BLEND_OP_ADD; + } +} + +static void blend_attachment_from_d3d12(struct VkPipelineColorBlendAttachmentState *vk_desc, + const D3D12_RENDER_TARGET_BLEND_DESC *d3d12_desc) +{ + vk_desc->blendEnable = d3d12_desc->BlendEnable; + vk_desc->srcColorBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->SrcBlend, false); + vk_desc->dstColorBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->DestBlend, false); + vk_desc->colorBlendOp = vk_blend_op_from_d3d12(d3d12_desc->BlendOp); + vk_desc->srcAlphaBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->SrcBlendAlpha, true); + vk_desc->dstAlphaBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->DestBlendAlpha, true); + vk_desc->alphaBlendOp = vk_blend_op_from_d3d12(d3d12_desc->BlendOpAlpha);; + vk_desc->colorWriteMask = 0; + if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_RED) + vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_R_BIT; + if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_GREEN) + vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_G_BIT; + if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_BLUE) + vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_B_BIT; + if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_ALPHA) + vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_A_BIT; + + if (d3d12_desc->LogicOpEnable) + FIXME("Ignoring LogicOpEnable %#x.\n", d3d12_desc->LogicOpEnable); +} + +static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state, + struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc) +{ + struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics; + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct VkSubpassDescription sub_pass_desc; + struct VkRenderPassCreateInfo pass_desc; + const struct vkd3d_format *format; + unsigned int i; + VkResult vr; + HRESULT hr; + + static const struct + { + enum VkShaderStageFlagBits stage; + ptrdiff_t offset; + } + shader_stages[] = + { + {VK_SHADER_STAGE_VERTEX_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, VS)}, + {VK_SHADER_STAGE_FRAGMENT_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, PS)}, + {VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, DS)}, + {VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, HS)}, + {VK_SHADER_STAGE_GEOMETRY_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, GS)}, + }; + + state->ID3D12PipelineState_iface.lpVtbl = &d3d12_pipeline_state_vtbl; + state->refcount = 1; + + for (i = 0, graphics->stage_count = 0; i < ARRAY_SIZE(shader_stages); ++i) + { + const D3D12_SHADER_BYTECODE *b = (const void *)((uintptr_t)desc + shader_stages[i].offset); + + if (!b->pShaderBytecode) + continue; + + if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count], + shader_stages[i].stage, b))) + goto fail; + + ++graphics->stage_count; + } + + graphics->attribute_count = desc->InputLayout.NumElements; + if (graphics->attribute_count > ARRAY_SIZE(graphics->attributes)) + { + FIXME("InputLayout.NumElements %zu > %zu, ignoring extra elements.\n", + graphics->attribute_count, ARRAY_SIZE(graphics->attributes)); + graphics->attribute_count = ARRAY_SIZE(graphics->attributes); + } + + for (i = 0; i < graphics->attribute_count; ++i) + { + const D3D12_INPUT_ELEMENT_DESC *e = &desc->InputLayout.pInputElementDescs[i]; + + if (!(format = vkd3d_get_format(e->Format))) + { + WARN("Invalid DXGI format %#x.\n", e->Format); + hr = E_FAIL; + goto fail; + } + + graphics->attributes[i].location = i; + graphics->attributes[i].binding = e->InputSlot; + graphics->attributes[i].format = format->vk_format; + if (e->AlignedByteOffset == D3D12_APPEND_ALIGNED_ELEMENT) + FIXME("D3D12_APPEND_ALIGNED_ELEMENT not implemented.\n"); + graphics->attributes[i].offset = e->AlignedByteOffset; + if (e->InputSlotClass != D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) + FIXME("Ignoring input slot class %#x on input element %u.\n", e->InputSlotClass, i); + } + + graphics->attachment_count = desc->NumRenderTargets; + if (graphics->attachment_count > ARRAY_SIZE(graphics->attachments)) + { + FIXME("NumRenderTargets %zu > %zu, ignoring extra formats.\n", + graphics->attachment_count, ARRAY_SIZE(graphics->attachments)); + graphics->attachment_count = ARRAY_SIZE(graphics->attachments); + } + + for (i = 0; i < graphics->attachment_count; ++i) + { + unsigned int blend_idx = desc->BlendState.IndependentBlendEnable ? i : 0; + + if (!(format = vkd3d_get_format(desc->RTVFormats[i]))) + { + WARN("Invalid DXGI format %#x.\n", desc->RTVFormats[i]); + hr = E_FAIL; + goto fail; + } + + graphics->attachments[i].flags = 0; + graphics->attachments[i].format = format->vk_format; + graphics->attachments[i].samples = VK_SAMPLE_COUNT_1_BIT; + graphics->attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + graphics->attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + graphics->attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + graphics->attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + graphics->attachments[i].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + graphics->attachments[i].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + graphics->attachment_references[i].attachment = i; + graphics->attachment_references[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + blend_attachment_from_d3d12(&graphics->blend_attachments[i], &desc->BlendState.RenderTarget[blend_idx]); + } + + sub_pass_desc.flags = 0; + sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + sub_pass_desc.inputAttachmentCount = 0; + sub_pass_desc.pInputAttachments = NULL; + sub_pass_desc.colorAttachmentCount = graphics->attachment_count; + sub_pass_desc.pColorAttachments = graphics->attachment_references; + sub_pass_desc.pResolveAttachments = NULL; + sub_pass_desc.pDepthStencilAttachment = NULL; + sub_pass_desc.preserveAttachmentCount = 0; + sub_pass_desc.pPreserveAttachments = NULL; + + pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + pass_desc.pNext = NULL; + pass_desc.flags = 0; + pass_desc.attachmentCount = graphics->attachment_count; + pass_desc.pAttachments = graphics->attachments; + pass_desc.subpassCount = 1; + pass_desc.pSubpasses = &sub_pass_desc; + pass_desc.dependencyCount = 0; + pass_desc.pDependencies = NULL; + if ((vr = VK_CALL(vkCreateRenderPass(device->vk_device, &pass_desc, NULL, &graphics->render_pass))) < 0) + { + WARN("Failed to create Vulkan render pass, vr %d.\n", vr); + hr = hresult_from_vk_result(vr); + goto fail; + } + + rs_desc_from_d3d12(&graphics->rs_desc, &desc->RasterizerState); + + graphics->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + graphics->ms_desc.pNext = NULL; + graphics->ms_desc.flags = 0; + graphics->ms_desc.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + graphics->ms_desc.sampleShadingEnable = VK_FALSE; + graphics->ms_desc.minSampleShading = 0.0f; + graphics->ms_desc.pSampleMask = NULL; + graphics->ms_desc.alphaToCoverageEnable = desc->BlendState.AlphaToCoverageEnable; + graphics->ms_desc.alphaToOneEnable = VK_FALSE; + + graphics->root_signature = unsafe_impl_from_ID3D12RootSignature(desc->pRootSignature); + + state->vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; + state->device = device; + ID3D12Device_AddRef(&device->ID3D12Device_iface); + + return S_OK; + +fail: + for (i = 0; i < graphics->stage_count; ++i) + { + VK_CALL(vkDestroyShaderModule(device->vk_device, state->u.graphics.stages[i].module, NULL)); + } + + return hr; +} + +HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device, + const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) +{ + struct d3d12_pipeline_state *object; + HRESULT hr; + + if (!(object = vkd3d_malloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = d3d12_pipeline_state_init_graphics(object, device, desc))) + { + vkd3d_free(object); + return hr; + } + + TRACE("Created graphics pipeline state %p.\n", object); + + *state = object; + + return S_OK; +} diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 3901fb4a..2d137b65 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -37,6 +37,8 @@ #define VKD3D_DESCRIPTOR_MAGIC_FREE 0x00000000u #define VKD3D_DESCRIPTOR_MAGIC_RTV 0x00565452u +#define VKD3D_MAX_SHADER_STAGES 5u + struct d3d12_command_list; struct d3d12_device; @@ -178,19 +180,51 @@ struct d3d12_root_signature HRESULT d3d12_root_signature_create(struct d3d12_device *device, const D3D12_ROOT_SIGNATURE_DESC *desc, struct d3d12_root_signature **root_signature) DECLSPEC_HIDDEN; +struct d3d12_graphics_pipeline_state +{ + struct VkPipelineShaderStageCreateInfo stages[VKD3D_MAX_SHADER_STAGES]; + size_t stage_count; + + struct VkVertexInputAttributeDescription attributes[D3D12_VS_INPUT_REGISTER_COUNT]; + size_t attribute_count; + + struct VkAttachmentDescription attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + struct VkAttachmentReference attachment_references[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + struct VkPipelineColorBlendAttachmentState blend_attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + size_t attachment_count; + VkRenderPass render_pass; + + struct VkPipelineRasterizationStateCreateInfo rs_desc; + struct VkPipelineMultisampleStateCreateInfo ms_desc; + + struct d3d12_root_signature *root_signature; +}; + +struct d3d12_compute_pipeline_state +{ + VkPipeline vk_pipeline; +}; + /* ID3D12PipelineState */ struct d3d12_pipeline_state { ID3D12PipelineState ID3D12PipelineState_iface; LONG refcount; - VkPipeline vk_pipeline; + union + { + struct d3d12_graphics_pipeline_state graphics; + struct d3d12_compute_pipeline_state compute; + } u; + VkPipelineBindPoint vk_bind_point; struct d3d12_device *device; }; HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN; +HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device, + const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN; struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface) DECLSPEC_HIDDEN; /* ID3D12CommandAllocator */