From: Stefan Dösinger stefan@codeweavers.com
--- libs/vkd3d/device.c | 190 +++++++++++++++++++++++++++++++++++++ libs/vkd3d/state.c | 2 +- libs/vkd3d/vkd3d_private.h | 2 + 3 files changed, 193 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index d5cc50f0c..370a2f67f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -4424,7 +4424,196 @@ static bool d3d12_device_load_cache(struct vkd3d_shader_cache *cache, - offsetof(struct vkd3d_shader_cache_root_signature, dxbc[0]), NULL); break;
+ case SHADER_CACHE_ENTRY_COMPUTE_STATE: + case SHADER_CACHE_ENTRY_GRAPHICS_PIPELINE: + case SHADER_CACHE_ENTRY_GRAPHICS_STATE: + /* These are handled in a second pass */ + break; + + case SHADER_CACHE_ENTRY_VULKAN_BLOB: + break; + } + + return true; +} + +static bool d3d12_device_load_cache2(struct vkd3d_shader_cache *cache, + const void *key, uint32_t key_size, const void *value, + uint32_t value_size, void *context) +{ + const struct vkd3d_shader_cache_entry *e = value; + struct vkd3d_shader_cache_root_signature *rs; + struct d3d12_root_signature *d3d12_root_sig; + struct vkd3d_shader_cache_pipeline_state *s; + const struct vkd3d_graphics_pipeline_key *k; + D3D12_INPUT_ELEMENT_DESC *il_element = NULL; + D3D12_SO_DECLARATION_ENTRY *so_decl = NULL; + struct d3d12_pipeline_state_desc desc; + struct d3d12_device *device = context; + struct d3d12_pipeline_state *object; + uint32_t size, size2, pos = 0; + enum vkd3d_result ret; + unsigned int i; + HRESULT hr; + + TRACE("device %p got entry type (%c%c%c%c)\n", device, + e->type & 0xff, e->type >> 8 & 0xff, e->type >> 16 & 0xff, + e->type >> 24 & 0xff); + + switch (e->type) + { + case SHADER_CACHE_ENTRY_RENDER_PASS: + case SHADER_CACHE_ENTRY_ROOT_SIGNATURE: case SHADER_CACHE_ENTRY_VULKAN_BLOB: + /* Handled already */ + break; + + case SHADER_CACHE_ENTRY_COMPUTE_STATE: + /* TODO */ + break; + + case SHADER_CACHE_ENTRY_GRAPHICS_STATE: + /* Ignore, look it up when handling the full state */ + break; + + case SHADER_CACHE_ENTRY_GRAPHICS_PIPELINE: + k = key; + ret = vkd3d_shader_cache_get(cache, &k->state, sizeof(k->state), + NULL, &size); + if (ret) + { + FIXME("Did not find graphics state\n"); + break; + } + + s = vkd3d_malloc(size); + if (!s) + break; + ret = vkd3d_shader_cache_get(cache, &k->state, sizeof(k->state), + s, &size); + if (ret) + ERR("whut?\n"); + + ret = vkd3d_shader_cache_get(cache, &s->root_signature, sizeof(s->root_signature), + NULL, &size); + if (ret) + { + FIXME("Did not find root signature %lx for graphics pipeline\n", s->root_signature); + vkd3d_free(s); + break; + } + rs = vkd3d_malloc(size); + ret = vkd3d_shader_cache_get(cache, &s->root_signature, sizeof(s->root_signature), + rs, &size); + if (ret) + ERR("whut?\n"); + + size2 = sizeof(d3d12_root_sig); + ret = vkd3d_shader_cache_get(device->root_signature_cache, rs->dxbc, + size - offsetof(struct vkd3d_shader_cache_root_signature, dxbc[0]), + &d3d12_root_sig, &size2); + vkd3d_free(rs); + if (ret) + { + ERR("whut 2? Did not find root sig of hash %lx %d\n", s->root_signature, ret); + // return; + } + + memset(&desc, 0, sizeof(desc)); + desc.root_signature = &d3d12_root_sig->ID3D12RootSignature_iface; + + desc.vs.BytecodeLength = s->vs_size; + desc.vs.pShaderBytecode = s->vs_size ? s->data + pos : NULL; + pos += s->vs_size; + desc.ps.BytecodeLength = s->ps_size; + desc.ps.pShaderBytecode = s->ps_size ? s->data + pos : NULL; + pos += s->ps_size; + desc.ds.BytecodeLength = s->ds_size; + desc.ds.pShaderBytecode = s->ds_size ? s->data + pos : NULL; + pos += s->ds_size; + desc.hs.BytecodeLength = s->hs_size; + desc.hs.pShaderBytecode = s->hs_size ? s->data + pos : NULL; + pos += s->hs_size; + desc.gs.BytecodeLength = s->gs_size; + desc.gs.pShaderBytecode = s->gs_size ? s->data + pos : NULL; + pos += s->gs_size; + + desc.stream_output.NumEntries = s->so_entries; + if (s->so_entries) + { + so_decl = vkd3d_malloc(sizeof(*so_decl) * s->so_entries); + for (i = 0; i < s->so_entries; ++i) + { + struct vkd3d_so_declaration_cache_entry *sod = (void *)(s->data + pos); + so_decl[i].Stream = sod->stream; + so_decl[i].SemanticName = sod->semantic_name; + so_decl[i].SemanticIndex = sod->semantic_index; + so_decl[i].StartComponent = sod->start_component; + so_decl[i].ComponentCount = sod->component_count; + so_decl[i].OutputSlot = sod->output_slot; + pos += sizeof(*sod); + } + desc.stream_output.pSODeclaration = so_decl; + } + desc.stream_output.NumStrides = s->so_strides; + desc.stream_output.pBufferStrides = (void *)(s->data + pos); + pos += s->so_strides * sizeof(*desc.stream_output.pBufferStrides); + desc.stream_output.RasterizedStream = s->so_RasterizedStream; + + desc.blend_state = s->blend_state; + desc.sample_mask = s->sample_mask; + desc.rasterizer_state = s->rasterizer_state; + desc.depth_stencil_state = s->depth_stencil_state; + + desc.input_layout.NumElements = s->input_layout_elements; + if (s->input_layout_elements) + { + il_element = vkd3d_malloc(sizeof(*il_element) * s->input_layout_elements); + for (i = 0; i < s->input_layout_elements; ++i) + { + struct vkd3d_input_layout_element_cache *ile = (void *)(s->data + pos); + il_element[i].SemanticName = ile->semantic_name; + il_element[i].SemanticIndex = ile->semantic_index; + il_element[i].Format = ile->format; + il_element[i].InputSlot = ile->input_slot; + il_element[i].AlignedByteOffset = ile->aligned_byte_offset; + il_element[i].InputSlotClass = ile->input_slot_class; + il_element[i].InstanceDataStepRate = ile->instance_data_step_rate; + pos += sizeof(*ile); + } + desc.input_layout.pInputElementDescs = il_element; + } + + desc.strip_cut_value = s->strip_cut_value; + desc.primitive_topology_type = s->primitive_topology_type; + desc.rtv_formats = s->rtv_formats; + desc.dsv_format = s->dsv_format; + desc.sample_desc = s->sample_desc; + desc.node_mask = s->node_mask; + desc.flags = s->flags; + + if (!(object = vkd3d_malloc(sizeof(*object)))) + ERR("meh\n"); + /* We're happy with just creating and destroying it for now. It will feed the vulkan + * pipeline cache, which should re-use the pipeline when the game creates it for actual + * use later. + * + * FIXME: The manipulation of the device refcount in init() and Release() makes it + * unsafe to move this function to a separate thread. We might hold and release the + * last reference to the device. */ + hr = d3d12_pipeline_state_init_graphics(object, device, &desc); + if (SUCCEEDED(hr)) + { + VkRenderPass pass; + VkPipeline p = d3d12_pipeline_state_get_or_create_pipeline(object, + k->topology, k->strides, k->dsv_format, &pass); + TRACE("got render pass %lx\n", p); + ID3D12PipelineState_Release(&object->ID3D12PipelineState_iface); + } + + vkd3d_free(so_decl); + vkd3d_free(il_element); + vkd3d_free(s); break; }
@@ -4527,6 +4716,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, device_init_descriptor_pool_sizes(device);
vkd3d_shader_cache_enumerate(device->persistent_cache, d3d12_device_load_cache, device); + vkd3d_shader_cache_enumerate(device->persistent_cache, d3d12_device_load_cache2, device);
if ((device->parent = create_info->parent)) IUnknown_AddRef(device->parent); diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index eb72464bd..8b72c6408 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -3151,7 +3151,7 @@ static VkLogicOp vk_logic_op_from_d3d12(D3D12_LOGIC_OP op) } }
-static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state, +HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state, struct d3d12_device *device, const struct d3d12_pipeline_state_desc *desc) { unsigned int ps_output_swizzle[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index f934be5fb..31f989947 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1462,6 +1462,8 @@ HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state); HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state); +HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state, + struct d3d12_device *device, const struct d3d12_pipeline_state_desc *desc); HRESULT d3d12_pipeline_state_create(struct d3d12_device *device, const D3D12_PIPELINE_STATE_STREAM_DESC *desc, struct d3d12_pipeline_state **state); VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,