microsoft: Initial vulkan-on-12 driver

This is Dozen, the Vulkan on DirectX 12 driver. Not to be confused with
DirectEggs.

This is an early prototype, and not meant to be upstreamed as-is.

Co-Authored-by: Boris Brezillon <boris.brezillon@collabora.com>
Co-Authored-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Co-Authored-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Co-Authored-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Acked-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14766>
This commit is contained in:
Erik Faye-Lund 2021-06-24 13:09:35 +02:00 committed by Marge Bot
parent 6635d011cb
commit a012b21964
23 changed files with 14901 additions and 5 deletions

View File

@ -276,6 +276,7 @@ with_freedreno_virtio = get_option('freedreno-virtio')
with_broadcom_vk = _vulkan_drivers.contains('broadcom')
with_imagination_vk = _vulkan_drivers.contains('imagination-experimental')
with_imagination_srv = get_option('imagination-srv')
with_microsoft_vk = _vulkan_drivers.contains('microsoft-experimental')
with_any_vk = _vulkan_drivers.length() != 0
with_any_broadcom = with_gallium_vc4 or with_gallium_v3d or with_broadcom_vk
@ -667,11 +668,11 @@ if with_gallium_zink
endif
dep_dxheaders = null_dep
if with_gallium_d3d12 or with_microsoft_clc
if with_gallium_d3d12 or with_microsoft_clc or with_microsoft_vk
dep_dxheaders = dependency('directx-headers', required : false)
if not dep_dxheaders.found()
dep_dxheaders = dependency('DirectX-Headers', fallback : ['DirectX-Headers', 'dep_dxheaders'],
required : with_gallium_d3d12
required : with_gallium_d3d12 or with_microsoft_vk
)
endif
endif

View File

@ -192,7 +192,7 @@ option(
'vulkan-drivers',
type : 'array',
value : ['auto'],
choices : ['auto', 'amd', 'broadcom', 'freedreno', 'imagination-experimental', 'intel', 'panfrost', 'swrast', 'virtio-experimental'],
choices : ['auto', 'amd', 'broadcom', 'freedreno', 'imagination-experimental', 'intel', 'microsoft-experimental', 'panfrost', 'swrast', 'virtio-experimental'],
description : 'List of vulkan drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
)
option(

View File

@ -104,7 +104,7 @@ endif
if with_gallium_virgl or with_virtio_vk
subdir('virtio')
endif
if with_microsoft_clc or with_gallium_d3d12 or with_spirv_to_dxil
if with_microsoft_clc or with_gallium_d3d12 or with_spirv_to_dxil or with_microsoft_vk
subdir('microsoft')
endif
if with_gallium_nouveau

View File

@ -26,6 +26,9 @@ endif
if with_gallium_d3d12
subdir('resource_state_manager')
endif
if with_spirv_to_dxil
if with_spirv_to_dxil or with_microsoft_vk
subdir('spirv_to_dxil')
endif
if with_microsoft_vk
subdir('vulkan')
endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
CmdBeginQuery
CmdBeginRenderPass2
CmdBindDescriptorSets
CmdBindIndexBuffer
CmdBindPipeline
CmdBindVertexBuffers
CmdBlitImage2
CmdClearAttachments
CmdClearColorImage
CmdClearDepthStencilImage
CmdCopyBuffer2
CmdCopyBufferToImage2
CmdCopyImage2
CmdCopyImageToBuffer2
CmdCopyQueryPoolResults
CmdDispatch
CmdDispatchIndirect
CmdDraw
CmdDrawIndexed
CmdDrawIndexedIndirect
CmdDrawIndirect
CmdEndQuery
CmdEndRenderPass2
CmdFillBuffer
CmdNextSubpass2
CmdPipelineBarrier2
CmdPushConstants
CmdResetEvent
CmdResetQueryPool
CmdResolveImage2
CmdSetBlendConstants
CmdSetDepthBias
CmdSetDepthBounds
CmdSetEvent
CmdSetLineWidth
CmdSetScissor
CmdSetStencilCompareMask
CmdSetStencilReference
CmdSetStencilWriteMask
CmdUpdateBuffer
CmdWaitEvents

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,744 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "spirv_to_dxil.h"
#include "nir_to_dxil.h"
#include "dxil_nir.h"
#include "dxil_nir_lower_int_samplers.h"
static void
dzn_meta_compile_shader(dzn_device *device, nir_shader *nir,
D3D12_SHADER_BYTECODE *slot)
{
dzn_instance *instance =
container_of(device->vk.physical->instance, dzn_instance, vk);
IDxcValidator *validator = instance->dxc.validator;
IDxcLibrary *library = instance->dxc.library;
IDxcCompiler *compiler = instance->dxc.compiler;
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
if ((instance->debug_flags & DZN_DEBUG_NIR) &&
(instance->debug_flags & DZN_DEBUG_INTERNAL))
nir_print_shader(nir, stderr);
struct nir_to_dxil_options opts = { .environment = DXIL_ENVIRONMENT_VULKAN };
struct blob dxil_blob;
bool ret = nir_to_dxil(nir, &opts, &dxil_blob);
assert(ret);
dzn_shader_blob blob(dxil_blob.data, dxil_blob.size);
ComPtr<IDxcOperationResult> result;
validator->Validate(&blob, DxcValidatorFlags_InPlaceEdit, &result);
if ((instance->debug_flags & DZN_DEBUG_DXIL) &&
(instance->debug_flags & DZN_DEBUG_INTERNAL)) {
IDxcBlobEncoding *disassembly;
compiler->Disassemble(&blob, &disassembly);
ComPtr<IDxcBlobEncoding> blobUtf8;
library->GetBlobAsUtf8(disassembly, blobUtf8.GetAddressOf());
char *disasm = reinterpret_cast<char*>(blobUtf8->GetBufferPointer());
disasm[blobUtf8->GetBufferSize() - 1] = 0;
fprintf(stderr,
"== BEGIN SHADER ============================================\n"
"%s\n"
"== END SHADER ==============================================\n",
disasm);
disassembly->Release();
}
HRESULT validationStatus;
result->GetStatus(&validationStatus);
if (FAILED(validationStatus)) {
if ((instance->debug_flags & DZN_DEBUG_DXIL) &&
(instance->debug_flags & DZN_DEBUG_INTERNAL)) {
ComPtr<IDxcBlobEncoding> printBlob, printBlobUtf8;
result->GetErrorBuffer(&printBlob);
library->GetBlobAsUtf8(printBlob.Get(), printBlobUtf8.GetAddressOf());
char *errorString;
if (printBlobUtf8) {
errorString = reinterpret_cast<char*>(printBlobUtf8->GetBufferPointer());
errorString[printBlobUtf8->GetBufferSize() - 1] = 0;
fprintf(stderr,
"== VALIDATION ERROR =============================================\n"
"%s\n"
"== END ==========================================================\n",
errorString);
}
}
}
assert(!FAILED(validationStatus));
void *data;
size_t size;
blob_finish_get_buffer(&dxil_blob, &data, &size);
slot->pShaderBytecode = data;
slot->BytecodeLength = size;
}
#define DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT 4
static void
dzn_meta_indirect_draw_finish(dzn_device *device, enum dzn_indirect_draw_type type)
{
dzn_meta_indirect_draw *meta = &device->indirect_draws[type];
if (meta->root_sig)
meta->root_sig->Release();
if (meta->pipeline_state)
meta->pipeline_state->Release();
}
static VkResult
dzn_meta_indirect_draw_init(dzn_device *device,
enum dzn_indirect_draw_type type)
{
dzn_meta_indirect_draw *meta = &device->indirect_draws[type];
dzn_instance *instance =
container_of(device->vk.physical->instance, dzn_instance, vk);
VkResult ret = VK_SUCCESS;
glsl_type_singleton_init_or_ref();
nir_shader *nir = dzn_nir_indirect_draw_shader(type);
bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
uint32_t shader_params_size =
triangle_fan ?
sizeof(struct dzn_indirect_draw_triangle_fan_rewrite_params) :
sizeof(struct dzn_indirect_draw_rewrite_params);
uint32_t root_param_count = 0;
D3D12_ROOT_PARAMETER1 root_params[DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT];
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
.Constants = {
.ShaderRegister = 0,
.RegisterSpace = 0,
.Num32BitValues = shader_params_size / 4,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
.Descriptor = {
.ShaderRegister = 1,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
.Descriptor = {
.ShaderRegister = 2,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
if (triangle_fan) {
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
.Descriptor = {
.ShaderRegister = 3,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
}
assert(root_param_count <= ARRAY_SIZE(root_params));
D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
.Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
.Desc_1_1 = {
.NumParameters = root_param_count,
.pParameters = root_params,
.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
},
};
D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
.Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
};
meta->root_sig =
dzn_device_create_root_sig(device, &root_sig_desc);
if (!meta->root_sig) {
ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
goto out;
}
desc.pRootSignature = meta->root_sig;
dzn_meta_compile_shader(device, nir, &desc.CS);
assert(desc.CS.pShaderBytecode);
if (FAILED(device->dev->CreateComputePipelineState(&desc,
IID_PPV_ARGS(&meta->pipeline_state))))
ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
out:
if (ret != VK_SUCCESS)
dzn_meta_indirect_draw_finish(device, type);
free((void *)desc.CS.pShaderBytecode);
ralloc_free(nir);
glsl_type_singleton_decref();
return ret;
}
#define DZN_META_TRIANGLE_FAN_REWRITE_IDX_MAX_PARAM_COUNT 3
static void
dzn_meta_triangle_fan_rewrite_index_finish(dzn_device *device,
enum dzn_index_type old_index_type)
{
dzn_meta_triangle_fan_rewrite_index *meta =
&device->triangle_fan[old_index_type];
if (meta->root_sig)
meta->root_sig->Release();
if (meta->pipeline_state)
meta->pipeline_state->Release();
if (meta->cmd_sig)
meta->cmd_sig->Release();
}
static VkResult
dzn_meta_triangle_fan_rewrite_index_init(dzn_device *device,
enum dzn_index_type old_index_type)
{
dzn_meta_triangle_fan_rewrite_index *meta =
&device->triangle_fan[old_index_type];
dzn_instance *instance =
container_of(device->vk.physical->instance, dzn_instance, vk);
VkResult ret = VK_SUCCESS;
glsl_type_singleton_init_or_ref();
uint8_t old_index_size = dzn_index_size(old_index_type);
nir_shader *nir = dzn_nir_triangle_fan_rewrite_index_shader(old_index_size);
uint32_t root_param_count = 0;
D3D12_ROOT_PARAMETER1 root_params[DZN_META_TRIANGLE_FAN_REWRITE_IDX_MAX_PARAM_COUNT];
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
.Descriptor = {
.ShaderRegister = 1,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
.Constants = {
.ShaderRegister = 0,
.RegisterSpace = 0,
.Num32BitValues = sizeof(struct dzn_triangle_fan_rewrite_index_params) / 4,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
if (old_index_type != DZN_NO_INDEX) {
root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
.Descriptor = {
.ShaderRegister = 2,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
}
assert(root_param_count <= ARRAY_SIZE(root_params));
D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
.Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
.Desc_1_1 = {
.NumParameters = root_param_count,
.pParameters = root_params,
.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
},
};
D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
.Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
};
D3D12_INDIRECT_ARGUMENT_DESC cmd_args[] = {
{
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW,
.UnorderedAccessView = {
.RootParameterIndex = 0,
},
},
{
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
.Constant = {
.RootParameterIndex = 1,
.DestOffsetIn32BitValues = 0,
.Num32BitValuesToSet = sizeof(struct dzn_triangle_fan_rewrite_index_params) / 4,
},
},
{
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
},
};
D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = {
.ByteStride = sizeof(struct dzn_indirect_triangle_fan_rewrite_index_exec_params),
.NumArgumentDescs = ARRAY_SIZE(cmd_args),
.pArgumentDescs = cmd_args,
};
assert((cmd_sig_desc.ByteStride & 7) == 0);
meta->root_sig = dzn_device_create_root_sig(device, &root_sig_desc);
if (!meta->root_sig) {
ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
goto out;
}
desc.pRootSignature = meta->root_sig;
dzn_meta_compile_shader(device, nir, &desc.CS);
if (FAILED(device->dev->CreateComputePipelineState(&desc,
IID_PPV_ARGS(&meta->pipeline_state)))) {
ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
goto out;
}
if (FAILED(device->dev->CreateCommandSignature(&cmd_sig_desc,
meta->root_sig,
IID_PPV_ARGS(&meta->cmd_sig))))
ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
out:
if (ret != VK_SUCCESS)
dzn_meta_triangle_fan_rewrite_index_finish(device, old_index_type);
free((void *)desc.CS.pShaderBytecode);
ralloc_free(nir);
glsl_type_singleton_decref();
return ret;
}
static const D3D12_SHADER_BYTECODE *
dzn_meta_blits_get_vs(dzn_device *device)
{
dzn_meta_blits *meta = &device->blits;
D3D12_SHADER_BYTECODE *out;
mtx_lock(&meta->shaders_lock);
if (meta->vs.pShaderBytecode == NULL) {
nir_shader *nir = dzn_nir_blit_vs();
NIR_PASS_V(nir, nir_lower_system_values);
gl_system_value system_values[] = {
SYSTEM_VALUE_FIRST_VERTEX,
SYSTEM_VALUE_BASE_VERTEX,
};
NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values,
ARRAY_SIZE(system_values));
D3D12_SHADER_BYTECODE bc;
dzn_meta_compile_shader(device, nir, &bc);
meta->vs.pShaderBytecode =
vk_alloc(&device->vk.alloc, bc.BytecodeLength, 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (meta->vs.pShaderBytecode) {
meta->vs.BytecodeLength = bc.BytecodeLength;
memcpy((void *)meta->vs.pShaderBytecode, bc.pShaderBytecode, bc.BytecodeLength);
out = &meta->vs;
}
free((void *)bc.pShaderBytecode);
ralloc_free(nir);
} else {
out = &meta->vs;
}
mtx_unlock(&meta->shaders_lock);
return &meta->vs;
}
static const D3D12_SHADER_BYTECODE *
dzn_meta_blits_get_fs(dzn_device *device,
const struct dzn_nir_blit_info *info)
{
dzn_meta_blits *meta = &device->blits;
D3D12_SHADER_BYTECODE *out = NULL;
mtx_lock(&meta->shaders_lock);
STATIC_ASSERT(sizeof(struct dzn_nir_blit_info) == sizeof(uint32_t));
struct hash_entry *he =
_mesa_hash_table_search(meta->fs, (void *)(uintptr_t)info->hash_key);
if (!he) {
nir_shader *nir = dzn_nir_blit_fs(info);
if (info->out_type != GLSL_TYPE_FLOAT) {
dxil_wrap_sampler_state wrap_state = {
.is_int_sampler = 1,
.is_linear_filtering = 0,
.skip_boundary_conditions = 1,
};
dxil_lower_sample_to_txf_for_integer_tex(nir, &wrap_state, NULL, 0);
}
D3D12_SHADER_BYTECODE bc;
dzn_meta_compile_shader(device, nir, &bc);
out = (D3D12_SHADER_BYTECODE *)
vk_alloc(&device->vk.alloc,
sizeof(D3D12_SHADER_BYTECODE) + bc.BytecodeLength, 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (out) {
out->pShaderBytecode = (void *)(out + 1);
memcpy((void *)out->pShaderBytecode, bc.pShaderBytecode, bc.BytecodeLength);
out->BytecodeLength = bc.BytecodeLength;
_mesa_hash_table_insert(meta->fs, &info->hash_key, out);
}
free((void *)bc.pShaderBytecode);
ralloc_free(nir);
} else {
out = (D3D12_SHADER_BYTECODE *)he->data;
}
mtx_unlock(&meta->shaders_lock);
return out;
}
static void
dzn_meta_blit_destroy(dzn_device *device, dzn_meta_blit *blit)
{
if (!blit)
return;
if (blit->root_sig)
blit->root_sig->Release();
if (blit->pipeline_state)
blit->pipeline_state->Release();
vk_free(&device->vk.alloc, blit);
}
static dzn_meta_blit *
dzn_meta_blit_create(dzn_device *device, const dzn_meta_blit_key *key)
{
dzn_meta_blits *blits = &device->blits;
dzn_meta_blit *blit = (dzn_meta_blit *)
vk_zalloc(&device->vk.alloc, sizeof(*blit), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (!blit)
return NULL;
D3D12_DESCRIPTOR_RANGE1 ranges[] = {
{
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
.NumDescriptors = 1,
.BaseShaderRegister = 0,
.RegisterSpace = 0,
.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS,
.OffsetInDescriptorsFromTableStart = 0,
},
};
D3D12_STATIC_SAMPLER_DESC samplers[] = {
{
.Filter = key->linear_filter ?
D3D12_FILTER_MIN_MAG_MIP_LINEAR :
D3D12_FILTER_MIN_MAG_MIP_POINT,
.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
.MipLODBias = 0,
.MaxAnisotropy = 0,
.MinLOD = 0,
.MaxLOD = D3D12_FLOAT32_MAX,
.ShaderRegister = 0,
.RegisterSpace = 0,
.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
},
};
D3D12_ROOT_PARAMETER1 root_params[] = {
{
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
.DescriptorTable = {
.NumDescriptorRanges = ARRAY_SIZE(ranges),
.pDescriptorRanges = ranges,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
},
{
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
.Constants = {
.ShaderRegister = 0,
.RegisterSpace = 0,
.Num32BitValues = 17,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX,
},
};
D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
.Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
.Desc_1_1 = {
.NumParameters = ARRAY_SIZE(root_params),
.pParameters = root_params,
.NumStaticSamplers = ARRAY_SIZE(samplers),
.pStaticSamplers = samplers,
.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
},
};
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {
.SampleMask = key->resolve ? 1 : (1ULL << key->samples) - 1,
.RasterizerState = {
.FillMode = D3D12_FILL_MODE_SOLID,
.CullMode = D3D12_CULL_MODE_NONE,
.DepthClipEnable = TRUE,
},
.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
.SampleDesc = {
.Count = key->resolve ? 1 : key->samples,
.Quality = 0,
},
.Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
};
struct dzn_nir_blit_info blit_fs_info = {
.src_samples = key->samples,
.loc = key->loc,
.out_type = key->out_type,
.sampler_dim = key->sampler_dim,
.src_is_array = key->src_is_array,
.resolve = key->resolve,
.padding = 0,
};
blit->root_sig = dzn_device_create_root_sig(device, &root_sig_desc);
if (!blit->root_sig) {
dzn_meta_blit_destroy(device, blit);
return NULL;
}
desc.pRootSignature = blit->root_sig;
const D3D12_SHADER_BYTECODE *vs, *fs;
vs = dzn_meta_blits_get_vs(device);
if (!vs) {
dzn_meta_blit_destroy(device, blit);
return NULL;
}
desc.VS = *vs;
assert(desc.VS.pShaderBytecode);
fs = dzn_meta_blits_get_fs(device, &blit_fs_info);
if (!fs) {
dzn_meta_blit_destroy(device, blit);
return NULL;
}
desc.PS = *fs;
assert(desc.PS.pShaderBytecode);
assert(key->loc == FRAG_RESULT_DATA0 ||
key->loc == FRAG_RESULT_DEPTH ||
key->loc == FRAG_RESULT_STENCIL);
if (key->loc == FRAG_RESULT_DATA0) {
desc.NumRenderTargets = 1;
desc.RTVFormats[0] = key->out_format;
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0xf;
} else {
desc.DSVFormat = key->out_format;
if (key->loc == FRAG_RESULT_DEPTH) {
desc.DepthStencilState.DepthEnable = TRUE;
desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
} else {
assert(key->loc == FRAG_RESULT_STENCIL);
desc.DepthStencilState.StencilEnable = TRUE;
desc.DepthStencilState.StencilWriteMask = 0xff;
desc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_REPLACE;
desc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_REPLACE;
desc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;
desc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
desc.DepthStencilState.BackFace = desc.DepthStencilState.FrontFace;
}
}
if (FAILED(device->dev->CreateGraphicsPipelineState(&desc,
IID_PPV_ARGS(&blit->pipeline_state)))) {
dzn_meta_blit_destroy(device, blit);
return NULL;
}
return blit;
}
const dzn_meta_blit *
dzn_meta_blits_get_context(dzn_device *device,
const dzn_meta_blit_key *key)
{
dzn_meta_blit *out = NULL;
STATIC_ASSERT(sizeof(key) == sizeof(uint64_t));
mtx_lock(&device->blits.contexts_lock);
out = (dzn_meta_blit *)
_mesa_hash_table_u64_search(device->blits.contexts, key->u64);
if (!out) {
out = dzn_meta_blit_create(device, key);
if (out)
_mesa_hash_table_u64_insert(device->blits.contexts, key->u64, out);
}
mtx_unlock(&device->blits.contexts_lock);
return out;
}
static void
dzn_meta_blits_finish(dzn_device *device)
{
dzn_meta_blits *meta = &device->blits;
vk_free(&device->vk.alloc, (void *)meta->vs.pShaderBytecode);
if (meta->fs) {
hash_table_foreach(meta->fs, he)
vk_free(&device->vk.alloc, he->data);
_mesa_hash_table_destroy(meta->fs, NULL);
}
if (meta->contexts) {
hash_table_foreach(meta->contexts->table, he)
dzn_meta_blit_destroy(device, (dzn_meta_blit *)he->data);
_mesa_hash_table_u64_destroy(meta->contexts);
}
mtx_destroy(&meta->shaders_lock);
mtx_destroy(&meta->contexts_lock);
}
static VkResult
dzn_meta_blits_init(dzn_device *device)
{
dzn_instance *instance =
container_of(device->vk.physical->instance, dzn_instance, vk);
dzn_meta_blits *meta = &device->blits;
mtx_init(&meta->shaders_lock, mtx_plain);
mtx_init(&meta->contexts_lock, mtx_plain);
meta->fs = _mesa_hash_table_create_u32_keys(NULL);
if (!meta->fs) {
dzn_meta_blits_finish(device);
return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
meta->contexts = _mesa_hash_table_u64_create(NULL);
if (!meta->contexts) {
dzn_meta_blits_finish(device);
return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
return VK_SUCCESS;
}
void
dzn_meta_finish(dzn_device *device)
{
for (uint32_t i = 0; i < ARRAY_SIZE(device->triangle_fan); i++)
dzn_meta_triangle_fan_rewrite_index_finish(device, (enum dzn_index_type)i);
for (uint32_t i = 0; i < ARRAY_SIZE(device->indirect_draws); i++)
dzn_meta_indirect_draw_finish(device, (enum dzn_indirect_draw_type)i);
dzn_meta_blits_finish(device);
}
VkResult
dzn_meta_init(dzn_device *device)
{
VkResult result = dzn_meta_blits_init(device);
if (result != VK_SUCCESS)
goto out;
for (uint32_t i = 0; i < ARRAY_SIZE(device->indirect_draws); i++) {
VkResult result =
dzn_meta_indirect_draw_init(device, (enum dzn_indirect_draw_type)i);
if (result != VK_SUCCESS)
goto out;
}
for (uint32_t i = 0; i < ARRAY_SIZE(device->triangle_fan); i++) {
VkResult result =
dzn_meta_triangle_fan_rewrite_index_init(device, (enum dzn_index_type)i);
if (result != VK_SUCCESS)
goto out;
}
out:
if (result != VK_SUCCESS) {
dzn_meta_finish(device);
return result;
}
return VK_SUCCESS;
}

View File

@ -0,0 +1,513 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <directx/d3d12.h>
#include "spirv_to_dxil.h"
#include "nir_to_dxil.h"
#include "nir_builder.h"
#include "nir_vulkan.h"
#include "dzn_nir.h"
static nir_ssa_def *
dzn_nir_create_bo_desc(nir_builder *b,
nir_variable_mode mode,
uint32_t desc_set,
uint32_t binding,
const char *name,
unsigned access)
{
struct glsl_struct_field field = {
.type = mode == nir_var_mem_ubo ?
glsl_array_type(glsl_uint_type(), 4096, 4) :
glsl_uint_type(),
.name = "dummy_int",
};
const struct glsl_type *dummy_type =
glsl_struct_type(&field, 1, "dummy_type", false);
nir_variable *var =
nir_variable_create(b->shader, mode, dummy_type, name);
var->data.descriptor_set = desc_set;
var->data.binding = binding;
var->data.access = access;
assert(mode == nir_var_mem_ubo || mode == nir_var_mem_ssbo);
if (mode == nir_var_mem_ubo)
b->shader->info.num_ubos++;
else
b->shader->info.num_ssbos++;
VkDescriptorType desc_type =
var->data.mode == nir_var_mem_ubo ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
nir_address_format addr_format = nir_address_format_32bit_index_offset;
nir_ssa_def *index =
nir_vulkan_resource_index(b,
nir_address_format_num_components(addr_format),
nir_address_format_bit_size(addr_format),
nir_imm_int(b, 0),
.desc_set = desc_set,
.binding = binding,
.desc_type = desc_type);
nir_ssa_def *desc =
nir_load_vulkan_descriptor(b,
nir_address_format_num_components(addr_format),
nir_address_format_bit_size(addr_format),
index,
.desc_type = desc_type);
return nir_channel(b, desc, 0);
}
nir_shader *
dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type)
{
const char *type_str[] = {
"draw",
"indexed_draw",
"draw_triangle_fan",
"indexed_draw_triangle_fan",
};
assert(type < ARRAY_SIZE(type_str));
bool indexed = type == DZN_INDIRECT_INDEXED_DRAW ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
nir_builder b =
nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
dxil_get_nir_compiler_options(),
"dzn_meta_indirect_%s()",
type_str[type]);
b.shader->info.internal = true;
struct glsl_struct_field field = {
.type = glsl_uint_type(),
.name = "dummy_int",
};
const struct glsl_type *dummy_type =
glsl_struct_type(&field, 1, "dummy_type", false);
nir_ssa_def *params_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ubo, 0, 0, "params", 0);
nir_ssa_def *draw_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 1, "draw_buf", ACCESS_NON_WRITEABLE);
nir_ssa_def *exec_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 2, "exec_buf", ACCESS_NON_READABLE);
unsigned params_size =
triangle_fan ?
sizeof(struct dzn_indirect_draw_triangle_fan_rewrite_params) :
sizeof(struct dzn_indirect_draw_rewrite_params);
nir_ssa_def *params =
nir_load_ubo(&b, params_size / 4, 32,
params_desc, nir_imm_int(&b, 0),
.align_mul = 4, .align_offset = 0, .range_base = 0, .range = ~0);
nir_ssa_def *draw_stride = nir_channel(&b, params, 0);
nir_ssa_def *exec_stride = nir_imm_int(&b, sizeof(struct dzn_indirect_draw_exec_params));
nir_ssa_def *index =
nir_channel(&b, nir_load_global_invocation_id(&b, 32), 0);
nir_ssa_def *draw_offset = nir_imul(&b, draw_stride, index);
nir_ssa_def *exec_offset = nir_imul(&b, exec_stride, index);
nir_ssa_def *draw_info1 =
nir_load_ssbo(&b, 4, 32, draw_buf_desc, draw_offset, .align_mul = 4);
nir_ssa_def *draw_info2 =
indexed ?
nir_load_ssbo(&b, 1, 32, draw_buf_desc,
nir_iadd_imm(&b, draw_offset, 16), .align_mul = 4) :
nir_imm_int(&b, 0);
nir_ssa_def *first_vertex = nir_channel(&b, draw_info1, indexed ? 3 : 2);
nir_ssa_def *base_instance =
indexed ? draw_info2 : nir_channel(&b, draw_info1, 3);
nir_ssa_def *exec_vals[7] = {
first_vertex,
base_instance,
};
if (triangle_fan) {
/* Patch {vertex,index}_count and first_index */
nir_ssa_def *triangle_count =
nir_usub_sat(&b, nir_channel(&b, draw_info1, 0), nir_imm_int(&b, 2));
exec_vals[2] = nir_imul_imm(&b, triangle_count, 3);
exec_vals[3] = nir_channel(&b, draw_info1, 1);
exec_vals[4] = nir_imm_int(&b, 0);
exec_vals[5] = indexed ? nir_channel(&b, draw_info1, 3) : nir_imm_int(&b, 0);
exec_vals[6] = indexed ? draw_info2 : nir_channel(&b, draw_info1, 3);
nir_ssa_def *triangle_fan_exec_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 3,
"triangle_fan_exec_buf",
ACCESS_NON_READABLE);
nir_ssa_def *triangle_fan_index_buf_stride = nir_channel(&b, params, 1);
nir_ssa_def *triangle_fan_index_buf_addr_lo =
nir_iadd(&b, nir_channel(&b, params, 2),
nir_imul(&b, triangle_fan_index_buf_stride, index));
nir_ssa_def *addr_lo_overflow =
nir_ult(&b, triangle_fan_index_buf_addr_lo, nir_channel(&b, params, 2));
nir_ssa_def *triangle_fan_index_buf_addr_hi =
nir_iadd(&b, nir_channel(&b, params, 3),
nir_bcsel(&b, addr_lo_overflow, nir_imm_int(&b, 1), nir_imm_int(&b, 0)));
nir_ssa_def *triangle_fan_exec_vals[] = {
triangle_fan_index_buf_addr_lo,
triangle_fan_index_buf_addr_hi,
nir_channel(&b, draw_info1, 2),
triangle_count,
nir_imm_int(&b, 1),
nir_imm_int(&b, 1),
};
assert(sizeof(struct dzn_indirect_triangle_fan_rewrite_index_exec_params) == (ARRAY_SIZE(triangle_fan_exec_vals) * 4));
nir_ssa_def *triangle_fan_exec_stride =
nir_imm_int(&b, sizeof(struct dzn_indirect_triangle_fan_rewrite_index_exec_params));
nir_ssa_def *triangle_fan_exec_offset =
nir_imul(&b, triangle_fan_exec_stride, index);
nir_store_ssbo(&b, nir_vec(&b, &triangle_fan_exec_vals[0], 4),
triangle_fan_exec_buf_desc, triangle_fan_exec_offset,
.write_mask = 0xf, .access = ACCESS_NON_READABLE, .align_mul = 4);
nir_store_ssbo(&b, nir_vec(&b, &triangle_fan_exec_vals[4], 2),
triangle_fan_exec_buf_desc,
nir_iadd_imm(&b, triangle_fan_exec_offset, 16),
.write_mask = 0x3, .access = ACCESS_NON_READABLE, .align_mul = 4);
nir_ssa_def *ibview_vals[] = {
triangle_fan_index_buf_addr_lo,
triangle_fan_index_buf_addr_hi,
triangle_fan_index_buf_stride,
nir_imm_int(&b, DXGI_FORMAT_R32_UINT),
};
nir_store_ssbo(&b, nir_vec(&b, ibview_vals, ARRAY_SIZE(ibview_vals)),
exec_buf_desc, exec_offset,
.write_mask = 0x3, .access = ACCESS_NON_READABLE, .align_mul = 4);
exec_offset = nir_iadd_imm(&b, exec_offset, ARRAY_SIZE(ibview_vals) * 4);
} else {
exec_vals[2] = nir_channel(&b, draw_info1, 0);
exec_vals[3] = nir_channel(&b, draw_info1, 1);
exec_vals[4] = nir_channel(&b, draw_info1, 2);
exec_vals[5] = nir_channel(&b, draw_info1, 3);
exec_vals[6] = draw_info2;
}
nir_store_ssbo(&b, nir_vec(&b, exec_vals, 4),
exec_buf_desc, exec_offset,
.write_mask = 0xf, .access = ACCESS_NON_READABLE, .align_mul = 4);
nir_store_ssbo(&b, nir_vec(&b, &exec_vals[4], 3),
exec_buf_desc, nir_iadd_imm(&b, exec_offset, 16),
.write_mask = 7, .access = ACCESS_NON_READABLE, .align_mul = 4);
return b.shader;
}
nir_shader *
dzn_nir_triangle_fan_rewrite_index_shader(uint8_t old_index_size)
{
assert(old_index_size == 0 || old_index_size == 2 || old_index_size == 4);
nir_builder b =
nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
dxil_get_nir_compiler_options(),
"dzn_meta_triangle_rewrite_index(old_index_size=%d)",
old_index_size);
b.shader->info.internal = true;
nir_ssa_def *params_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ubo, 0, 0, "params", 0);
nir_ssa_def *new_index_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 1,
"new_index_buf", ACCESS_NON_READABLE);
nir_ssa_def *old_index_buf_desc = NULL;
if (old_index_size > 0) {
old_index_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 2,
"old_index_buf", ACCESS_NON_WRITEABLE);
}
nir_ssa_def *params =
nir_load_ubo(&b, sizeof(struct dzn_triangle_fan_rewrite_index_params) / 4, 32,
params_desc, nir_imm_int(&b, 0),
.align_mul = 4, .align_offset = 0, .range_base = 0, .range = ~0);
nir_ssa_def *triangle = nir_channel(&b, nir_load_global_invocation_id(&b, 32), 0);
nir_ssa_def *new_indices;
if (old_index_size > 0) {
nir_ssa_def *old_first_index = nir_channel(&b, params, 0);
nir_ssa_def *old_index0_offset =
nir_imul_imm(&b, old_first_index, old_index_size);
nir_ssa_def *old_index1_offset =
nir_imul_imm(&b, nir_iadd(&b, nir_iadd_imm(&b, triangle, 1), old_first_index),
old_index_size);
nir_ssa_def *old_index0 =
nir_load_ssbo(&b, 1, 32, old_index_buf_desc,
old_index_size == 2 ? nir_iand_imm(&b, old_index0_offset, ~3ULL) : old_index0_offset,
.align_mul = 4);
if (old_index_size == 2) {
old_index0 =
nir_bcsel(&b,
nir_ieq_imm(&b, nir_iand_imm(&b, old_index0_offset, 0x2), 0),
nir_iand_imm(&b, old_index0, 0xffff),
nir_ushr_imm(&b, old_index0, 16));
}
nir_ssa_def *old_index12 =
nir_load_ssbo(&b, 2, 32, old_index_buf_desc,
old_index_size == 2 ? nir_iand_imm(&b, old_index1_offset, ~3ULL) : old_index1_offset,
.align_mul = 4);
if (old_index_size == 2) {
nir_ssa_def *indices[] = {
nir_iand_imm(&b, nir_channel(&b, old_index12, 0), 0xffff),
nir_ushr_imm(&b, nir_channel(&b, old_index12, 0), 16),
nir_iand_imm(&b, nir_channel(&b, old_index12, 1), 0xffff),
};
old_index12 =
nir_bcsel(&b,
nir_ieq_imm(&b, nir_iand_imm(&b, old_index1_offset, 0x2), 0),
nir_vec2(&b, indices[0], indices[1]),
nir_vec2(&b, indices[1], indices[2]));
}
/* TODO: VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT */
new_indices =
nir_vec3(&b, nir_channel(&b, old_index12, 0),
nir_channel(&b, old_index12, 1), old_index0);
} else {
nir_ssa_def *first_vertex = nir_channel(&b, params, 0);
new_indices =
nir_vec3(&b,
nir_iadd(&b, nir_iadd_imm(&b, triangle, 1), first_vertex),
nir_iadd(&b, nir_iadd_imm(&b, triangle, 2), first_vertex),
first_vertex);
}
nir_ssa_def *new_index_offset =
nir_imul_imm(&b, triangle, 4 * 3);
nir_store_ssbo(&b, new_indices, new_index_buf_desc,
new_index_offset,
.write_mask = 7, .access = ACCESS_NON_READABLE, .align_mul = 4);
return b.shader;
}
nir_shader *
dzn_nir_blit_vs(void)
{
nir_builder b =
nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
dxil_get_nir_compiler_options(),
"dzn_meta_blit_vs()");
b.shader->info.internal = true;
nir_ssa_def *params_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ubo, 0, 0, "params", 0);
nir_variable *out_pos =
nir_variable_create(b.shader, nir_var_shader_out, glsl_vec4_type(),
"gl_Position");
out_pos->data.location = VARYING_SLOT_POS;
out_pos->data.driver_location = 0;
nir_variable *out_coords =
nir_variable_create(b.shader, nir_var_shader_out, glsl_vec_type(3),
"coords");
out_coords->data.location = VARYING_SLOT_TEX0;
out_coords->data.driver_location = 1;
nir_ssa_def *vertex = nir_load_vertex_id(&b);
nir_ssa_def *base = nir_imul_imm(&b, vertex, 4 * sizeof(float));
nir_ssa_def *coords =
nir_load_ubo(&b, 4, 32, params_desc, base,
.align_mul = 16, .align_offset = 0, .range_base = 0, .range = ~0);
nir_ssa_def *pos =
nir_vec4(&b, nir_channel(&b, coords, 0), nir_channel(&b, coords, 1),
nir_imm_float(&b, 0.0), nir_imm_float(&b, 1.0));
nir_ssa_def *z_coord =
nir_load_ubo(&b, 1, 32, params_desc, nir_imm_int(&b, 4 * 4 * sizeof(float)),
.align_mul = 64, .align_offset = 0, .range_base = 0, .range = ~0);
coords = nir_vec3(&b, nir_channel(&b, coords, 2), nir_channel(&b, coords, 3), z_coord);
nir_store_var(&b, out_pos, pos, 0xf);
nir_store_var(&b, out_coords, coords, 0x7);
return b.shader;
}
nir_shader *
dzn_nir_blit_fs(const struct dzn_nir_blit_info *info)
{
bool ms = info->src_samples > 1;
nir_alu_type nir_out_type =
nir_get_nir_type_for_glsl_base_type(info->out_type);
uint32_t coord_comps =
glsl_get_sampler_dim_coordinate_components(info->sampler_dim) +
info->src_is_array;
nir_builder b =
nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
dxil_get_nir_compiler_options(),
"dzn_meta_blit_fs()");
b.shader->info.internal = true;
const struct glsl_type *tex_type =
glsl_texture_type(info->sampler_dim, info->src_is_array, info->out_type);
nir_variable *tex_var =
nir_variable_create(b.shader, nir_var_uniform, tex_type, "texture");
nir_deref_instr *tex_deref = nir_build_deref_var(&b, tex_var);
nir_variable *pos_var =
nir_variable_create(b.shader, nir_var_shader_in,
glsl_vector_type(GLSL_TYPE_FLOAT, 4),
"gl_FragCoord");
pos_var->data.location = VARYING_SLOT_POS;
pos_var->data.driver_location = 0;
nir_variable *coord_var =
nir_variable_create(b.shader, nir_var_shader_in,
glsl_vector_type(GLSL_TYPE_FLOAT, 3),
"coord");
coord_var->data.location = VARYING_SLOT_TEX0;
coord_var->data.driver_location = 1;
nir_ssa_def *coord =
nir_channels(&b, nir_load_var(&b, coord_var), (1 << coord_comps) - 1);
uint32_t out_comps =
(info->loc == FRAG_RESULT_DEPTH || info->loc == FRAG_RESULT_STENCIL) ? 1 : 4;
nir_variable *out =
nir_variable_create(b.shader, nir_var_shader_out,
glsl_vector_type(info->out_type, out_comps),
"out");
out->data.location = info->loc;
nir_ssa_def *res = NULL;
if (info->resolve) {
/* When resolving a float type, we need to calculate the average of all
* samples. For integer resolve, Vulkan says that one sample should be
* chosen without telling which. Let's just pick the first one in that
* case.
*/
unsigned nsamples = info->out_type == GLSL_TYPE_FLOAT ?
info->src_samples : 1;
for (unsigned s = 0; s < nsamples; s++) {
nir_tex_instr *tex = nir_tex_instr_create(b.shader, 4);
tex->op = nir_texop_txf_ms;
tex->dest_type = nir_out_type;
tex->texture_index = 0;
tex->is_array = info->src_is_array;
tex->sampler_dim = info->sampler_dim;
tex->src[0].src_type = nir_tex_src_coord;
tex->src[0].src = nir_src_for_ssa(nir_f2i32(&b, coord));
tex->coord_components = coord_comps;
tex->src[1].src_type = nir_tex_src_ms_index;
tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, s));
tex->src[2].src_type = nir_tex_src_lod;
tex->src[2].src = nir_src_for_ssa(nir_imm_int(&b, 0));
tex->src[3].src_type = nir_tex_src_texture_deref;
tex->src[3].src = nir_src_for_ssa(&tex_deref->dest.ssa);
nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
nir_builder_instr_insert(&b, &tex->instr);
res = res ? nir_fadd(&b, res, &tex->dest.ssa) : &tex->dest.ssa;
}
if (nsamples > 1) {
unsigned type_sz = nir_alu_type_get_type_size(nir_out_type);
res = nir_fmul(&b, res, nir_imm_floatN_t(&b, 1.0f / nsamples, type_sz));
}
} else {
nir_tex_instr *tex =
nir_tex_instr_create(b.shader, ms ? 4 : 3);
tex->dest_type = nir_out_type;
tex->is_array = info->src_is_array;
tex->sampler_dim = info->sampler_dim;
if (ms) {
tex->op = nir_texop_txf_ms;
tex->src[0].src_type = nir_tex_src_coord;
tex->src[0].src = nir_src_for_ssa(nir_f2i32(&b, coord));
tex->coord_components = coord_comps;
tex->src[1].src_type = nir_tex_src_ms_index;
tex->src[1].src = nir_src_for_ssa(nir_load_sample_id(&b));
tex->src[2].src_type = nir_tex_src_lod;
tex->src[2].src = nir_src_for_ssa(nir_imm_int(&b, 0));
tex->src[3].src_type = nir_tex_src_texture_deref;
tex->src[3].src = nir_src_for_ssa(&tex_deref->dest.ssa);
} else {
nir_variable *sampler_var =
nir_variable_create(b.shader, nir_var_uniform, glsl_bare_sampler_type(), "sampler");
nir_deref_instr *sampler_deref = nir_build_deref_var(&b, sampler_var);
tex->op = nir_texop_tex;
tex->sampler_index = 0;
tex->src[0].src_type = nir_tex_src_coord;
tex->src[0].src = nir_src_for_ssa(coord);
tex->coord_components = coord_comps;
tex->src[1].src_type = nir_tex_src_texture_deref;
tex->src[1].src = nir_src_for_ssa(&tex_deref->dest.ssa);
tex->src[2].src_type = nir_tex_src_sampler_deref;
tex->src[2].src = nir_src_for_ssa(&sampler_deref->dest.ssa);
}
nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
nir_builder_instr_insert(&b, &tex->instr);
res = &tex->dest.ssa;
}
nir_store_var(&b, out, nir_channels(&b, res, (1 << out_comps) - 1), 0xf);
return b.shader;
}

View File

@ -0,0 +1,138 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef DZN_NIR_H
#define DZN_NIR_H
#define D3D12_IGNORE_SDK_LAYERS
#include <directx/d3d12.h>
#include "nir.h"
#ifdef __cplusplus
extern "C" {
#endif
struct dzn_indirect_draw_params {
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
uint32_t first_instance;
};
struct dzn_indirect_indexed_draw_params {
uint32_t index_count;
uint32_t instance_count;
uint32_t first_index;
int32_t vertex_offset;
uint32_t first_instance;
};
struct dzn_indirect_draw_rewrite_params {
uint32_t draw_buf_stride;
};
struct dzn_indirect_draw_triangle_fan_rewrite_params {
uint32_t draw_buf_stride;
uint32_t triangle_fan_index_buf_stride;
uint64_t triangle_fan_index_buf_start;
};
struct dzn_indirect_draw_exec_params {
struct {
uint32_t first_vertex;
uint32_t base_instance;
} sysvals;
union {
struct dzn_indirect_draw_params draw;
struct dzn_indirect_indexed_draw_params indexed_draw;
};
};
struct dzn_indirect_triangle_fan_draw_exec_params {
D3D12_INDEX_BUFFER_VIEW ibview;
struct {
uint32_t first_vertex;
uint32_t base_instance;
} sysvals;
union {
struct dzn_indirect_draw_params draw;
struct dzn_indirect_indexed_draw_params indexed_draw;
};
};
struct dzn_triangle_fan_rewrite_index_params {
union {
uint32_t first_index;
uint32_t first_vertex;
};
};
struct dzn_indirect_triangle_fan_rewrite_index_exec_params {
uint64_t new_index_buf;
struct dzn_triangle_fan_rewrite_index_params params;
struct {
uint32_t x, y, z;
} group_count;
};
enum dzn_indirect_draw_type {
DZN_INDIRECT_DRAW,
DZN_INDIRECT_INDEXED_DRAW,
DZN_INDIRECT_DRAW_TRIANGLE_FAN,
DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN,
DZN_NUM_INDIRECT_DRAW_TYPES,
};
nir_shader *
dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type);
nir_shader *
dzn_nir_triangle_fan_rewrite_index_shader(uint8_t old_index_size);
struct dzn_nir_blit_info {
union {
struct {
uint32_t src_samples : 6;
uint32_t loc : 4;
uint32_t out_type : 4;
uint32_t sampler_dim : 4;
uint32_t src_is_array : 1;
uint32_t resolve : 1;
uint32_t padding : 12;
};
const uint32_t hash_key;
};
};
nir_shader *
dzn_nir_blit_vs(void);
nir_shader *
dzn_nir_blit_fs(const struct dzn_nir_blit_info *info);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,159 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_alloc.h"
#include "vk_format.h"
VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateRenderPass2(VkDevice dev,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
VK_FROM_HANDLE(dzn_device, device, dev);
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, dzn_render_pass, pass, 1);
VK_MULTIALLOC_DECL(&ma, dzn_subpass, subpasses,
pCreateInfo->subpassCount);
VK_MULTIALLOC_DECL(&ma, dzn_attachment, attachments,
pCreateInfo->attachmentCount);
if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS);
pass->subpasses = subpasses;
pass->subpass_count = pCreateInfo->subpassCount;
pass->attachments = attachments;
pass->attachment_count = pCreateInfo->attachmentCount;
assert(!pass->attachment_count || pass->attachments);
for (uint32_t i = 0; i < pass->attachment_count; i++) {
const VkAttachmentDescription2 *attachment = &pCreateInfo->pAttachments[i];
attachments[i].idx = i;
attachments[i].format = attachment->format;
assert(attachments[i].format);
if (vk_format_is_depth_or_stencil(attachment->format)) {
attachments[i].clear.depth =
attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[i].clear.stencil =
attachment->stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
} else {
attachments[i].clear.color =
attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
}
attachments[i].samples = attachment->samples;
attachments[i].before = dzn_image_layout_to_state(attachment->initialLayout);
attachments[i].after = dzn_image_layout_to_state(attachment->finalLayout);
attachments[i].last = attachments[i].before;
}
assert(subpasses);
for (uint32_t i = 0; i < pass->subpass_count; i++) {
const VkSubpassDescription2 *subpass = &pCreateInfo->pSubpasses[i];
const VkSubpassDescription2 *subpass_after = NULL;
if (i + 1 < pass->subpass_count)
subpass_after = &pCreateInfo->pSubpasses[i + 1];
for (uint32_t j = 0; j < subpass->colorAttachmentCount; j++) {
uint32_t idx = subpass->pColorAttachments[j].attachment;
subpasses[i].colors[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].colors[j].before = attachments[idx].last;
subpasses[i].colors[j].during =
dzn_image_layout_to_state(subpass->pColorAttachments[j].layout);
attachments[idx].last = subpasses[i].colors[j].during;
subpasses[i].color_count = j + 1;
}
idx = subpass->pResolveAttachments ?
subpass->pResolveAttachments[j].attachment :
VK_ATTACHMENT_UNUSED;
subpasses[i].resolve[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].resolve[j].before = attachments[idx].last;
subpasses[i].resolve[j].during =
dzn_image_layout_to_state(subpass->pResolveAttachments[j].layout);
attachments[idx].last = subpasses[i].resolve[j].during;
}
}
subpasses[i].zs.idx = VK_ATTACHMENT_UNUSED;
if (subpass->pDepthStencilAttachment) {
uint32_t idx = subpass->pDepthStencilAttachment->attachment;
subpasses[i].zs.idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].zs.before = attachments[idx].last;
subpasses[i].zs.during =
dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout);
attachments[idx].last = subpasses[i].zs.during;
}
}
subpasses[i].input_count = subpass->inputAttachmentCount;
for (uint32_t j = 0; j < subpasses[i].input_count; j++) {
uint32_t idx = subpass->pInputAttachments[j].attachment;
subpasses[i].inputs[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].inputs[j].before = attachments[idx].last;
subpasses[i].inputs[j].during =
dzn_image_layout_to_state(subpass->pInputAttachments[j].layout);
attachments[idx].last = subpasses[i].inputs[j].during;
}
}
}
*pRenderPass = dzn_render_pass_to_handle(pass);
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
dzn_DestroyRenderPass(VkDevice dev,
VkRenderPass p,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(dzn_device, device, dev);
VK_FROM_HANDLE(dzn_render_pass, pass, p);
if (!pass)
return;
vk_object_base_finish(&pass->base);
vk_free2(&device->vk.alloc, pAllocator, pass);
}
VKAPI_ATTR void VKAPI_CALL
dzn_GetRenderAreaGranularity(VkDevice device,
VkRenderPass pass,
VkExtent2D *pGranularity)
{
// FIXME: query the actual optimal granularity
pGranularity->width = pGranularity->height = 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_alloc.h"
static void
dzn_pipeline_cache_destroy(dzn_pipeline_cache *pcache,
const VkAllocationCallbacks *pAllocator)
{
if (!pcache)
return;
dzn_device *device = container_of(pcache->base.device, dzn_device, vk);
vk_object_base_finish(&pcache->base);
vk_free2(&device->vk.alloc, pAllocator, pcache);
}
static VkResult
dzn_pipeline_cache_create(dzn_device *device,
const VkPipelineCacheCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineCache *out)
{
dzn_pipeline_cache *pcache = (dzn_pipeline_cache *)
vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pcache), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pcache)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
vk_object_base_init(&device->vk, &pcache->base, VK_OBJECT_TYPE_PIPELINE_CACHE);
/* TODO: cache-ism! */
*out = dzn_pipeline_cache_to_handle(pcache);
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreatePipelineCache(VkDevice device,
const VkPipelineCacheCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineCache *pPipelineCache)
{
return dzn_pipeline_cache_create(dzn_device_from_handle(device),
pCreateInfo, pAllocator, pPipelineCache);
}
VKAPI_ATTR void VKAPI_CALL
dzn_DestroyPipelineCache(VkDevice device,
VkPipelineCache pipelineCache,
const VkAllocationCallbacks *pAllocator)
{
return dzn_pipeline_cache_destroy(dzn_pipeline_cache_from_handle(pipelineCache),
pAllocator);
}
VKAPI_ATTR VkResult VKAPI_CALL
dzn_GetPipelineCacheData(VkDevice device,
VkPipelineCache pipelineCache,
size_t *pDataSize,
void *pData)
{
// FIXME
*pDataSize = 0;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
dzn_MergePipelineCaches(VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache *pSrcCaches)
{
// FIXME
return VK_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,327 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_alloc.h"
#include "vk_debug_report.h"
#include "vk_util.h"
static D3D12_QUERY_HEAP_TYPE
dzn_query_pool_get_heap_type(VkQueryType in)
{
switch (in) {
case VK_QUERY_TYPE_OCCLUSION: return D3D12_QUERY_HEAP_TYPE_OCCLUSION;
case VK_QUERY_TYPE_PIPELINE_STATISTICS: return D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS;
case VK_QUERY_TYPE_TIMESTAMP: return D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
default: unreachable("Unsupported query type");
}
}
D3D12_QUERY_TYPE
dzn_query_pool_get_query_type(const dzn_query_pool *qpool,
VkQueryControlFlags flags)
{
switch (qpool->heap_type) {
case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
return flags & VK_QUERY_CONTROL_PRECISE_BIT ?
D3D12_QUERY_TYPE_OCCLUSION : D3D12_QUERY_TYPE_BINARY_OCCLUSION;
case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS: return D3D12_QUERY_TYPE_PIPELINE_STATISTICS;
case D3D12_QUERY_HEAP_TYPE_TIMESTAMP: return D3D12_QUERY_TYPE_TIMESTAMP;
default: unreachable("Unsupported query type");
}
}
static void
dzn_query_pool_destroy(dzn_query_pool *qpool,
const VkAllocationCallbacks *alloc)
{
if (!qpool)
return;
dzn_device *device = container_of(qpool->base.device, dzn_device, vk);
if (qpool->collect_map)
qpool->collect_buffer->Unmap(0, NULL);
if (qpool->collect_buffer)
qpool->collect_buffer->Release();
if (qpool->resolve_buffer)
qpool->resolve_buffer->Release();
if (qpool->heap)
qpool->heap->Release();
for (uint32_t q = 0; q < qpool->query_count; q++) {
if (qpool->queries[q].fence)
qpool->queries[q].fence->Release();
}
mtx_destroy(&qpool->queries_lock);
vk_object_base_finish(&qpool->base);
vk_free2(&device->vk.alloc, alloc, qpool);
}
static VkResult
dzn_query_pool_create(dzn_device *device,
const VkQueryPoolCreateInfo *info,
const VkAllocationCallbacks *alloc,
VkQueryPool *out)
{
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, dzn_query_pool, qpool, 1);
VK_MULTIALLOC_DECL(&ma, dzn_query, queries, info->queryCount);
if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
vk_object_base_init(&device->vk, &qpool->base, VK_OBJECT_TYPE_QUERY_POOL);
mtx_init(&qpool->queries_lock, mtx_plain);
qpool->query_count = info->queryCount;
qpool->queries = queries;
D3D12_QUERY_HEAP_DESC desc = { 0 };
qpool->heap_type = desc.Type = dzn_query_pool_get_heap_type(info->queryType);
desc.Count = info->queryCount;
desc.NodeMask = 0;
HRESULT hres =
device->dev->CreateQueryHeap(&desc, IID_PPV_ARGS(&qpool->heap));
if (FAILED(hres)) {
dzn_query_pool_destroy(qpool, alloc);
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
switch (info->queryType) {
case VK_QUERY_TYPE_OCCLUSION:
case VK_QUERY_TYPE_TIMESTAMP:
qpool->query_size = sizeof(uint64_t);
break;
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
qpool->pipeline_statistics = info->pipelineStatistics;
qpool->query_size = sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS);
break;
default: unreachable("Unsupported query type");
}
D3D12_HEAP_PROPERTIES hprops =
device->dev->GetCustomHeapProperties(0, D3D12_HEAP_TYPE_DEFAULT);
D3D12_RESOURCE_DESC rdesc = {
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
.Width = info->queryCount * qpool->query_size,
.Height = 1,
.DepthOrArraySize = 1,
.MipLevels = 1,
.Format = DXGI_FORMAT_UNKNOWN,
.SampleDesc = { .Count = 1, .Quality = 0 },
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
.Flags = D3D12_RESOURCE_FLAG_NONE,
};
hres = device->dev->CreateCommittedResource(&hprops,
D3D12_HEAP_FLAG_NONE,
&rdesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL, IID_PPV_ARGS(&qpool->resolve_buffer));
if (FAILED(hres)) {
dzn_query_pool_destroy(qpool, alloc);
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
hprops = device->dev->GetCustomHeapProperties(0, D3D12_HEAP_TYPE_READBACK);
rdesc.Width = info->queryCount * (qpool->query_size + sizeof(uint64_t));
hres = device->dev->CreateCommittedResource(&hprops,
D3D12_HEAP_FLAG_NONE,
&rdesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL, IID_PPV_ARGS(&qpool->collect_buffer));
if (FAILED(hres)) {
dzn_query_pool_destroy(qpool, alloc);
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
hres = qpool->collect_buffer->Map(0, NULL, (void **)&qpool->collect_map);
if (FAILED(hres)) {
dzn_query_pool_destroy(qpool, alloc);
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
}
memset(qpool->collect_map, 0, rdesc.Width);
*out = dzn_query_pool_to_handle(qpool);
return VK_SUCCESS;
}
uint32_t
dzn_query_pool_get_result_offset(const dzn_query_pool *qpool, uint32_t query)
{
return query * qpool->query_size;
}
uint32_t
dzn_query_pool_get_result_size(const dzn_query_pool *qpool, uint32_t query_count)
{
return query_count * qpool->query_size;
}
uint32_t
dzn_query_pool_get_availability_offset(const dzn_query_pool *qpool, uint32_t query)
{
return (qpool->query_count * qpool->query_size) + (sizeof(uint64_t) * query);
}
VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateQueryPool(VkDevice device,
const VkQueryPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkQueryPool *pQueryPool)
{
return dzn_query_pool_create(dzn_device_from_handle(device),
pCreateInfo, pAllocator, pQueryPool);
}
VKAPI_ATTR void VKAPI_CALL
dzn_DestroyQueryPool(VkDevice device,
VkQueryPool queryPool,
const VkAllocationCallbacks *pAllocator)
{
dzn_query_pool_destroy(dzn_query_pool_from_handle(queryPool), pAllocator);
}
VKAPI_ATTR void VKAPI_CALL
dzn_ResetQueryPool(VkDevice device,
VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount)
{
VK_FROM_HANDLE(dzn_query_pool, qpool, queryPool);
mtx_lock(&qpool->queries_lock);
for (uint32_t q = 0; q < queryCount; q++) {
dzn_query *query = &qpool->queries[firstQuery + q];
query->fence_value = 0;
if (query->fence) {
query->fence->Release();
query->fence = NULL;
}
}
mtx_lock(&qpool->queries_lock);
memset((uint8_t *)qpool->collect_map + dzn_query_pool_get_result_offset(qpool, firstQuery),
0, queryCount * qpool->query_size);
memset((uint8_t *)qpool->collect_map + dzn_query_pool_get_availability_offset(qpool, firstQuery),
0, queryCount * sizeof(uint64_t));
}
VKAPI_ATTR VkResult VKAPI_CALL
dzn_GetQueryPoolResults(VkDevice device,
VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount,
size_t dataSize,
void *pData,
VkDeviceSize stride,
VkQueryResultFlags flags)
{
VK_FROM_HANDLE(dzn_query_pool, qpool, queryPool);
uint32_t step = (flags & VK_QUERY_RESULT_64_BIT) ?
sizeof(uint64_t) : sizeof(uint32_t);
VkResult result = VK_SUCCESS;
for (uint32_t q = 0; q < queryCount; q++) {
dzn_query *query = &qpool->queries[q + firstQuery];
uint8_t *dst_ptr = (uint8_t *)pData + (stride * q);
uint8_t *src_ptr =
(uint8_t *)qpool->collect_map +
dzn_query_pool_get_result_offset(qpool, firstQuery + q);
uint64_t available = 0;
if (flags & VK_QUERY_RESULT_WAIT_BIT) {
ComPtr<ID3D12Fence> query_fence(NULL);
uint64_t query_fence_val = 0;
while (true) {
mtx_lock(&qpool->queries_lock);
query_fence = ComPtr<ID3D12Fence>(query->fence);
query_fence_val = query->fence_value;
mtx_unlock(&qpool->queries_lock);
if (query_fence.Get())
break;
/* Check again in 10ms.
* FIXME: decrease the polling period if it happens to hurt latency.
*/
Sleep(10);
}
query_fence->SetEventOnCompletion(query_fence_val, NULL);
available = UINT64_MAX;
} else {
mtx_lock(&qpool->queries_lock);
ComPtr<ID3D12Fence> query_fence(query->fence);
uint64_t query_fence_val = query->fence_value;
mtx_unlock(&qpool->queries_lock);
if (query_fence.Get() &&
query_fence->GetCompletedValue() >= query_fence_val)
available = UINT64_MAX;
}
if (qpool->heap_type != D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS) {
if (available)
memcpy(dst_ptr, src_ptr, step);
else if (flags & VK_QUERY_RESULT_PARTIAL_BIT)
memset(dst_ptr, 0, step);
dst_ptr += step;
} else {
for (uint32_t c = 0; c < sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS) / sizeof(uint64_t); c++) {
if (!(BITFIELD_BIT(c) & qpool->pipeline_statistics))
continue;
if (available)
memcpy(dst_ptr, src_ptr + (c * sizeof(uint64_t)), step);
else if (flags & VK_QUERY_RESULT_PARTIAL_BIT)
memset(dst_ptr, 0, step);
dst_ptr += step;
}
}
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
memcpy(dst_ptr, &available, step);
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
}
return result;
}

View File

@ -0,0 +1,203 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_alloc.h"
#include "vk_debug_report.h"
#include "vk_util.h"
#include "util/macros.h"
#include "util/os_time.h"
static VkResult
dzn_sync_init(struct vk_device *device,
struct vk_sync *sync,
uint64_t initial_value)
{
dzn_sync *dsync = container_of(sync, dzn_sync, vk);
dzn_device *ddev = container_of(device, dzn_device, vk);
assert(!(sync->flags & VK_SYNC_IS_SHAREABLE));
if (FAILED(ddev->dev->CreateFence(initial_value, D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(&dsync->fence))))
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
return VK_SUCCESS;
}
static void
dzn_sync_finish(struct vk_device *device,
struct vk_sync *sync)
{
dzn_sync *dsync = container_of(sync, dzn_sync, vk);
dsync->fence->Release();
}
static VkResult
dzn_sync_signal(struct vk_device *device,
struct vk_sync *sync,
uint64_t value)
{
dzn_sync *dsync = container_of(sync, dzn_sync, vk);
if (!(sync->flags & VK_SYNC_IS_TIMELINE))
value = 1;
if (FAILED(dsync->fence->Signal(value)))
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
return VK_SUCCESS;
}
static VkResult
dzn_sync_get_value(struct vk_device *device,
struct vk_sync *sync,
uint64_t *value)
{
dzn_sync *dsync = container_of(sync, dzn_sync, vk);
*value = dsync->fence->GetCompletedValue();
return VK_SUCCESS;
}
static VkResult
dzn_sync_reset(struct vk_device *device,
struct vk_sync *sync)
{
dzn_sync *dsync = container_of(sync, dzn_sync, vk);
if (FAILED(dsync->fence->Signal(0)))
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
return VK_SUCCESS;
}
static VkResult
dzn_sync_move(struct vk_device *device,
struct vk_sync *dst,
struct vk_sync *src)
{
dzn_device *ddev = container_of(device, dzn_device, vk);
dzn_sync *ddst = container_of(dst, dzn_sync, vk);
dzn_sync *dsrc = container_of(src, dzn_sync, vk);
ID3D12Fence *new_fence;
if (FAILED(ddev->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(&new_fence))))
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
ddst->fence->Release();
ddst->fence = dsrc->fence;
dsrc->fence = new_fence;
return VK_SUCCESS;
}
static VkResult
dzn_sync_wait(struct vk_device *device,
uint32_t wait_count,
const struct vk_sync_wait *waits,
enum vk_sync_wait_flags wait_flags,
uint64_t abs_timeout_ns)
{
dzn_device *ddev = container_of(device, dzn_device, vk);
HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
if (event == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
STACK_ARRAY(ID3D12Fence *, fences, wait_count);
STACK_ARRAY(uint64_t, values, wait_count);
for (uint32_t i = 0; i < wait_count; i++) {
dzn_sync *sync = container_of(waits[i].sync, dzn_sync, vk);
fences[i] = sync->fence;
values[i] = (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? waits[i].wait_value : 1;
}
D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags =
(wait_flags & VK_SYNC_WAIT_ANY) ?
D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY :
D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL;
if (FAILED(ddev->dev->SetEventOnMultipleFenceCompletion(fences, values,
wait_count, flags,
event))) {
STACK_ARRAY_FINISH(fences);
STACK_ARRAY_FINISH(values);
CloseHandle(event);
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
}
DWORD timeout_ms;
if (abs_timeout_ns == OS_TIMEOUT_INFINITE) {
timeout_ms = INFINITE;
} else {
uint64_t cur_time = os_time_get_nano();
uint64_t rel_timeout_ns =
abs_timeout_ns > cur_time ? abs_timeout_ns - cur_time : 0;
timeout_ms = (rel_timeout_ns / 1000000) + (rel_timeout_ns % 1000000 ? 1 : 0);
}
DWORD res =
WaitForSingleObject(event, timeout_ms);
CloseHandle(event);
STACK_ARRAY_FINISH(fences);
STACK_ARRAY_FINISH(values);
if (res == WAIT_TIMEOUT)
return VK_TIMEOUT;
else if (res != WAIT_OBJECT_0)
return vk_error(device, VK_ERROR_UNKNOWN);
return VK_SUCCESS;
}
const struct vk_sync_type dzn_sync_type = {
.size = sizeof(dzn_sync),
.features = (enum vk_sync_features)
(VK_SYNC_FEATURE_BINARY |
VK_SYNC_FEATURE_TIMELINE |
VK_SYNC_FEATURE_GPU_WAIT |
VK_SYNC_FEATURE_GPU_MULTI_WAIT |
VK_SYNC_FEATURE_CPU_WAIT |
VK_SYNC_FEATURE_CPU_RESET |
VK_SYNC_FEATURE_CPU_SIGNAL |
VK_SYNC_FEATURE_WAIT_ANY |
VK_SYNC_FEATURE_WAIT_BEFORE_SIGNAL),
.init = dzn_sync_init,
.finish = dzn_sync_finish,
.signal = dzn_sync_signal,
.get_value = dzn_sync_get_value,
.reset = dzn_sync_reset,
.move = dzn_sync_move,
.wait_many = dzn_sync_wait,
};

View File

@ -0,0 +1,234 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <directx/d3d12.h>
#include <vulkan/vulkan.h>
#include "util/format/u_format.h"
static const DXGI_FORMAT formats[PIPE_FORMAT_COUNT] = {
#define MAP_FORMAT_NORM(FMT) \
[PIPE_FORMAT_ ## FMT ## _UNORM] = DXGI_FORMAT_ ## FMT ## _UNORM, \
[PIPE_FORMAT_ ## FMT ## _SNORM] = DXGI_FORMAT_ ## FMT ## _SNORM,
#define MAP_FORMAT_INT(FMT) \
[PIPE_FORMAT_ ## FMT ## _UINT] = DXGI_FORMAT_ ## FMT ## _UINT, \
[PIPE_FORMAT_ ## FMT ## _SINT] = DXGI_FORMAT_ ## FMT ## _SINT,
#define MAP_FORMAT_SRGB(FMT) \
[PIPE_FORMAT_ ## FMT ## _SRGB] = DXGI_FORMAT_ ## FMT ## _UNORM_SRGB,
#define MAP_FORMAT_FLOAT(FMT) \
[PIPE_FORMAT_ ## FMT ## _FLOAT] = DXGI_FORMAT_ ## FMT ## _FLOAT,
#define MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE) \
[PIPE_FORMAT_L ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
[PIPE_FORMAT_I ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
[PIPE_FORMAT_L ## BITS ## A ## BITS ## _ ## TYPE] = \
DXGI_FORMAT_R ## BITS ## G ## BITS ## _ ## TYPE,
#define MAP_EMU_FORMAT(BITS, TYPE) \
[PIPE_FORMAT_A ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE)
MAP_FORMAT_NORM(R8)
MAP_FORMAT_INT(R8)
MAP_FORMAT_NORM(R8G8)
MAP_FORMAT_INT(R8G8)
MAP_FORMAT_NORM(R8G8B8A8)
MAP_FORMAT_INT(R8G8B8A8)
MAP_FORMAT_SRGB(R8G8B8A8)
[PIPE_FORMAT_B8G8R8X8_UNORM] = DXGI_FORMAT_B8G8R8X8_UNORM,
[PIPE_FORMAT_B8G8R8A8_UNORM] = DXGI_FORMAT_B8G8R8A8_UNORM,
[PIPE_FORMAT_B4G4R4A4_UNORM] = DXGI_FORMAT_B4G4R4A4_UNORM,
[PIPE_FORMAT_A4R4G4B4_UNORM] = DXGI_FORMAT_B4G4R4A4_UNORM,
[PIPE_FORMAT_B5G6R5_UNORM] = DXGI_FORMAT_B5G6R5_UNORM,
[PIPE_FORMAT_B5G5R5A1_UNORM] = DXGI_FORMAT_B5G5R5A1_UNORM,
MAP_FORMAT_SRGB(B8G8R8A8)
MAP_FORMAT_INT(R32)
MAP_FORMAT_FLOAT(R32)
MAP_FORMAT_INT(R32G32)
MAP_FORMAT_FLOAT(R32G32)
MAP_FORMAT_INT(R32G32B32)
MAP_FORMAT_FLOAT(R32G32B32)
MAP_FORMAT_INT(R32G32B32A32)
MAP_FORMAT_FLOAT(R32G32B32A32)
MAP_FORMAT_NORM(R16)
MAP_FORMAT_INT(R16)
MAP_FORMAT_FLOAT(R16)
MAP_FORMAT_NORM(R16G16)
MAP_FORMAT_INT(R16G16)
MAP_FORMAT_FLOAT(R16G16)
MAP_FORMAT_NORM(R16G16B16A16)
MAP_FORMAT_INT(R16G16B16A16)
MAP_FORMAT_FLOAT(R16G16B16A16)
[PIPE_FORMAT_A8_UNORM] = DXGI_FORMAT_A8_UNORM,
MAP_EMU_FORMAT_NO_ALPHA(8, UNORM)
MAP_EMU_FORMAT(8, SNORM)
MAP_EMU_FORMAT(8, SINT)
MAP_EMU_FORMAT(8, UINT)
MAP_EMU_FORMAT(16, UNORM)
MAP_EMU_FORMAT(16, SNORM)
MAP_EMU_FORMAT(16, SINT)
MAP_EMU_FORMAT(16, UINT)
MAP_EMU_FORMAT(16, FLOAT)
MAP_EMU_FORMAT(32, SINT)
MAP_EMU_FORMAT(32, UINT)
MAP_EMU_FORMAT(32, FLOAT)
[PIPE_FORMAT_R9G9B9E5_FLOAT] = DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
[PIPE_FORMAT_R11G11B10_FLOAT] = DXGI_FORMAT_R11G11B10_FLOAT,
[PIPE_FORMAT_R10G10B10A2_UINT] = DXGI_FORMAT_R10G10B10A2_UINT,
[PIPE_FORMAT_R10G10B10A2_UNORM] = DXGI_FORMAT_R10G10B10A2_UNORM,
[PIPE_FORMAT_DXT1_RGB] = DXGI_FORMAT_BC1_UNORM,
[PIPE_FORMAT_DXT1_RGBA] = DXGI_FORMAT_BC1_UNORM,
[PIPE_FORMAT_DXT3_RGBA] = DXGI_FORMAT_BC2_UNORM,
[PIPE_FORMAT_DXT5_RGBA] = DXGI_FORMAT_BC3_UNORM,
[PIPE_FORMAT_DXT1_SRGB] = DXGI_FORMAT_BC1_UNORM_SRGB,
[PIPE_FORMAT_DXT1_SRGBA] = DXGI_FORMAT_BC1_UNORM_SRGB,
[PIPE_FORMAT_DXT3_SRGBA] = DXGI_FORMAT_BC2_UNORM_SRGB,
[PIPE_FORMAT_DXT5_SRGBA] = DXGI_FORMAT_BC3_UNORM_SRGB,
[PIPE_FORMAT_RGTC1_UNORM] = DXGI_FORMAT_BC4_UNORM,
[PIPE_FORMAT_RGTC1_SNORM] = DXGI_FORMAT_BC4_SNORM,
[PIPE_FORMAT_RGTC2_UNORM] = DXGI_FORMAT_BC5_UNORM,
[PIPE_FORMAT_RGTC2_SNORM] = DXGI_FORMAT_BC5_SNORM,
[PIPE_FORMAT_BPTC_RGB_UFLOAT] = DXGI_FORMAT_BC6H_UF16,
[PIPE_FORMAT_BPTC_RGB_FLOAT] = DXGI_FORMAT_BC6H_SF16,
[PIPE_FORMAT_BPTC_RGBA_UNORM] = DXGI_FORMAT_BC7_UNORM,
[PIPE_FORMAT_BPTC_SRGBA] = DXGI_FORMAT_BC7_UNORM_SRGB,
[PIPE_FORMAT_Z32_FLOAT] = DXGI_FORMAT_R32_TYPELESS,
[PIPE_FORMAT_Z16_UNORM] = DXGI_FORMAT_R16_TYPELESS,
[PIPE_FORMAT_Z24X8_UNORM] = DXGI_FORMAT_R24G8_TYPELESS,
[PIPE_FORMAT_X24S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
[PIPE_FORMAT_Z24_UNORM_S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
[PIPE_FORMAT_Z32_FLOAT_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
[PIPE_FORMAT_X32_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
};
DXGI_FORMAT
dzn_pipe_to_dxgi_format(enum pipe_format in)
{
return formats[in];
}
struct dzn_sampler_filter_info {
VkFilter min, mag;
VkSamplerMipmapMode mipmap;
};
#define FILTER(__min, __mag, __mipmap) \
{ \
.min = VK_FILTER_ ## __min, \
.mag = VK_FILTER_ ## __mag, \
.mipmap = VK_SAMPLER_MIPMAP_MODE_ ## __mipmap, \
}
static const struct dzn_sampler_filter_info filter_table[] = {
[D3D12_FILTER_MIN_MAG_MIP_POINT] = FILTER(NEAREST, NEAREST, NEAREST),
[D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR] = FILTER(NEAREST, NEAREST, LINEAR),
[D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT] = FILTER(NEAREST, LINEAR, NEAREST),
[D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR] = FILTER(NEAREST, LINEAR, LINEAR),
[D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT] = FILTER(LINEAR, NEAREST, NEAREST),
[D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR] = FILTER(LINEAR, NEAREST, LINEAR),
[D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT] = FILTER(LINEAR, LINEAR, NEAREST),
[D3D12_FILTER_MIN_MAG_MIP_LINEAR] = FILTER(LINEAR, LINEAR, LINEAR),
};
dzn_translate_sampler_filter(const VkSamplerCreateInfo *create_info)
{
D3D12_FILTER filter;
if (!create_info->anisotropyEnable) {
unsigned i;
for (i = 0; i < ARRAY_SIZE(filter_table); i++) {
if (create_info->minFilter == filter_table[i].min &&
create_info->magFilter == filter_table[i].mag &&
create_info->mipmapMode == filter_table[i].mipmap) {
filter = (D3D12_FILTER)i;
break;
}
}
assert(i < ARRAY_SIZE(filter_table));
} else {
filter = D3D12_FILTER_ANISOTROPIC;
}
if (create_info->compareEnable)
filter = (D3D12_FILTER)(filter + D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT);
return filter;
}
D3D12_COMPARISON_FUNC
dzn_translate_compare_op(VkCompareOp in)
{
switch (in) {
case VK_COMPARE_OP_NEVER: return D3D12_COMPARISON_FUNC_NEVER;
case VK_COMPARE_OP_LESS: return D3D12_COMPARISON_FUNC_LESS;
case VK_COMPARE_OP_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL;
case VK_COMPARE_OP_LESS_OR_EQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
case VK_COMPARE_OP_GREATER: return D3D12_COMPARISON_FUNC_GREATER;
case VK_COMPARE_OP_NOT_EQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
case VK_COMPARE_OP_GREATER_OR_EQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
case VK_COMPARE_OP_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS;
default: unreachable("Invalid compare op");
}
}
void
dzn_translate_viewport(D3D12_VIEWPORT *out,
const VkViewport *in)
{
out->TopLeftX = in->x;
out->TopLeftY = in->y;
out->Width = in->width;
out->Height = abs(in->height);
out->MinDepth = MIN2(in->minDepth, in->maxDepth);
out->MaxDepth = MAX2(in->maxDepth, in->minDepth);
}
void
dzn_translate_rect(D3D12_RECT *out,
const VkRect2D *in)
{
out->left = in->offset.x;
out->top = in->offset.y;
out->right = in->offset.x + in->extent.width;
out->bottom = in->offset.y + in->extent.height;
}

View File

@ -0,0 +1,226 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_enum_to_str.h"
#include <stdarg.h>
#include <stdio.h>
#include <directx/d3d12sdklayers.h>
IDXGIFactory4 *
dxgi_get_factory(bool debug)
{
static const GUID IID_IDXGIFactory4 = {
0x1bc6ea02, 0xef36, 0x464f,
{ 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a }
};
HMODULE dxgi_mod = LoadLibraryA("DXGI.DLL");
if (!dxgi_mod) {
mesa_loge("failed to load DXGI.DLL\n");
return NULL;
}
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY2)(UINT flags, REFIID riid, void **ppFactory);
PFN_CREATE_DXGI_FACTORY2 CreateDXGIFactory2;
CreateDXGIFactory2 = (PFN_CREATE_DXGI_FACTORY2)GetProcAddress(dxgi_mod, "CreateDXGIFactory2");
if (!CreateDXGIFactory2) {
mesa_loge("failed to load CreateDXGIFactory2 from DXGI.DLL\n");
return NULL;
}
UINT flags = 0;
if (debug)
flags |= DXGI_CREATE_FACTORY_DEBUG;
IDXGIFactory4 *factory;
HRESULT hr = CreateDXGIFactory2(flags, IID_IDXGIFactory4, (void **)&factory);
if (FAILED(hr)) {
mesa_loge("CreateDXGIFactory2 failed: %08x\n", hr);
return NULL;
}
return factory;
}
static ComPtr<ID3D12Debug>
get_debug_interface()
{
typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
HMODULE d3d12_mod = LoadLibraryA("D3D12.DLL");
if (!d3d12_mod) {
mesa_loge("failed to load D3D12.DLL\n");
return NULL;
}
D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d12_mod, "D3D12GetDebugInterface");
if (!D3D12GetDebugInterface) {
mesa_loge("failed to load D3D12GetDebugInterface from D3D12.DLL\n");
return NULL;
}
ComPtr<ID3D12Debug> debug;
if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
mesa_loge("D3D12GetDebugInterface failed\n");
return NULL;
}
return debug;
}
void
d3d12_enable_debug_layer()
{
ComPtr<ID3D12Debug> debug = get_debug_interface();
if (debug)
debug->EnableDebugLayer();
}
void
d3d12_enable_gpu_validation()
{
ComPtr<ID3D12Debug> debug = get_debug_interface();
ComPtr<ID3D12Debug3> debug3;
if (debug &&
SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3))))
debug3->SetEnableGPUBasedValidation(true);
}
ID3D12Device1 *
d3d12_create_device(IUnknown *adapter, bool experimental_features)
{
typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
PFN_D3D12CREATEDEVICE D3D12CreateDevice;
HMODULE d3d12_mod = LoadLibraryA("D3D12.DLL");
if (!d3d12_mod) {
mesa_loge("failed to load D3D12.DLL\n");
return NULL;
}
#ifdef _WIN32
if (experimental_features)
#endif
{
typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
(PFN_D3D12ENABLEEXPERIMENTALFEATURES)GetProcAddress(d3d12_mod, "D3D12EnableExperimentalFeatures");
if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
mesa_loge("failed to enable experimental shader models\n");
return nullptr;
}
}
D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)GetProcAddress(d3d12_mod, "D3D12CreateDevice");
if (!D3D12CreateDevice) {
mesa_loge("failed to load D3D12CreateDevice from D3D12.DLL\n");
return NULL;
}
ID3D12Device1 *dev;
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
IID_PPV_ARGS(&dev))))
return dev;
mesa_loge("D3D12CreateDevice failed\n");
return NULL;
}
IDxcValidator *
dxil_get_validator(void)
{
IDxcValidator *ret = NULL;
HMODULE dxil_mod = LoadLibraryA("dxil.dll");
if (!dxil_mod) {
mesa_loge("failed to load dxil.dll\n");
return ret;
}
DxcCreateInstanceProc CreateInstance = (DxcCreateInstanceProc)
GetProcAddress(dxil_mod, "DxcCreateInstance");
HRESULT hr = CreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&ret));
if (FAILED(hr))
mesa_loge("DxcCreateInstance failed: %08x\n", hr);
return ret;
}
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE
d3d12_get_serialize_root_sig(void)
{
HMODULE d3d12_mod = LoadLibraryA("d3d12.dll");
if (!d3d12_mod) {
mesa_loge("failed to load d3d12.dll\n");
return NULL;
}
return (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)
GetProcAddress(d3d12_mod, "D3D12SerializeVersionedRootSignature");
}
IDxcLibrary *
dxc_get_library(void)
{
IDxcLibrary *ret = NULL;
HMODULE dxil_mod = LoadLibraryA("dxcompiler.dll");
if (!dxil_mod) {
mesa_loge("failed to load dxcompiler.dll\n");
return ret;
}
DxcCreateInstanceProc CreateInstance = (DxcCreateInstanceProc)
GetProcAddress(dxil_mod, "DxcCreateInstance");
HRESULT hr = CreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&ret));
if (FAILED(hr))
mesa_loge("DxcCreateInstance failed: %08x\n", hr);
return ret;
}
IDxcCompiler *
dxc_get_compiler(void)
{
IDxcCompiler *ret = NULL;
HMODULE dxil_mod = LoadLibraryA("dxcompiler.dll");
if (!dxil_mod) {
mesa_loge("failed to load dxcompiler.dll\n");
return ret;
}
DxcCreateInstanceProc CreateInstance = (DxcCreateInstanceProc)
GetProcAddress(dxil_mod, "DxcCreateInstance");
HRESULT hr = CreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&ret));
if (FAILED(hr))
mesa_loge("DxcCreateInstance failed: %08x\n", hr);
return ret;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_util.h"
static PFN_vkVoidFunction VKAPI_PTR
dzn_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
{
VK_FROM_HANDLE(dzn_physical_device, pdevice, physicalDevice);
return vk_instance_get_proc_addr_unchecked(pdevice->vk.instance, pName);
}
void
dzn_wsi_finish(struct dzn_physical_device *physical_device)
{
wsi_device_finish(&physical_device->wsi_device,
&physical_device->vk.instance->alloc);
}
VkResult
dzn_wsi_init(struct dzn_physical_device *physical_device)
{
VkResult result;
/* TODO: implement a proper, non-sw winsys for D3D12 */
bool sw_device = true;
result = wsi_device_init(&physical_device->wsi_device,
dzn_physical_device_to_handle(physical_device),
dzn_wsi_proc_addr,
&physical_device->vk.instance->alloc,
-1, NULL, sw_device);
if (result != VK_SUCCESS)
return result;
physical_device->wsi_device.supports_modifiers = false;
physical_device->vk.wsi_device = &physical_device->wsi_device;
physical_device->wsi_device.signal_semaphore_with_memory = true;
physical_device->wsi_device.signal_fence_with_memory = true;
return VK_SUCCESS;
}

View File

@ -0,0 +1,123 @@
# Copyright © Microsoft Corporation
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
dzn_entrypoints = custom_target(
'dzn_entrypoints',
input : [vk_entrypoints_gen, vk_api_xml],
output : ['dzn_entrypoints.h', 'dzn_entrypoints.c'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--proto', '--weak',
'--out-h', '@OUTPUT0@', '--out-c', '@OUTPUT1@', '--prefix', 'dzn'
],
depend_files : vk_entrypoints_gen_depend_files,
)
libdzn_files = files(
'dzn_cmd_buffer.cpp',
'dzn_descriptor_set.cpp',
'dzn_device.cpp',
'dzn_image.cpp',
'dzn_meta.cpp',
'dzn_nir.c',
'dzn_pass.cpp',
'dzn_pipeline_cache.cpp',
'dzn_pipeline.cpp',
'dzn_query.cpp',
'dzn_sync.cpp',
'dzn_util.cpp',
'dzn_util.c',
'dzn_wsi.cpp',
)
dzn_deps = [
idep_libdxil_compiler,
idep_libspirv_to_dxil,
idep_nir,
idep_nir_headers,
idep_vulkan_util,
idep_vulkan_runtime,
idep_vulkan_wsi,
dep_dxheaders,
]
dzn_flags = [ ]
if with_platform_windows
dzn_flags += '-DVK_USE_PLATFORM_WIN32_KHR'
endif
libvulkan_dzn = shared_library(
'vulkan_dzn',
[libdzn_files, dzn_entrypoints, sha1_h],
vs_module_defs : 'vulkan_dzn.def',
include_directories : [
inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux,
inc_compiler, inc_util
],
dependencies : [dzn_deps, idep_vulkan_wsi],
c_args : dzn_flags,
cpp_args : dzn_flags,
gnu_symbol_visibility : 'hidden',
link_args : [ld_args_bsymbolic, ld_args_gc_sections],
name_prefix : host_machine.system() == 'windows' ? '' : 'lib',
install : true,
override_options: ['cpp_std=c++latest']
)
icd_file_name = 'libvulkan_dzn.so'
module_dir = join_paths(get_option('prefix'), get_option('libdir'))
if with_platform_windows
module_dir = join_paths(get_option('prefix'), get_option('bindir'))
icd_file_name = 'vulkan_dzn.dll'
endif
dzn_icd = custom_target(
'dzn_icd',
input : [vk_icd_gen, vk_api_xml],
output : 'dzn_icd.@0@.json'.format(host_machine.cpu()),
command : [
prog_python, '@INPUT0@',
'--api-version', '1.2', '--xml', '@INPUT1@',
'--lib-path', join_paths(module_dir, icd_file_name),
'--out', '@OUTPUT@',
],
build_by_default : true,
install_dir : with_vulkan_icd_dir,
install : true,
)
if meson.version().version_compare('>= 0.58')
_dev_icdname = 'dzn_devenv_icd.@0@.json'.format(host_machine.cpu())
custom_target(
'dzn_devenv_icd',
input : [vk_icd_gen, vk_api_xml],
output : _dev_icdname,
command : [
prog_python, '@INPUT0@',
'--api-version', '1.1', '--xml', '@INPUT1@',
'--lib-path', meson.current_build_dir() / icd_file_name,
'--out', '@OUTPUT@',
],
build_by_default : true,
)
devenv.append('VK_ICD_FILENAMES', meson.current_build_dir() / _dev_icdname)
endif

View File

@ -0,0 +1,4 @@
EXPORTS
vk_icdNegotiateLoaderICDInterfaceVersion
vk_icdGetInstanceProcAddr
vk_icdGetPhysicalDeviceProcAddr