From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../dxvk-native-1.9.2a/tests/d3d11/meson.build | 10 + .../tests/d3d11/test_d3d11_compute.cpp | 172 ++++++ .../tests/d3d11/test_d3d11_formats.cpp | 273 ++++++++++ .../tests/d3d11/test_d3d11_map_read.cpp | 203 +++++++ .../tests/d3d11/test_d3d11_streamout.cpp | 288 ++++++++++ .../tests/d3d11/test_d3d11_triangle.cpp | 606 +++++++++++++++++++++ .../tests/d3d11/test_d3d11_video.cpp | 459 ++++++++++++++++ .../dxvk-native-1.9.2a/tests/d3d11/video_image.raw | Bin 0 -> 49152 bytes 8 files changed, 2011 insertions(+) create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/meson.build create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_compute.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_formats.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_map_read.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_streamout.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_triangle.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_video.cpp create mode 100644 src/libs/dxvk-native-1.9.2a/tests/d3d11/video_image.raw (limited to 'src/libs/dxvk-native-1.9.2a/tests/d3d11') diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/meson.build b/src/libs/dxvk-native-1.9.2a/tests/d3d11/meson.build new file mode 100644 index 00000000..96fa90a3 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/meson.build @@ -0,0 +1,10 @@ +test_d3d11_deps = [ util_dep, lib_dxgi, lib_d3d11, lib_d3dcompiler_47 ] + +executable('d3d11-compute'+exe_ext, files('test_d3d11_compute.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) +executable('d3d11-formats'+exe_ext, files('test_d3d11_formats.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) +executable('d3d11-map-read'+exe_ext, files('test_d3d11_map_read.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) +executable('d3d11-streamout'+exe_ext, files('test_d3d11_streamout.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) +executable('d3d11-triangle'+exe_ext, files('test_d3d11_triangle.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) +executable('d3d11-video'+exe_ext, files('test_d3d11_video.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true, override_options: ['cpp_std='+dxvk_cpp_std]) + +install_data('video_image.raw', install_dir : get_option('bindir')) \ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_compute.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_compute.cpp new file mode 100644 index 00000000..87826581 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_compute.cpp @@ -0,0 +1,172 @@ +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_computeShaderCode = + "StructuredBuffer buf_in : register(t0);\n" + "RWStructuredBuffer buf_out : register(u0);\n" + "groupshared uint tmp[64];\n" + "[numthreads(64,1,1)]\n" + "void main(uint localId : SV_GroupIndex, uint3 globalId : SV_DispatchThreadID) {\n" + " tmp[localId] = buf_in[2 * globalId.x + 0]\n" + " + buf_in[2 * globalId.x + 1];\n" + " GroupMemoryBarrierWithGroupSync();\n" + " uint activeGroups = 32;\n" + " while (activeGroups != 0) {\n" + " if (localId < activeGroups)\n" + " tmp[localId] += tmp[localId + activeGroups];\n" + " GroupMemoryBarrierWithGroupSync();\n" + " activeGroups >>= 1;\n" + " }\n" + " if (localId == 0)\n" + " buf_out[0] = tmp[0];\n" + "}\n"; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + Com device; + Com context; + Com computeShader; + + Com srcBuffer; + Com dstBuffer; + Com readBuffer; + + Com srcView; + Com dstView; + + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &device, nullptr, &context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com computeShaderBlob; + + if (FAILED(D3DCompile( + g_computeShaderCode.data(), + g_computeShaderCode.size(), + "Compute shader", + nullptr, nullptr, + "main", "cs_5_0", 0, 0, + &computeShaderBlob, + nullptr))) { + std::cerr << "Failed to compile compute shader" << std::endl; + return 1; + } + + if (FAILED(device->CreateComputeShader( + computeShaderBlob->GetBufferPointer(), + computeShaderBlob->GetBufferSize(), + nullptr, &computeShader))) { + std::cerr << "Failed to create compute shader" << std::endl; + return 1; + } + + std::array srcData; + for (uint32_t i = 0; i < srcData.size(); i++) + srcData[i] = i + 1; + + D3D11_BUFFER_DESC srcBufferDesc; + srcBufferDesc.ByteWidth = sizeof(uint32_t) * srcData.size(); + srcBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + srcBufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + srcBufferDesc.CPUAccessFlags = 0; + srcBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + srcBufferDesc.StructureByteStride = sizeof(uint32_t); + + D3D11_SUBRESOURCE_DATA srcDataInfo; + srcDataInfo.pSysMem = srcData.data(); + srcDataInfo.SysMemPitch = 0; + srcDataInfo.SysMemSlicePitch = 0; + + if (FAILED(device->CreateBuffer(&srcBufferDesc, &srcDataInfo, &srcBuffer))) { + std::cerr << "Failed to create source buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC dstBufferDesc; + dstBufferDesc.ByteWidth = sizeof(uint32_t); + dstBufferDesc.Usage = D3D11_USAGE_DEFAULT; + dstBufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + dstBufferDesc.CPUAccessFlags = 0; + dstBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + dstBufferDesc.StructureByteStride = sizeof(uint32_t); + + if (FAILED(device->CreateBuffer(&dstBufferDesc, &srcDataInfo, &dstBuffer))) { + std::cerr << "Failed to create destination buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC readBufferDesc; + readBufferDesc.ByteWidth = sizeof(uint32_t); + readBufferDesc.Usage = D3D11_USAGE_STAGING; + readBufferDesc.BindFlags = 0; + readBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readBufferDesc.MiscFlags = 0; + readBufferDesc.StructureByteStride = 0; + + if (FAILED(device->CreateBuffer(&readBufferDesc, nullptr, &readBuffer))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srcViewDesc; + srcViewDesc.Format = DXGI_FORMAT_UNKNOWN; + srcViewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; + srcViewDesc.BufferEx.FirstElement = 0; + srcViewDesc.BufferEx.NumElements = srcData.size(); + srcViewDesc.BufferEx.Flags = 0; + + if (FAILED(device->CreateShaderResourceView(srcBuffer.ptr(), &srcViewDesc, &srcView))) { + std::cerr << "Failed to create shader resource view" << std::endl; + return 1; + } + + D3D11_UNORDERED_ACCESS_VIEW_DESC dstViewDesc; + dstViewDesc.Format = DXGI_FORMAT_UNKNOWN; + dstViewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + dstViewDesc.Buffer.FirstElement = 0; + dstViewDesc.Buffer.NumElements = 1; + dstViewDesc.Buffer.Flags = 0; + + if (FAILED(device->CreateUnorderedAccessView(dstBuffer.ptr(), &dstViewDesc, &dstView))) { + std::cerr << "Failed to create unordered access view" << std::endl; + return 1; + } + + // Compute sum of the source buffer values + context->CSSetShader(computeShader.ptr(), nullptr, 0); + context->CSSetShaderResources(0, 1, &srcView); + context->CSSetUnorderedAccessViews(0, 1, &dstView, nullptr); + context->Dispatch(1, 1, 1); + + // Write data to the readback buffer and query the result + context->CopyResource(readBuffer.ptr(), dstBuffer.ptr()); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + if (FAILED(context->Map(readBuffer.ptr(), 0, D3D11_MAP_READ, 0, &mappedResource))) { + std::cerr << "Failed to map readback buffer" << std::endl; + return 1; + } + + uint32_t result = 0; + std::memcpy(&result, mappedResource.pData, sizeof(result)); + context->Unmap(readBuffer.ptr(), 0); + + std::cout << "Sum of the numbers 1 to " << srcData.size() << " = " << result << std::endl; + context->ClearState(); + return 0; +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_formats.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_formats.cpp new file mode 100644 index 00000000..daac8365 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_formats.cpp @@ -0,0 +1,273 @@ +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +#undef ENUM_NAME +#define ENUM_NAME(e) case e: return #e; + +using namespace dxvk; + +std::string GetFormatName(DXGI_FORMAT Format) { + switch (Format) { + ENUM_NAME(DXGI_FORMAT_UNKNOWN); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT); + ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_SINT); + ENUM_NAME(DXGI_FORMAT_R32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_UINT); + ENUM_NAME(DXGI_FORMAT_R32_SINT); + ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT); + ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_SINT); + ENUM_NAME(DXGI_FORMAT_R16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16_FLOAT); + ENUM_NAME(DXGI_FORMAT_D16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UINT); + ENUM_NAME(DXGI_FORMAT_R16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16_SINT); + ENUM_NAME(DXGI_FORMAT_R8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8_UINT); + ENUM_NAME(DXGI_FORMAT_R8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8_SINT); + ENUM_NAME(DXGI_FORMAT_A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R1_UNORM); + ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP); + ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC4_UNORM); + ENUM_NAME(DXGI_FORMAT_BC4_SNORM); + ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC5_UNORM); + ENUM_NAME(DXGI_FORMAT_BC5_SNORM); + ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM); + ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC6H_UF16); + ENUM_NAME(DXGI_FORMAT_BC6H_SF16); + ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB); + default: return std::to_string(Format); + } +} + + +std::string GetFormatFlagName(D3D11_FORMAT_SUPPORT Flag) { + switch (Flag) { + ENUM_NAME(D3D11_FORMAT_SUPPORT_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SO_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE1D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE2D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE3D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURECUBE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_LOAD); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_MONO_TEXT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MIP); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MIP_AUTOGEN); + ENUM_NAME(D3D11_FORMAT_SUPPORT_RENDER_TARGET); + ENUM_NAME(D3D11_FORMAT_SUPPORT_BLENDABLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + ENUM_NAME(D3D11_FORMAT_SUPPORT_CPU_LOCKABLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DISPLAY); + ENUM_NAME(D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_GATHER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DECODER_OUTPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_ENCODER); + default: return std::to_string(Flag); + } +} + + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + Com device; + + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &device, nullptr, nullptr))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + D3D11_FEATURE_DATA_THREADING featureThreading = { }; + D3D11_FEATURE_DATA_DOUBLES featureDoubles = { }; + D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT featureMinPrecision = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS featureD3D11Options = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS1 featureD3D11Options1 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS2 featureD3D11Options2 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS3 featureD3D11Options3 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS4 featureD3D11Options4 = { }; + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_THREADING, &featureThreading, sizeof(featureThreading)))) { + std::cout << "D3D11_FEATURE_THREADING:" << std::endl + << " DriverConcurrentCreates: " << featureThreading.DriverConcurrentCreates << std::endl + << " DriverCommandLists: " << featureThreading.DriverCommandLists << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_DOUBLES, &featureDoubles, sizeof(featureDoubles)))) { + std::cout << "D3D11_FEATURE_DOUBLES:" << std::endl + << " DoublePrecisionFloatShaderOps: " << featureDoubles.DoublePrecisionFloatShaderOps << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT, &featureMinPrecision, sizeof(featureMinPrecision)))) { + std::cout << "D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT:" << std::endl + << " PixelShaderMinPrecision: " << featureMinPrecision.PixelShaderMinPrecision << std::endl + << " AllOtherShaderStagesMinPrecision: " << featureMinPrecision.AllOtherShaderStagesMinPrecision << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &featureD3D11Options, sizeof(featureD3D11Options)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS:" << std::endl + << " OutputMergerLogicOp: " << featureD3D11Options.OutputMergerLogicOp << std::endl + << " UAVOnlyRenderingForcedSampleCount: " << featureD3D11Options.UAVOnlyRenderingForcedSampleCount << std::endl + << " DiscardAPIsSeenByDriver: " << featureD3D11Options.DiscardAPIsSeenByDriver << std::endl + << " FlagsForUpdateAndCopySeenByDriver: " << featureD3D11Options.FlagsForUpdateAndCopySeenByDriver << std::endl + << " ClearView: " << featureD3D11Options.ClearView << std::endl + << " CopyWithOverlap: " << featureD3D11Options.CopyWithOverlap << std::endl + << " ConstantBufferPartialUpdate: " << featureD3D11Options.ConstantBufferPartialUpdate << std::endl + << " ConstantBufferOffsetting: " << featureD3D11Options.ConstantBufferOffsetting << std::endl + << " MapNoOverwriteOnDynamicConstantBuffer: " << featureD3D11Options.MapNoOverwriteOnDynamicConstantBuffer << std::endl + << " MapNoOverwriteOnDynamicBufferSRV: " << featureD3D11Options.MapNoOverwriteOnDynamicBufferSRV << std::endl + << " MultisampleRTVWithForcedSampleCountOne: " << featureD3D11Options.MultisampleRTVWithForcedSampleCountOne << std::endl + << " SAD4ShaderInstructions: " << featureD3D11Options.SAD4ShaderInstructions << std::endl + << " ExtendedDoublesShaderInstructions: " << featureD3D11Options.ExtendedDoublesShaderInstructions << std::endl + << " ExtendedResourceSharing: " << featureD3D11Options.ExtendedResourceSharing << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS1, &featureD3D11Options1, sizeof(featureD3D11Options1)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS1:" << std::endl + << " TiledResourcesTier: " << featureD3D11Options1.TiledResourcesTier << std::endl + << " MinMaxFiltering: " << featureD3D11Options1.MinMaxFiltering << std::endl + << " ClearViewAlsoSupportsDepthOnlyFormats: " << featureD3D11Options1.ClearViewAlsoSupportsDepthOnlyFormats << std::endl + << " MapOnDefaultBuffers: " << featureD3D11Options1.MapOnDefaultBuffers << std::endl; + + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &featureD3D11Options2, sizeof(featureD3D11Options2)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS2:" << std::endl + << " PSSpecifiedStencilRefSupported: " << featureD3D11Options2.PSSpecifiedStencilRefSupported << std::endl + << " TypedUAVLoadAdditionalFormats: " << featureD3D11Options2.TypedUAVLoadAdditionalFormats << std::endl + << " ROVsSupported: " << featureD3D11Options2.ROVsSupported << std::endl + << " ConservativeRasterizationTier: " << featureD3D11Options2.ConservativeRasterizationTier << std::endl + << " MapOnDefaultTextures: " << featureD3D11Options2.MapOnDefaultTextures << std::endl + << " TiledResourcesTier: " << featureD3D11Options2.TiledResourcesTier << std::endl + << " StandardSwizzle: " << featureD3D11Options2.StandardSwizzle << std::endl + << " UnifiedMemoryArchitecture: " << featureD3D11Options2.UnifiedMemoryArchitecture << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &featureD3D11Options3, sizeof(featureD3D11Options3)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS3:" << std::endl + << " VPAndRTArrayIndexFromAnyShaderFeedingRasterizer: " << featureD3D11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS4, &featureD3D11Options4, sizeof(featureD3D11Options4)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS4:" << std::endl + << " ExtendedNV12SharedTextureSupported: " << featureD3D11Options4.ExtendedNV12SharedTextureSupported << std::endl; + } + + for (UINT i = UINT(DXGI_FORMAT_UNKNOWN); + i <= UINT(DXGI_FORMAT_BC7_UNORM_SRGB); + i++) { + DXGI_FORMAT format = DXGI_FORMAT(i); + UINT flags = 0; + + std::cout << GetFormatName(format) << ": " << std::endl; + + if (SUCCEEDED(device->CheckFormatSupport(format, &flags))) { + for (uint32_t i = 0; i < 32; i++) { + if (flags & (1 << i)) { + std::cout << " " + << GetFormatFlagName(D3D11_FORMAT_SUPPORT(1 << i)) + << std::endl; + } + } + + } else { + std::cout << " Not supported" << std::endl; + } + } + + return 0; +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_map_read.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_map_read.cpp new file mode 100644 index 00000000..8e73dc45 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_map_read.cpp @@ -0,0 +1,203 @@ +#include +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_vsCode = + "float4 main(float4 v_pos : VS_POSITION) : SV_POSITION {\n" + " return v_pos;\n" + "}\n"; + +Com g_d3d11Device; +Com g_d3d11Context; + +Com g_vertShader; +Com g_inputLayout; + +Com g_vertexBuffer; + +Com g_depthRender; +Com g_depthRead; +Com g_depthView; +Comg_depthState; + +struct Vertex { + float x, y, z, w; +}; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &g_d3d11Device, nullptr, &g_d3d11Context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com vsBlob; + Com gsBlob; + + if (FAILED(D3DCompile(g_vsCode.data(), g_vsCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_4_0", + 0, 0, &vsBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateVertexShader( + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + nullptr, &g_vertShader))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return 1; + } + + std::array iaElements = {{ + { "VS_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(g_d3d11Device->CreateInputLayout( + iaElements.data(), + iaElements.size(), + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + &g_inputLayout))) { + std::cerr << "Failed to create input layout" << std::endl; + return 1; + } + + std::array vertexData = {{ + { -1.0f, -1.0f, 0.00f, 1.0f }, + { -1.0f, 1.0f, 0.66f, 1.0f }, + { 1.0f, -1.0f, 0.33f, 1.0f }, + { 1.0f, 1.0f, 1.00f, 1.0f }, + }}; + + D3D11_BUFFER_DESC vertexDesc; + vertexDesc.ByteWidth = vertexData.size() * sizeof(Vertex); + vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexDesc.CPUAccessFlags = 0; + vertexDesc.MiscFlags = 0; + vertexDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vertexInfo; + vertexInfo.pSysMem = vertexData.data(); + vertexInfo.SysMemPitch = vertexDesc.ByteWidth; + vertexInfo.SysMemSlicePitch = vertexDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&vertexDesc, &vertexInfo, &g_vertexBuffer))) { + std::cerr << "Failed to create vertex buffer" << std::endl; + return 1; + } + + D3D11_TEXTURE2D_DESC depthDesc; + depthDesc.Width = 16; + depthDesc.Height = 16; + depthDesc.MipLevels = 1; + depthDesc.ArraySize = 1; + depthDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + // depthDesc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + depthDesc.SampleDesc = { 1, 0 }; + depthDesc.Usage = D3D11_USAGE_DEFAULT; + depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthDesc.CPUAccessFlags = 0; + depthDesc.MiscFlags = 0; + + if (FAILED(g_d3d11Device->CreateTexture2D(&depthDesc, nullptr, &g_depthRender))) { + std::cerr << "Failed to create render buffer" << std::endl; + return 1; + } + + depthDesc.Usage = D3D11_USAGE_STAGING; + depthDesc.BindFlags = 0; + depthDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + + if (FAILED(g_d3d11Device->CreateTexture2D(&depthDesc, nullptr, &g_depthRead))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateDepthStencilView(g_depthRender.ptr(), nullptr, &g_depthView))) { + std::cerr << "Failed to create depth-stencil view" << std::endl; + return 1; + } + + D3D11_DEPTH_STENCIL_DESC dsDesc; + dsDesc.DepthEnable = TRUE; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = 0; + dsDesc.FrontFace = { }; + dsDesc.BackFace = { }; + + if (FAILED(g_d3d11Device->CreateDepthStencilState(&dsDesc, &g_depthState))) { + std::cerr << "Failed to create depth-stencil state" << std::endl; + return 1; + } + + FLOAT omBlendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + D3D11_VIEWPORT omViewport; + omViewport.TopLeftX = 0.0f; + omViewport.TopLeftY = 0.0f; + omViewport.Width = 16.0f; + omViewport.Height = 16.0f; + omViewport.MinDepth = 0.0f; + omViewport.MaxDepth = 1.0f; + + UINT vbOffset = 0; + UINT vbStride = sizeof(Vertex); + + g_d3d11Context->RSSetState(nullptr); + g_d3d11Context->RSSetViewports(1, &omViewport); + + g_d3d11Context->OMSetRenderTargets(0, nullptr, g_depthView.ptr()); + g_d3d11Context->OMSetBlendState(nullptr, omBlendFactor, 0xFFFFFFFF); + g_d3d11Context->OMSetDepthStencilState(g_depthState.ptr(), 0); + + g_d3d11Context->ClearDepthStencilView(g_depthView.ptr(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.5f, 0x80); + + g_d3d11Context->IASetInputLayout(g_inputLayout.ptr()); + g_d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + g_d3d11Context->IASetVertexBuffers(0, 1, &g_vertexBuffer, &vbStride, &vbOffset); + + g_d3d11Context->VSSetShader(g_vertShader.ptr(), nullptr, 0); + g_d3d11Context->Draw(4, 0); + + g_d3d11Context->CopyResource(g_depthRead.ptr(), g_depthRender.ptr()); + + D3D11_MAPPED_SUBRESOURCE mapped; + + if (FAILED(g_d3d11Context->Map(g_depthRead.ptr(), 0, D3D11_MAP_READ, 0, &mapped))) { + std::cerr << "Failed to map image" << std::endl; + return 1; + } + + for (uint32_t y = 0; y < 16; y++) { + auto data = reinterpret_cast(mapped.pData) + + (y * mapped.RowPitch / 4); + + for (uint32_t x = 0; x < 16; x++) + std::cout << std::hex << std::setfill('0') << std::setw(8) << data[x] << " "; + + std::cout << std::endl; + } + + g_d3d11Context->Unmap(g_depthRead.ptr(), 0); + g_d3d11Context->ClearState(); + return 0; +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_streamout.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_streamout.cpp new file mode 100644 index 00000000..3ff5f9ec --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_streamout.cpp @@ -0,0 +1,288 @@ +#include +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_vsCode = + "struct VS_IFACE {\n" + " float4 pos : VS_POSITION;\n" + "};\n" + "VS_IFACE main(VS_IFACE ia_in) {\n" + " return ia_in;\n" + "}\n"; + +const std::string g_gsCode = + "struct GS_IN {\n" + " float4 pos : VS_POSITION;\n" + "};\n" + "struct GS_OUT_NORMAL {\n" + " float3 nor : GS_NORMAL;\n" + " float len : GS_LENGTH;\n" + "};\n" + "[maxvertexcount(1)]\n" + "void main(triangle GS_IN vs_in[3], inout PointStream o_normals) {\n" + " float3 ds1 = vs_in[1].pos.xyz - vs_in[0].pos.xyz;\n" + " float3 ds2 = vs_in[2].pos.xyz - vs_in[0].pos.xyz;\n" + " float3 cv = cross(ds1, ds2);\n" + " float cl = length(cv);\n" + " GS_OUT_NORMAL normal;\n" + " normal.nor = cv / cl;\n" + " normal.len = cl;" + " o_normals.Append(normal);\n" + "}\n"; + +Com g_d3d11Device; +Com g_d3d11Context; + +Com g_vertShader; +Com g_geomShader; + +Com g_inputLayout; + +Com g_vertexBuffer; +Com g_normalBuffer; +Com g_readBuffer; + +Com g_soStream; +Com g_soOverflow; + +struct Vertex { + float x, y, z, w; +}; + +struct Normal { + float x, y, z, len; +}; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &g_d3d11Device, nullptr, &g_d3d11Context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com vsBlob; + Com gsBlob; + + if (FAILED(D3DCompile(g_vsCode.data(), g_vsCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_4_0", + 0, 0, &vsBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return 1; + } + + if (FAILED(D3DCompile(g_gsCode.data(), g_gsCode.size(), + "Geometry shader", nullptr, nullptr, "main", "gs_4_0", + 0, 0, &gsBlob, nullptr))) { + std::cerr << "Failed to compile geometry shader" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateVertexShader( + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + nullptr, &g_vertShader))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return 1; + } + + std::array soDeclarations = {{ + { 0, "GS_NORMAL", 0, 0, 3, 0 }, + { 0, "GS_LENGTH", 0, 0, 1, 0 }, + }}; + + std::array soBufferStrides = {{ + sizeof(Normal), + }}; + + if (FAILED(g_d3d11Device->CreateGeometryShaderWithStreamOutput( + gsBlob->GetBufferPointer(), + gsBlob->GetBufferSize(), + soDeclarations.data(), + soDeclarations.size(), + soBufferStrides.data(), + soBufferStrides.size(), + D3D11_SO_NO_RASTERIZED_STREAM, + nullptr, &g_geomShader))) { + std::cerr << "Failed to create geometry shader" << std::endl; + return 1; + } + + std::array iaElements = {{ + { "VS_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(g_d3d11Device->CreateInputLayout( + iaElements.data(), + iaElements.size(), + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + &g_inputLayout))) { + std::cerr << "Failed to create input layout" << std::endl; + return 1; + } + + std::array vertexData = {{ + { 0.0f, 0.0f, 0.0f, 1.0f }, + { 1.0f, 0.0f, 0.0f, 1.0f }, + { 0.0f, 1.0f, 0.0f, 1.0f }, + + { 0.5f,-1.0f,-0.2f, 1.0f }, + { 3.2f, 2.0f, 0.0f, 1.0f }, + {-1.0f,-1.0f, 0.4f, 1.0f }, + + { 0.7f,-0.5f,-0.8f, 1.0f }, + { 1.2f, 1.0f,-1.0f, 1.0f }, + {-0.1f, 1.0f,-2.7f, 1.0f }, + }}; + + D3D11_BUFFER_DESC vertexDesc; + vertexDesc.ByteWidth = vertexData.size() * sizeof(Vertex); + vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexDesc.CPUAccessFlags = 0; + vertexDesc.MiscFlags = 0; + vertexDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vertexInfo; + vertexInfo.pSysMem = vertexData.data(); + vertexInfo.SysMemPitch = vertexDesc.ByteWidth; + vertexInfo.SysMemSlicePitch = vertexDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&vertexDesc, &vertexInfo, &g_vertexBuffer))) { + std::cerr << "Failed to create vertex buffer" << std::endl; + return 1; + } + + std::array normalData = { }; + + D3D11_BUFFER_DESC normalDesc; + normalDesc.ByteWidth = normalData.size() * sizeof(Normal); + normalDesc.Usage = D3D11_USAGE_DEFAULT; + normalDesc.BindFlags = D3D11_BIND_STREAM_OUTPUT; + normalDesc.CPUAccessFlags = 0; + normalDesc.MiscFlags = 0; + normalDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA normalInfo; + normalInfo.pSysMem = normalData.data(); + normalInfo.SysMemPitch = normalDesc.ByteWidth; + normalInfo.SysMemSlicePitch = normalDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&normalDesc, &normalInfo, &g_normalBuffer))) { + std::cerr << "Failed to create normal buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC readDesc; + readDesc.ByteWidth = normalDesc.ByteWidth; + readDesc.Usage = D3D11_USAGE_STAGING; + readDesc.BindFlags = 0; + readDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readDesc.MiscFlags = 0; + readDesc.StructureByteStride = 0; + + if (FAILED(g_d3d11Device->CreateBuffer(&readDesc, nullptr, &g_readBuffer))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + D3D11_QUERY_DESC soQueryDesc; + soQueryDesc.Query = D3D11_QUERY_SO_STATISTICS_STREAM0; + soQueryDesc.MiscFlags = 0; + + if (FAILED(g_d3d11Device->CreateQuery(&soQueryDesc, &g_soStream))) { + std::cerr << "Failed to create streamout query" << std::endl; + return 1; + } + + soQueryDesc.Query = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0; + if (FAILED(g_d3d11Device->CreateQuery(&soQueryDesc, &g_soOverflow))) { + std::cerr << "Failed to create streamout overflow query" << std::endl; + return 1; + } + + UINT soOffset = 0; + UINT vbOffset = 0; + UINT vbStride = sizeof(Vertex); + + FLOAT omBlendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + D3D11_VIEWPORT omViewport; + omViewport.TopLeftX = 0.0f; + omViewport.TopLeftY = 0.0f; + omViewport.Width = 256.0f; + omViewport.Height = 256.0f; + omViewport.MinDepth = 0.0f; + omViewport.MaxDepth = 1.0f; + + g_d3d11Context->IASetInputLayout(g_inputLayout.ptr()); + g_d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + g_d3d11Context->IASetVertexBuffers(0, 1, &g_vertexBuffer, &vbStride, &vbOffset); + + g_d3d11Context->RSSetState(nullptr); + g_d3d11Context->RSSetViewports(1, &omViewport); + + g_d3d11Context->OMSetRenderTargets(0, nullptr, nullptr); + g_d3d11Context->OMSetBlendState(nullptr, omBlendFactor, 0xFFFFFFFF); + g_d3d11Context->OMSetDepthStencilState(nullptr, 0); + + g_d3d11Context->SOSetTargets(1, &g_normalBuffer, &soOffset); + + g_d3d11Context->VSSetShader(g_vertShader.ptr(), nullptr, 0); + g_d3d11Context->GSSetShader(g_geomShader.ptr(), nullptr, 0); + + g_d3d11Context->Begin(g_soStream.ptr()); + g_d3d11Context->Begin(g_soOverflow.ptr()); + + g_d3d11Context->Draw(vertexData.size(), 0); + + g_d3d11Context->End(g_soOverflow.ptr()); + g_d3d11Context->End(g_soStream.ptr()); + + g_d3d11Context->CopyResource( + g_readBuffer.ptr(), + g_normalBuffer.ptr()); + + D3D11_QUERY_DATA_SO_STATISTICS soQueryData = { }; + BOOL soOverflowData = false; + + while (g_d3d11Context->GetData(g_soStream.ptr(), &soQueryData, sizeof(soQueryData), 0) != S_OK + || g_d3d11Context->GetData(g_soOverflow.ptr(), &soOverflowData, sizeof(soOverflowData), 0) != S_OK) + continue; + + std::cout << "Written: " << soQueryData.NumPrimitivesWritten << std::endl; + std::cout << "Needed: " << soQueryData.PrimitivesStorageNeeded << std::endl; + std::cout << "Overflow: " << (soOverflowData ? "Yes" : "No") << std::endl; + + D3D11_MAPPED_SUBRESOURCE mapInfo; + + if (FAILED(g_d3d11Context->Map(g_readBuffer.ptr(), 0, D3D11_MAP_READ, 0, &mapInfo))) { + std::cerr << "Failed to map readback buffer" << std::endl; + return 1; + } + + std::memcpy(normalData.data(), mapInfo.pData, normalDesc.ByteWidth); + g_d3d11Context->Unmap(g_readBuffer.ptr(), 0); + + for (uint32_t i = 0; i < normalData.size(); i++) { + std::cout << i << ": " << normalData[i].x << "," + << normalData[i].y << "," << normalData[i].z << "," + << normalData[i].len << std::endl; + } + + return 0; +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_triangle.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_triangle.cpp new file mode 100644 index 00000000..5c2ea78f --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_triangle.cpp @@ -0,0 +1,606 @@ +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Vertex { + float x, y; +}; + +struct VsConstants { + float x, y; + float w, h; +}; + +struct VsConstantsPad { + VsConstants data; + uint32_t pad[60]; +}; + +struct PsConstants { + float r, g, b, a; +}; + +struct DrawOptions { + bool mapDiscardOnce; + bool sortByTexture; + bool drawIndexed; +}; + +const std::string g_vertexShaderCode = + "cbuffer vs_cb : register(b0) {\n" + " float2 v_offset;\n" + " float2 v_scale;\n" + "};\n" + "float4 main(float4 v_pos : IN_POSITION) : SV_POSITION {\n" + " float2 coord = 2.0f * (v_pos * v_scale + v_offset) - 1.0f;\n" + " return float4(coord, 0.0f, 1.0f);\n" + "}\n"; + +const std::string g_pixelShaderCode = + "Texture2D tex0 : register(t0);" + "cbuffer ps_cb : register(b0) {\n" + " float4 color;\n" + "};\n" + "float4 main() : SV_TARGET {\n" + " return color * tex0.Load(int3(0, 0, 0));\n" + "}\n"; + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + Com device; + + D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_1; + + HRESULT status = D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, &fl, 1, D3D11_SDK_VERSION, + &device, nullptr, nullptr); + + if (FAILED(status)) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return; + } + + if (FAILED(device->QueryInterface(IID_PPV_ARGS(&m_device)))) { + std::cerr << "Failed to query ID3D11DeviceContext1" << std::endl; + return; + } + + Com dxgiDevice; + + if (FAILED(m_device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)))) { + std::cerr << "Failed to query DXGI device" << std::endl; + return; + } + + if (FAILED(dxgiDevice->GetAdapter(&m_adapter))) { + std::cerr << "Failed to query DXGI adapter" << std::endl; + return; + } + + if (FAILED(m_adapter->GetParent(IID_PPV_ARGS(&m_factory)))) { + std::cerr << "Failed to query DXGI factory" << std::endl; + return; + } + + m_device->GetImmediateContext1(&m_context); + + DXGI_SWAP_CHAIN_DESC1 swapDesc; + swapDesc.Width = m_windowSizeW; + swapDesc.Height = m_windowSizeH; + swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapDesc.Stereo = FALSE; + swapDesc.SampleDesc = { 1, 0 }; + swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapDesc.BufferCount = 3; + swapDesc.Scaling = DXGI_SCALING_STRETCH; + swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT + | DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc; + fsDesc.RefreshRate = { 0, 0 }; + fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + fsDesc.Windowed = TRUE; + + Com swapChain; + if (FAILED(m_factory->CreateSwapChainForHwnd(m_device.ptr(), m_window, &swapDesc, &fsDesc, nullptr, &swapChain))) { + std::cerr << "Failed to create DXGI swap chain" << std::endl; + return; + } + + if (FAILED(swapChain->QueryInterface(IID_PPV_ARGS(&m_swapChain)))) { + std::cerr << "Failed to query DXGI swap chain interface" << std::endl; + return; + } + + m_factory->MakeWindowAssociation(m_window, 0); + + Com vertexShaderBlob; + Com pixelShaderBlob; + + if (FAILED(D3DCompile(g_vertexShaderCode.data(), g_vertexShaderCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return; + } + + if (FAILED(D3DCompile(g_pixelShaderCode.data(), g_pixelShaderCode.size(), + "Pixel shader", nullptr, nullptr, "main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr))) { + std::cerr << "Failed to compile pixel shader" << std::endl; + return; + } + + if (FAILED(m_device->CreateVertexShader( + vertexShaderBlob->GetBufferPointer(), + vertexShaderBlob->GetBufferSize(), + nullptr, &m_vs))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return; + } + + if (FAILED(m_device->CreatePixelShader( + pixelShaderBlob->GetBufferPointer(), + pixelShaderBlob->GetBufferSize(), + nullptr, &m_ps))) { + std::cerr << "Failed to create pixel shader" << std::endl; + return; + } + + std::array vertexFormatDesc = {{ + { "IN_POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(m_device->CreateInputLayout( + vertexFormatDesc.data(), + vertexFormatDesc.size(), + vertexShaderBlob->GetBufferPointer(), + vertexShaderBlob->GetBufferSize(), + &m_vertexFormat))) { + std::cerr << "Failed to create input layout" << std::endl; + return; + } + + std::array vertexData = {{ + Vertex { -0.3f, 0.1f }, + Vertex { 0.5f, 0.9f }, + Vertex { 1.3f, 0.1f }, + Vertex { -0.3f, 0.9f }, + Vertex { 1.3f, 0.9f }, + Vertex { 0.5f, 0.1f }, + }}; + + D3D11_BUFFER_DESC vboDesc; + vboDesc.ByteWidth = sizeof(vertexData); + vboDesc.Usage = D3D11_USAGE_IMMUTABLE; + vboDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vboDesc.CPUAccessFlags = 0; + vboDesc.MiscFlags = 0; + vboDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vboData; + vboData.pSysMem = vertexData.data(); + vboData.SysMemPitch = vboDesc.ByteWidth; + vboData.SysMemSlicePitch = vboDesc.ByteWidth; + + if (FAILED(m_device->CreateBuffer(&vboDesc, &vboData, &m_vbo))) { + std::cerr << "Failed to create index buffer" << std::endl; + return; + } + + std::array indexData = {{ 0, 1, 2, 3, 4, 5 }}; + + D3D11_BUFFER_DESC iboDesc; + iboDesc.ByteWidth = sizeof(indexData); + iboDesc.Usage = D3D11_USAGE_IMMUTABLE; + iboDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + iboDesc.CPUAccessFlags = 0; + iboDesc.MiscFlags = 0; + iboDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA iboData; + iboData.pSysMem = indexData.data(); + iboData.SysMemPitch = iboDesc.ByteWidth; + iboData.SysMemSlicePitch = iboDesc.ByteWidth; + + if (FAILED(m_device->CreateBuffer(&iboDesc, &iboData, &m_ibo))) { + std::cerr << "Failed to create index buffer" << std::endl; + return; + } + + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = sizeof(PsConstants); + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + cbDesc.StructureByteStride = 0; + + if (FAILED(m_device->CreateBuffer(&cbDesc, nullptr, &m_cbPs))) { + std::cerr << "Failed to create constant buffer" << std::endl; + return; + } + + cbDesc.ByteWidth = sizeof(VsConstantsPad) * 128 * 8; + + if (FAILED(m_device->CreateBuffer(&cbDesc, nullptr, &m_cbVs))) { + std::cerr << "Failed to create constant buffer" << std::endl; + return; + } + + std::array colors = { 0xFFFFFFFF, 0xFFC0C0C0 }; + + D3D11_SUBRESOURCE_DATA texData; + texData.pSysMem = &colors[0]; + texData.SysMemPitch = sizeof(colors[0]); + texData.SysMemSlicePitch = sizeof(colors[0]); + + D3D11_TEXTURE2D_DESC texDesc; + texDesc.Width = 1; + texDesc.Height = 1; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texDesc.SampleDesc = { 1, 0 }; + texDesc.Usage = D3D11_USAGE_IMMUTABLE; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; + texDesc.MiscFlags = 0; + + if (FAILED(m_device->CreateTexture2D(&texDesc, &texData, &m_tex0))) { + std::cerr << "Failed to create texture" << std::endl; + return; + } + + texData.pSysMem = &colors[1]; + + if (FAILED(m_device->CreateTexture2D(&texDesc, &texData, &m_tex1))) { + std::cerr << "Failed to create texture" << std::endl; + return; + } + + if (FAILED(m_device->CreateShaderResourceView(m_tex0.ptr(), nullptr, &m_srv0)) + || FAILED(m_device->CreateShaderResourceView(m_tex1.ptr(), nullptr, &m_srv1))) { + std::cerr << "Failed to create SRV" << std::endl; + return; + } + + m_initialized = true; + } + + + ~TriangleApp() { + m_context->ClearState(); + } + + + bool run() { + if (!m_initialized) + return false; + + if (m_occluded && (m_occluded = isOccluded())) + return true; + + if (!beginFrame()) + return true; + + std::array colors = {{ + PsConstants { 0.25f, 0.25f, 0.25f, 1.0f }, + PsConstants { 0.40f, 0.40f, 0.40f, 1.0f }, + }}; + + for (uint32_t i = 0; i < 8; i++) { + DrawOptions options; + options.sortByTexture = i & 1; + options.drawIndexed = i & 2; + options.mapDiscardOnce = i & 4; + drawLines(colors[i & 1], options, i); + } + + if (!endFrame()) + return false; + + updateFps(); + return true; + } + + + void drawLines(const PsConstants& psData, const DrawOptions& options, uint32_t baseY) { + D3D11_MAPPED_SUBRESOURCE sr; + + // Update color for the row + m_context->PSSetConstantBuffers(0, 1, &m_cbPs); + m_context->Map(m_cbPs.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + std::memcpy(sr.pData, &psData, sizeof(psData)); + m_context->Unmap(m_cbPs.ptr(), 0); + + baseY *= 8; + + if (options.mapDiscardOnce) { + uint32_t drawIndex = 0; + + // Discard and map the entire vertex constant buffer + // once, then bind sub-ranges while emitting draw calls + m_context->Map(m_cbVs.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + auto vsData = reinterpret_cast(sr.pData); + + for (uint32_t y = 0; y < 8; y++) { + for (uint32_t x = 0; x < 128; x++) + vsData[drawIndex++].data = getVsConstants(x, baseY + y); + } + + m_context->Unmap(m_cbVs.ptr(), 0); + } + + if (options.drawIndexed) + m_context->IASetIndexBuffer(m_ibo.ptr(), DXGI_FORMAT_R32_UINT, 0); + + uint32_t vsStride = sizeof(Vertex); + uint32_t vsOffset = 0; + m_context->IASetVertexBuffers(0, 1, &m_vbo, &vsStride, &vsOffset); + + uint32_t maxZ = options.sortByTexture ? 2 : 1; + + for (uint32_t z = 0; z < maxZ; z++) { + uint32_t drawIndex = z; + + if (options.sortByTexture) { + ID3D11ShaderResourceView* view = z ? m_srv1.ptr() : m_srv0.ptr(); + m_context->PSSetShaderResources(0, 1, &view); + } + + for (uint32_t y = 0; y < 8; y++) { + for (uint32_t x = z; x < 128; x += maxZ) { + uint32_t triIndex = (x ^ y) & 1; + + if (!options.mapDiscardOnce) { + D3D11_MAP mapMode = drawIndex ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD; + m_context->Map(m_cbVs.ptr(), 0, mapMode, 0, &sr); + auto vsData = reinterpret_cast(sr.pData); + vsData[drawIndex].data = getVsConstants(x, baseY + y); + m_context->Unmap(m_cbVs.ptr(), 0); + } + + uint32_t constantOffset = 16 * drawIndex; + uint32_t constantCount = 16; + m_context->VSSetConstantBuffers1(0, 1, &m_cbVs, &constantOffset, &constantCount); + + if (!options.sortByTexture) { + ID3D11ShaderResourceView* view = triIndex ? m_srv1.ptr() : m_srv0.ptr(); + m_context->PSSetShaderResources(0, 1, &view); + } + + // Submit draw call + uint32_t baseIndex = 3 * triIndex; + + if (options.drawIndexed) + m_context->DrawIndexed(3, baseIndex, 0); + else + m_context->Draw(3, baseIndex); + + drawIndex += maxZ; + } + } + } + } + + + static VsConstants getVsConstants(uint32_t x, uint32_t y) { + VsConstants result; + result.x = float(x) / 128.0f; + result.y = float(y) / 64.0f; + result.w = 1.0f / 128.0f; + result.h = 1.0f / 64.0f; + return result; + } + + + bool beginFrame() { + // Make sure we can actually render to the window + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + uint32_t newWindowSizeW = uint32_t(windowRect.right - windowRect.left); + uint32_t newWindowSizeH = uint32_t(windowRect.bottom - windowRect.top); + + if (m_windowSizeW != newWindowSizeW || m_windowSizeH != newWindowSizeH) { + m_rtv = nullptr; + m_context->ClearState(); + + DXGI_SWAP_CHAIN_DESC1 desc; + m_swapChain->GetDesc1(&desc); + + if (FAILED(m_swapChain->ResizeBuffers(desc.BufferCount, + newWindowSizeW, newWindowSizeH, desc.Format, desc.Flags))) { + std::cerr << "Failed to resize back buffers" << std::endl; + return false; + } + + Com backBuffer; + if (FAILED(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)))) { + std::cerr << "Failed to get swap chain back buffer" << std::endl; + return false; + } + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + rtvDesc.Texture2D = { 0u }; + + if (FAILED(m_device->CreateRenderTargetView(backBuffer.ptr(), &rtvDesc, &m_rtv))) { + std::cerr << "Failed to create render target view" << std::endl; + return false; + } + + m_windowSizeW = newWindowSizeW; + m_windowSizeH = newWindowSizeH; + } + + // Set up render state + FLOAT color[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + m_context->OMSetRenderTargets(1, &m_rtv, nullptr); + m_context->ClearRenderTargetView(m_rtv.ptr(), color); + + m_context->VSSetShader(m_vs.ptr(), nullptr, 0); + m_context->PSSetShader(m_ps.ptr(), nullptr, 0); + + m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + m_context->IASetInputLayout(m_vertexFormat.ptr()); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = float(m_windowSizeW); + viewport.Height = float(m_windowSizeH); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + m_context->RSSetViewports(1, &viewport); + return true; + } + + + bool endFrame() { + HRESULT hr = m_swapChain->Present(0, DXGI_PRESENT_TEST); + + if (hr == S_OK) + hr = m_swapChain->Present(0, 0); + + m_occluded = hr == DXGI_STATUS_OCCLUDED; + return true; + } + + void updateFps() { + if (!m_qpcFrequency.QuadPart) + QueryPerformanceFrequency(&m_qpcFrequency); + + if (!m_qpcLastUpdate.QuadPart) + QueryPerformanceCounter(&m_qpcLastUpdate); + + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + + m_frameCount++; + + if (now.QuadPart - m_qpcLastUpdate.QuadPart < m_qpcFrequency.QuadPart) + return; + + double seconds = double(now.QuadPart - m_qpcLastUpdate.QuadPart) / double(m_qpcFrequency.QuadPart); + double fps = double(m_frameCount) / seconds; + + std::wstringstream str; + str << L"D3D11 triangle (" << fps << L" FPS)"; + + SetWindowTextW(m_window, str.str().c_str()); + + m_qpcLastUpdate = now; + m_frameCount = 0; + } + + bool isOccluded() { + return m_swapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED; + } + +private: + + HWND m_window; + uint32_t m_windowSizeW = 1024; + uint32_t m_windowSizeH = 600; + bool m_initialized = false; + bool m_occluded = false; + + Com m_factory; + Com m_adapter; + Com m_device; + Com m_context; + Com m_swapChain; + + Com m_rtv; + Com m_ibo; + Com m_vbo; + Com m_vertexFormat; + + Com m_tex0; + Com m_tex1; + Com m_srv0; + Com m_srv1; + + Com m_cbPs; + Com m_cbVs; + + Com m_vs; + Com m_ps; + + LARGE_INTEGER m_qpcLastUpdate = { }; + LARGE_INTEGER m_qpcFrequency = { }; + + uint32_t m_frameCount = 0; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + WNDCLASSEXW wc = { }; + wc.cbSize = sizeof(wc); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = HBRUSH(COLOR_WINDOW); + wc.lpszClassName = L"WindowClass"; + RegisterClassExW(&wc); + + HWND hWnd = CreateWindowExW(0, L"WindowClass", L"D3D11 triangle", + WS_OVERLAPPEDWINDOW, 300, 300, 1024, 600, + nullptr, nullptr, hInstance, nullptr); + ShowWindow(hWnd, nCmdShow); + + TriangleApp app(hInstance, hWnd); + + MSG msg; + + while (true) { + if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + if (!app.run()) + break; + } + } + + return msg.wParam; +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProcW(hWnd, message, wParam, lParam); +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_video.cpp b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_video.cpp new file mode 100644 index 00000000..a974962a --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/tests/d3d11/test_d3d11_video.cpp @@ -0,0 +1,459 @@ +#include + +#include +#include + +#include +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +class VideoApp { + +public: + + VideoApp(HINSTANCE instance, HWND window) + : m_window(window) { + // Create base D3D11 device and swap chain + DXGI_SWAP_CHAIN_DESC swapchainDesc = { }; + swapchainDesc.BufferDesc.Width = m_windowSizeX; + swapchainDesc.BufferDesc.Height = m_windowSizeY; + swapchainDesc.BufferDesc.RefreshRate = { 0, 0 }; + swapchainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchainDesc.BufferCount = 2; + swapchainDesc.SampleDesc = { 1, 0 }; + swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchainDesc.OutputWindow = m_window; + swapchainDesc.Windowed = true; + swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapchainDesc.Flags = 0; + + HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, + D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, + D3D11_SDK_VERSION, &swapchainDesc, &m_swapchain, + &m_device, nullptr, &m_context); + + if (FAILED(hr)) { + std::cerr << "Failed to initialize D3D11 device and swap chain" << std::endl; + return; + } + + if (FAILED(hr = m_device->QueryInterface(IID_PPV_ARGS(&m_vdevice)))) { + std::cerr << "Failed to query D3D11 video device" << std::endl; + return; + } + + if (FAILED(hr = m_context->QueryInterface(IID_PPV_ARGS(&m_vcontext)))) { + std::cerr << "Failed to query D3D11 video context" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->ResizeTarget(&swapchainDesc.BufferDesc))) { + std::cerr << "Failed to resize target" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->GetBuffer(0, IID_PPV_ARGS(&m_swapImage)))) { + std::cerr << "Failed to query swap chain image" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_swapImage.ptr(), nullptr, &m_swapImageView))) { + std::cerr << "Failed to create render target view" << std::endl; + return; + } + + // Create video processor instance + D3D11_VIDEO_PROCESSOR_CONTENT_DESC videoEnumDesc = { }; + videoEnumDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE; + videoEnumDesc.InputFrameRate = { 60, 1 }; + videoEnumDesc.InputWidth = 128; + videoEnumDesc.InputHeight = 128; + videoEnumDesc.OutputFrameRate = { 60, 1 }; + videoEnumDesc.OutputWidth = 256; + videoEnumDesc.OutputHeight = 256; + videoEnumDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorEnumerator(&videoEnumDesc, &m_venum))) { + std::cerr << "Failed to create D3D11 video processor enumerator" << std::endl; + return; + } + + if (FAILED(hr = m_vdevice->CreateVideoProcessor(m_venum.ptr(), 0, &m_vprocessor))) { + std::cerr << "Failed to create D3D11 video processor" << std::endl; + return; + } + + // Video output image and view + D3D11_TEXTURE2D_DESC textureDesc = { }; + textureDesc.Width = 256; + textureDesc.Height = 256; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + textureDesc.SampleDesc = { 1, 0 }; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + + if (FAILED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoOutput))) { + std::cerr << "Failed to create D3D11 video output image" << std::endl; + return; + } + + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputDesc = { }; + outputDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; + outputDesc.Texture2D.MipSlice = 0; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorOutputView(m_videoOutput.ptr(), m_venum.ptr(), &outputDesc, &m_videoOutputView))) { + std::cerr << "Failed to create D3D11 video output view" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_videoOutput.ptr(), nullptr, &m_videoOutputRtv))) { + std::cerr << "Failed to create video render target view" << std::endl; + return; + } + + // RGBA input image and view + textureDesc.Width = 128; + textureDesc.Height = 128; + textureDesc.BindFlags = 0; + + size_t pixelCount = textureDesc.Width * textureDesc.Height; + + size_t rowSizeRgba = textureDesc.Width * 4; + size_t rowSizeNv12 = textureDesc.Width; + size_t rowSizeYuy2 = textureDesc.Width * 2; + size_t imageSizeRgba = textureDesc.Height * rowSizeRgba; + size_t imageSizeNv12 = pixelCount + pixelCount / 2; + size_t imageSizeYuy2 = textureDesc.Height * rowSizeYuy2; + + std::vector srcData(pixelCount * 3); + std::vector imgDataRgba(imageSizeRgba); + std::vector imgDataNv12(imageSizeNv12); + std::vector imgDataYuy2(imageSizeYuy2); + std::ifstream ifile("video_image.raw", std::ios::binary); + + if (!ifile || !ifile.read(reinterpret_cast(srcData.data()), srcData.size())) { + std::cerr << "Failed to read image file" << std::endl; + return; + } + + for (size_t i = 0; i < pixelCount; i++) { + imgDataRgba[4 * i + 0] = srcData[3 * i + 0]; + imgDataRgba[4 * i + 1] = srcData[3 * i + 1]; + imgDataRgba[4 * i + 2] = srcData[3 * i + 2]; + imgDataRgba[4 * i + 3] = 0xFF; + + imgDataNv12[i] = y_coeff(&srcData[3 * i], 0.299000f, 0.587000f, 0.114000f); + + imgDataYuy2[2 * i + 0] = y_coeff(&srcData[3 * i], 0.299000f, 0.587000f, 0.114000f); + imgDataYuy2[2 * i + 1] = i % 2 + ? c_coeff(&srcData[3 * i], -0.168736f, -0.331264f, 0.500000f) + : c_coeff(&srcData[3 * i], 0.500000f, -0.418688f, -0.081312f); + } + + for (size_t y = 0; y < textureDesc.Height / 2; y++) { + for (size_t x = 0; x < textureDesc.Width / 2; x++) { + size_t p = textureDesc.Width * (2 * y) + 2 * x; + size_t i = pixelCount + textureDesc.Width * y + 2 * x; + imgDataNv12[i + 0] = c_coeff(&srcData[3 * p], 0.500000f, -0.418688f, -0.081312f); + imgDataNv12[i + 1] = c_coeff(&srcData[3 * p], -0.168736f, -0.331264f, 0.500000f); + } + } + + D3D11_SUBRESOURCE_DATA subresourceData = { }; + subresourceData.pSysMem = imgDataRgba.data(); + subresourceData.SysMemPitch = rowSizeRgba; + subresourceData.SysMemSlicePitch = rowSizeRgba * textureDesc.Height; + + if (FAILED(hr = m_device->CreateTexture2D(&textureDesc, &subresourceData, &m_videoInput))) { + std::cerr << "Failed to create D3D11 video input image" << std::endl; + return; + } + + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputDesc = { }; + inputDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; + inputDesc.Texture2D.MipSlice = 0; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInput.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputView))) { + std::cerr << "Failed to create D3D11 video input view" << std::endl; + return; + } + + // NV12 input image and view + textureDesc.Format = DXGI_FORMAT_NV12; + textureDesc.BindFlags = 0; + + subresourceData.pSysMem = imgDataNv12.data(); + subresourceData.SysMemPitch = rowSizeNv12; + subresourceData.SysMemSlicePitch = rowSizeNv12 * textureDesc.Height; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoInputNv12))) { + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInputNv12.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputViewNv12))) { + std::cerr << "Failed to create D3D11 video input view for NV12" << std::endl; + return; + } + } else { + std::cerr << "NV12 not supported" << std::endl; + } + + textureDesc.Usage = D3D11_USAGE_STAGING; + textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoInputNv12Host))) { + D3D11_MAPPED_SUBRESOURCE mr = { }; + m_context->Map(m_videoInputNv12Host.ptr(), 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &mr); + memcpy(mr.pData, imgDataNv12.data(), imgDataNv12.size()); + m_context->Unmap(m_videoInputNv12Host.ptr(), 0); + D3D11_BOX box = { 0, 0, 0, 128, 128, 1 }; + m_context->CopySubresourceRegion(m_videoInputNv12.ptr(), 0, 0, 0, 0, m_videoInputNv12Host.ptr(), 0, &box); + } + + // YUY2 input image and view + textureDesc.Format = DXGI_FORMAT_YUY2; + textureDesc.BindFlags = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.CPUAccessFlags = 0; + + subresourceData.pSysMem = imgDataYuy2.data(); + subresourceData.SysMemPitch = rowSizeYuy2; + subresourceData.SysMemSlicePitch = imageSizeYuy2; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, &subresourceData, &m_videoInputYuy2))) { + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInputYuy2.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputViewYuy2))) { + std::cerr << "Failed to create D3D11 video input view for YUY2" << std::endl; + return; + } + } else { + std::cerr << "YUY2 not supported" << std::endl; + } + + m_initialized = true; + } + + + ~VideoApp() { + + } + + + void run() { + this->adjustBackBuffer(); + + float color[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + m_context->ClearRenderTargetView(m_swapImageView.ptr(), color); + + // Full range RGB output color space + D3D11_VIDEO_PROCESSOR_COLOR_SPACE csOut = { }; + csOut.Usage = 0; // Present + csOut.RGB_Range = 0; // Full range + csOut.Nominal_Range = 1; // Full range + + D3D11_VIDEO_PROCESSOR_COLOR_SPACE csIn = { }; + csIn.Usage = 0; // Present + csIn.RGB_Range = 0; // Full range + csIn.Nominal_Range = 1; // Full range + csIn.YCbCr_Matrix = 0; // BT.601 + + m_vcontext->VideoProcessorSetStreamAutoProcessingMode(m_vprocessor.ptr(), 0, false); + m_vcontext->VideoProcessorSetOutputColorSpace(m_vprocessor.ptr(), &csOut); + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 32, 32); + blit(m_videoInputViewNv12.ptr(), 32, 320); + blit(m_videoInputViewYuy2.ptr(), 32, 608); + + csIn.RGB_Range = 1; // Limited range + csIn.Nominal_Range = 0; // Limited range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 320, 32); + blit(m_videoInputViewNv12.ptr(), 320, 320); + blit(m_videoInputViewYuy2.ptr(), 320, 608); + + // Limited range RGB output color space + csOut.RGB_Range = 1; + csOut.Nominal_Range = 0; + m_vcontext->VideoProcessorSetOutputColorSpace(m_vprocessor.ptr(), &csOut); + + csIn.RGB_Range = 0; // Full range + csIn.Nominal_Range = 1; // Full range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 608, 32); + blit(m_videoInputViewNv12.ptr(), 608, 320); + blit(m_videoInputViewYuy2.ptr(), 608, 608); + + csIn.RGB_Range = 1; // Limited range + csIn.Nominal_Range = 0; // Limited range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 896, 32); + blit(m_videoInputViewNv12.ptr(), 896, 320); + blit(m_videoInputViewYuy2.ptr(), 896, 608); + + m_swapchain->Present(1, 0); + } + + + void blit(ID3D11VideoProcessorInputView* pView, uint32_t x, uint32_t y) { + if (!pView) + return; + + D3D11_VIDEO_PROCESSOR_STREAM stream = { }; + stream.Enable = true; + stream.pInputSurface = pView; + + D3D11_BOX box; + box.left = 0; + box.top = 0; + box.front = 0; + box.right = 256; + box.bottom = 256; + box.back = 1; + + FLOAT red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; + m_context->ClearRenderTargetView(m_videoOutputRtv.ptr(), red); + m_vcontext->VideoProcessorBlt(m_vprocessor.ptr(), m_videoOutputView.ptr(), 0, 1, &stream); + m_context->CopySubresourceRegion(m_swapImage.ptr(), 0, x, y, 0, m_videoOutput.ptr(), 0, &box); + } + + + void adjustBackBuffer() { + RECT windowRect = { }; + GetClientRect(m_window, &windowRect); + + if (uint32_t(windowRect.right - windowRect.left) != m_windowSizeX + || uint32_t(windowRect.bottom - windowRect.top) != m_windowSizeY) { + m_windowSizeX = windowRect.right - windowRect.left; + m_windowSizeY = windowRect.bottom - windowRect.top; + + m_swapImage = nullptr; + m_swapImageView = nullptr; + + HRESULT hr = m_swapchain->ResizeBuffers(0, + m_windowSizeX, m_windowSizeY, DXGI_FORMAT_UNKNOWN, 0); + + if (FAILED(hr)) { + std::cerr << "Failed to resize swap chain buffer" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->GetBuffer(0, IID_PPV_ARGS(&m_swapImage)))) { + std::cerr << "Failed to query swap chain image" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_swapImage.ptr(), nullptr, &m_swapImageView))) { + std::cerr << "Failed to create render target view" << std::endl; + return; + } + } + } + + operator bool () const { + return m_initialized; + } + +private: + + HWND m_window; + uint32_t m_windowSizeX = 1280; + uint32_t m_windowSizeY = 720; + + Com m_swapchain; + Com m_device; + Com m_context; + Com m_vdevice; + Com m_vcontext; + Com m_venum; + Com m_vprocessor; + Com m_swapImage; + Com m_swapImageView; + Com m_videoOutput; + Com m_videoOutputView; + Com m_videoOutputRtv; + Com m_videoInput; + Com m_videoInputView; + Com m_videoInputNv12; + Com m_videoInputNv12Host; + Com m_videoInputYuy2; + Com m_videoInputViewNv12; + Com m_videoInputViewYuy2; + + bool m_initialized = false; + + static inline uint8_t y_coeff(const uint8_t* rgb, float r, float g, float b) { + float x = (rgb[0] * r + rgb[1] * g + rgb[2] * b) / 255.0f; + return 16 + uint8_t(std::roundf(219.0f * std::clamp(x, 0.0f, 1.0f))); + } + + static inline uint8_t c_coeff(const uint8_t* rgb, float r, float g, float b) { + float x = ((rgb[0] * r + rgb[1] * g + rgb[2] * b) / 255.0f) + 0.5f; + return uint8_t(std::roundf(255.0f * std::clamp(x, 0.0f, 1.0f))); + } + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 1280, 720, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + VideoApp app(hInstance, hWnd); + + while (app) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + + return 0; +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/src/libs/dxvk-native-1.9.2a/tests/d3d11/video_image.raw b/src/libs/dxvk-native-1.9.2a/tests/d3d11/video_image.raw new file mode 100644 index 00000000..7d1b5f38 Binary files /dev/null and b/src/libs/dxvk-native-1.9.2a/tests/d3d11/video_image.raw differ -- cgit v1.2.3