mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 02:52:10 +01:00
[tests] Update D3D11 triangle test
Essentially implements a microbenchmark for state changes.
This commit is contained in:
parent
08a6b42458
commit
1516464c8b
@ -1,112 +1,59 @@
|
||||
#include <d3dcompiler.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_3.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <thread>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "../../src/util/thread.h"
|
||||
#include "../test_utils.h"
|
||||
|
||||
using namespace dxvk;
|
||||
|
||||
struct Extent2D {
|
||||
uint32_t w, h;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float x, y, z, w;
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct Color {
|
||||
uint8_t r, g, b, a;
|
||||
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;
|
||||
};
|
||||
|
||||
bool m_report = false;
|
||||
|
||||
const std::string g_vertexShaderCode =
|
||||
"Buffer<float4> buf : register(t0);\n"
|
||||
"struct vs_out {\n"
|
||||
" float4 pos : POSITION;\n"
|
||||
" float4 color : COLOR;\n"
|
||||
"cbuffer vs_cb : register(b0) {\n"
|
||||
" float2 v_offset;\n"
|
||||
" float2 v_scale;\n"
|
||||
"};\n"
|
||||
"vs_out main(float4 vsIn : IN_POSITION,\n"
|
||||
" uint vid : SV_VERTEXID,\n"
|
||||
" uint iid : SV_INSTANCEID) {\n"
|
||||
" vs_out result;\n"
|
||||
" result.pos = vsIn;\n"
|
||||
" result.color.x = buf[vid].x;\n"
|
||||
" result.color.y = buf[iid * 3].y;\n"
|
||||
" result.color.z = buf[0].z;\n"
|
||||
" result.color.w = 1.0f;\n"
|
||||
" return result;\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_hullShaderCode =
|
||||
"struct vs_out {\n"
|
||||
" float4 pos : POSITION;\n"
|
||||
" float4 color : COLOR;\n"
|
||||
"};\n"
|
||||
"struct hs_vtx {\n"
|
||||
" float4 pos : POSITION;\n"
|
||||
"};\n"
|
||||
"struct hs_patch {\n"
|
||||
" float4 color : COLOR;\n"
|
||||
" float tessEdge[3] : SV_TessFactor;\n"
|
||||
" float tessInner : SV_InsideTessFactor;\n"
|
||||
"};\n"
|
||||
"hs_patch main_pc(InputPatch<vs_out, 3> ip) {\n"
|
||||
" hs_patch ov;\n"
|
||||
" ov.color = ip[0].color;\n"
|
||||
" ov.tessEdge[0] = 4.0f;\n"
|
||||
" ov.tessEdge[1] = 4.0f;\n"
|
||||
" ov.tessEdge[2] = 4.0f;\n"
|
||||
" ov.tessInner = 4.0f;\n"
|
||||
" return ov;\n"
|
||||
"}\n"
|
||||
"[domain(\"tri\")]\n"
|
||||
"[partitioning(\"fractional_odd\")]\n"
|
||||
"[outputtopology(\"triangle_cw\")]\n"
|
||||
"[outputcontrolpoints(3)]\n"
|
||||
"[patchconstantfunc(\"main_pc\")]\n"
|
||||
"hs_vtx main(InputPatch<vs_out, 3> ip, uint i : SV_OutputControlPointID) {\n"
|
||||
" hs_vtx ov;\n"
|
||||
" ov.pos = ip[i].pos;\n"
|
||||
" return ov;\n"
|
||||
"}\n";
|
||||
|
||||
const std::string g_domainShaderCode =
|
||||
"struct ds_out {\n"
|
||||
" float4 pos : SV_POSITION;\n"
|
||||
" float4 color : COLOR;\n"
|
||||
"};\n"
|
||||
"struct hs_vtx {\n"
|
||||
" float4 pos : POSITION;\n"
|
||||
"};\n"
|
||||
"struct hs_patch {\n"
|
||||
" float4 color : COLOR;\n"
|
||||
" float tessEdge[3] : SV_TessFactor;\n"
|
||||
" float tessInner : SV_InsideTessFactor;\n"
|
||||
"};\n"
|
||||
"[domain(\"tri\")]\n"
|
||||
"ds_out main(float3 p : SV_DomainLocation, OutputPatch<hs_vtx, 3> ip, hs_patch pc) {\n"
|
||||
" ds_out ov;\n"
|
||||
" ov.pos = ip[0].pos * p.x\n"
|
||||
" + ip[1].pos * p.y\n"
|
||||
" + ip[2].pos * p.z;\n"
|
||||
" ov.color = pc.color;\n"
|
||||
" return ov;\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
const std::string g_pixelShaderCode =
|
||||
"struct vs_out {\n"
|
||||
" float4 pos : SV_POSITION;\n"
|
||||
" float4 color : COLOR;\n"
|
||||
"Texture2D<float4> tex0 : register(t0);"
|
||||
"cbuffer ps_cb : register(b0) {\n"
|
||||
" float4 color;\n"
|
||||
"};\n"
|
||||
"float4 main(vs_out ps_in) : SV_TARGET {\n"
|
||||
" return ps_in.color;\n"
|
||||
"float4 main() : SV_TARGET {\n"
|
||||
" return color * tex0.Load(int3(0, 0, 0));\n"
|
||||
"}\n";
|
||||
|
||||
class TriangleApp {
|
||||
@ -115,235 +62,227 @@ public:
|
||||
|
||||
TriangleApp(HINSTANCE instance, HWND window)
|
||||
: m_window(window) {
|
||||
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory),
|
||||
reinterpret_cast<void**>(&m_factory))))
|
||||
throw DxvkError("Failed to create DXGI factory");
|
||||
|
||||
if (FAILED(m_factory->EnumAdapters(0, &m_adapter)))
|
||||
throw DxvkError("Failed to enumerate DXGI adapter");
|
||||
|
||||
Com<ID3D11Device> device;
|
||||
|
||||
D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_1;
|
||||
|
||||
HRESULT status = D3D11CreateDevice(
|
||||
m_adapter.ptr(),
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr, 0,
|
||||
nullptr, 0,
|
||||
D3D11_SDK_VERSION,
|
||||
&m_device,
|
||||
&m_featureLevel,
|
||||
&m_context);
|
||||
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(status))
|
||||
throw DxvkError("Failed to create D3D11 device");
|
||||
if (FAILED(device->QueryInterface(IID_PPV_ARGS(&m_device)))) {
|
||||
std::cerr << "Failed to query ID3D11DeviceContext1" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Com<IDXGIDevice> 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;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
swapDesc.BufferDesc.Width = m_windowSize.w;
|
||||
swapDesc.BufferDesc.Height = m_windowSize.h;
|
||||
swapDesc.BufferDesc.RefreshRate = { 60, 1 };
|
||||
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapDesc.SampleDesc.Count = 8;
|
||||
swapDesc.SampleDesc.Quality = 0;
|
||||
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapDesc.BufferCount = 2;
|
||||
swapDesc.OutputWindow = window;
|
||||
swapDesc.Windowed = true;
|
||||
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
if (FAILED(m_factory->CreateSwapChain(m_device.ptr(), &swapDesc, &m_swapChain)))
|
||||
throw DxvkError("Failed to create DXGI swap chain");
|
||||
|
||||
if (FAILED(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&m_buffer))))
|
||||
throw DxvkError("Failed to get swap chain back buffer");
|
||||
|
||||
if (FAILED(m_device->CreateRenderTargetView(m_buffer.ptr(), nullptr, &m_bufferView)))
|
||||
throw DxvkError("Failed to create render target view");
|
||||
|
||||
if (FAILED(m_swapChain->ResizeTarget(&swapDesc.BufferDesc)))
|
||||
throw DxvkError("Failed to resize window");
|
||||
|
||||
std::array<Vertex, 21> vertexData = {{
|
||||
{ -0.25f, -0.15f, 0.0f, 1.0f },
|
||||
{ -0.50f, -0.65f, 0.0f, 1.0f },
|
||||
{ -0.75f, -0.15f, 0.0f, 1.0f },
|
||||
{ 0.75f, -0.15f, 0.0f, 1.0f },
|
||||
{ 0.50f, -0.65f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.15f, 0.0f, 1.0f },
|
||||
{ -0.75f, 0.15f, 0.0f, 1.0f },
|
||||
{ -0.50f, 0.65f, 0.0f, 1.0f },
|
||||
{ -0.25f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.25f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.50f, 0.65f, 0.0f, 1.0f },
|
||||
{ 0.75f, 0.15f, 0.0f, 1.0f },
|
||||
{ 0.25f, 0.75f, 0.0f, 1.0f },
|
||||
{ 0.00f, 0.25f, 0.0f, 1.0f },
|
||||
{ -0.25f, 0.75f, 0.0f, 1.0f },
|
||||
{ -0.25f, -0.75f, 0.0f, 1.0f },
|
||||
{ 0.00f, -0.25f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.75f, 0.0f, 1.0f },
|
||||
{ -0.25f, -0.25f, 0.0f, 1.0f },
|
||||
{ 0.00f, 0.25f, 0.0f, 1.0f },
|
||||
{ 0.25f, -0.25f, 0.0f, 1.0f },
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC vertexDesc;
|
||||
vertexDesc.ByteWidth = sizeof(Vertex) * vertexData.size();
|
||||
vertexDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexDesc.CPUAccessFlags = 0;
|
||||
vertexDesc.MiscFlags = 0;
|
||||
vertexDesc.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA vertexDataInfo;
|
||||
vertexDataInfo.pSysMem = vertexData.data();
|
||||
vertexDataInfo.SysMemPitch = 0;
|
||||
vertexDataInfo.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(m_device->CreateBuffer(&vertexDesc, &vertexDataInfo, &m_vertexBuffer)))
|
||||
throw DxvkError("Failed to create vertex buffer");
|
||||
|
||||
std::array<uint32_t, 9> indexData = {{
|
||||
0, 1, 2, 0, 1, 2, 2, 1, 0
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC indexDesc;
|
||||
indexDesc.ByteWidth = sizeof(uint32_t) * indexData.size();
|
||||
indexDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexDesc.CPUAccessFlags = 0;
|
||||
indexDesc.MiscFlags = 0;
|
||||
indexDesc.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA indexDataInfo;
|
||||
indexDataInfo.pSysMem = indexData.data();
|
||||
indexDataInfo.SysMemPitch = 0;
|
||||
indexDataInfo.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(m_device->CreateBuffer(&indexDesc, &indexDataInfo, &m_indexBuffer)))
|
||||
throw DxvkError("Failed to create index buffer");
|
||||
|
||||
std::array<Color, 6> resourceData = {{
|
||||
{ 0x20, 0x20, 0x20, 0xFF },
|
||||
{ 0x20, 0x20, 0x20, 0xFF },
|
||||
{ 0x20, 0x20, 0x20, 0xFF },
|
||||
{ 0xFF, 0xFF, 0x00, 0xFF },
|
||||
{ 0xFF, 0xFF, 0x00, 0xFF },
|
||||
{ 0xFF, 0xFF, 0x00, 0xFF },
|
||||
}};
|
||||
|
||||
D3D11_BUFFER_DESC resourceDesc;
|
||||
resourceDesc.ByteWidth = sizeof(Color) * resourceData.size();
|
||||
resourceDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
resourceDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
resourceDesc.CPUAccessFlags = 0;
|
||||
resourceDesc.MiscFlags = 0;
|
||||
resourceDesc.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA resourceDataInfo;
|
||||
resourceDataInfo.pSysMem = resourceData.data();
|
||||
resourceDataInfo.SysMemPitch = 0;
|
||||
resourceDataInfo.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(m_device->CreateBuffer(&resourceDesc, &resourceDataInfo, &m_resourceBuffer)))
|
||||
throw DxvkError("Failed to create resource buffer");
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
||||
resourceViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
resourceViewDesc.Buffer.FirstElement = 0;
|
||||
resourceViewDesc.Buffer.NumElements = resourceData.size();
|
||||
|
||||
if (FAILED(m_device->CreateShaderResourceView(m_resourceBuffer.ptr(), &resourceViewDesc, &m_resourceView)))
|
||||
throw DxvkError("Failed to create resource buffer view");
|
||||
Com<IDXGISwapChain1> 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<ID3DBlob> vertexShaderBlob;
|
||||
Com<ID3DBlob> hullShaderBlob;
|
||||
Com<ID3DBlob> domainShaderBlob;
|
||||
Com<ID3DBlob> pixelShaderBlob;
|
||||
|
||||
if (FAILED(D3DCompile(
|
||||
g_vertexShaderCode.data(),
|
||||
g_vertexShaderCode.size(),
|
||||
"Vertex shader",
|
||||
nullptr, nullptr,
|
||||
"main", "vs_5_0", 0, 0,
|
||||
&vertexShaderBlob,
|
||||
nullptr)))
|
||||
throw DxvkError("Failed to compile vertex shader");
|
||||
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_hullShaderCode.data(),
|
||||
g_hullShaderCode.size(),
|
||||
"Hull shader",
|
||||
nullptr, nullptr,
|
||||
"main", "hs_5_0", 0, 0,
|
||||
&hullShaderBlob,
|
||||
nullptr)))
|
||||
throw DxvkError("Failed to compile hull shader");
|
||||
|
||||
if (FAILED(D3DCompile(
|
||||
g_domainShaderCode.data(),
|
||||
g_domainShaderCode.size(),
|
||||
"Domain shader",
|
||||
nullptr, nullptr,
|
||||
"main", "ds_5_0", 0, 0,
|
||||
&domainShaderBlob,
|
||||
nullptr)))
|
||||
throw DxvkError("Failed to compile domain shader");
|
||||
|
||||
if (FAILED(D3DCompile(
|
||||
g_pixelShaderCode.data(),
|
||||
g_pixelShaderCode.size(),
|
||||
"Pixel shader",
|
||||
nullptr, nullptr,
|
||||
"main", "ps_5_0", 0, 0,
|
||||
&pixelShaderBlob,
|
||||
nullptr)))
|
||||
throw DxvkError("Failed to compile pixel shader");
|
||||
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_vertexShader)))
|
||||
throw DxvkError("Failed to create vertex shader");
|
||||
|
||||
if (FAILED(m_device->CreateHullShader(
|
||||
hullShaderBlob->GetBufferPointer(),
|
||||
hullShaderBlob->GetBufferSize(),
|
||||
nullptr, &m_hullShader)))
|
||||
throw DxvkError("Failed to create hull shader");
|
||||
|
||||
if (FAILED(m_device->CreateDomainShader(
|
||||
domainShaderBlob->GetBufferPointer(),
|
||||
domainShaderBlob->GetBufferSize(),
|
||||
nullptr, &m_domainShader)))
|
||||
throw DxvkError("Failed to create domain shader");
|
||||
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_pixelShader)))
|
||||
throw DxvkError("Failed to create pixel shader");
|
||||
pixelShaderBlob->GetBufferPointer(),
|
||||
pixelShaderBlob->GetBufferSize(),
|
||||
nullptr, &m_ps))) {
|
||||
std::cerr << "Failed to create pixel shader" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<D3D11_INPUT_ELEMENT_DESC, 1> vertexFormatDesc = {{
|
||||
{ "IN_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, x), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "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)))
|
||||
throw DxvkError("Failed to create input layout");
|
||||
|
||||
D3D11_QUERY_DESC queryDesc;
|
||||
queryDesc.Query = D3D11_QUERY_OCCLUSION;
|
||||
queryDesc.MiscFlags = 0;
|
||||
|
||||
if (FAILED(m_device->CreateQuery(&queryDesc, &m_query)))
|
||||
throw DxvkError("Failed to create occlusion query");
|
||||
vertexFormatDesc.data(),
|
||||
vertexFormatDesc.size(),
|
||||
vertexShaderBlob->GetBufferPointer(),
|
||||
vertexShaderBlob->GetBufferSize(),
|
||||
&m_vertexFormat))) {
|
||||
std::cerr << "Failed to create input layout" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<Vertex, 6> 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<uint32_t, 6> 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<uint32_t, 2> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -352,141 +291,266 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void run() {
|
||||
this->adjustBackBuffer();
|
||||
|
||||
D3D11_VIEWPORT viewport;
|
||||
viewport.TopLeftX = 0.0f;
|
||||
viewport.TopLeftY = 0.0f;
|
||||
viewport.Width = static_cast<float>(m_windowSize.w);
|
||||
viewport.Height = static_cast<float>(m_windowSize.h);
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
m_context->RSSetViewports(1, &viewport);
|
||||
|
||||
FLOAT color[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
m_context->OMSetRenderTargets(1, &m_bufferView, nullptr);
|
||||
m_context->ClearRenderTargetView(m_bufferView.ptr(), color);
|
||||
|
||||
m_context->VSSetShader(m_vertexShader.ptr(), nullptr, 0);
|
||||
m_context->HSSetShader(m_hullShader.ptr(), nullptr, 0);
|
||||
m_context->DSSetShader(m_domainShader.ptr(), nullptr, 0);
|
||||
m_context->PSSetShader(m_pixelShader.ptr(), nullptr, 0);
|
||||
|
||||
m_context->VSSetShaderResources(0, 1, &m_resourceView);
|
||||
|
||||
UINT vsStride = sizeof(Vertex);
|
||||
UINT vsOffset = 0;
|
||||
|
||||
// Test normal draws with base vertex
|
||||
m_context->Begin(m_query.ptr());
|
||||
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);
|
||||
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->Draw(3, 0);
|
||||
m_context->Draw(3, 3);
|
||||
m_context->End(m_query.ptr());
|
||||
|
||||
// Test instanced draws with base instance and base vertex
|
||||
vsOffset = 6 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->DrawInstanced(3, 1, 0, 1);
|
||||
m_context->DrawInstanced(3, 1, 3, 1);
|
||||
|
||||
// Test indexed draws with base vertex and base index
|
||||
vsOffset = 12 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->IASetIndexBuffer(m_indexBuffer.ptr(), DXGI_FORMAT_R32_UINT, 0);
|
||||
m_context->DrawIndexed(3, 0, 0);
|
||||
m_context->DrawIndexed(3, 3, 3);
|
||||
|
||||
// Test default backface culling
|
||||
vsOffset = 18 * sizeof(Vertex);
|
||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||
m_context->DrawIndexed(3, 6, 0);
|
||||
|
||||
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
|
||||
m_swapChain->Present(1, 0);
|
||||
|
||||
// Test query results
|
||||
while (true) {
|
||||
UINT64 samplesPassed = 0;
|
||||
|
||||
UINT queryStatus = m_context->GetData(
|
||||
m_query.ptr(), &samplesPassed, sizeof(samplesPassed),
|
||||
D3D11_ASYNC_GETDATA_DONOTFLUSH);
|
||||
|
||||
if (queryStatus == S_OK) {
|
||||
if (samplesPassed == 0)
|
||||
std::cerr << "Occlusion query returned 0 samples" << std::endl;
|
||||
break;
|
||||
} else if (queryStatus == S_FALSE) {
|
||||
std::this_thread::yield();
|
||||
} else {
|
||||
std::cerr << "Occlusion query failed" << std::endl;
|
||||
break;
|
||||
bool run() {
|
||||
if (!m_initialized)
|
||||
return false;
|
||||
|
||||
if (m_occluded && (m_occluded = isOccluded()))
|
||||
return true;
|
||||
|
||||
if (!beginFrame())
|
||||
return true;
|
||||
|
||||
std::array<PsConstants, 2> 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<VsConstantsPad*>(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<VsConstantsPad*>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void adjustBackBuffer() {
|
||||
|
||||
|
||||
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);
|
||||
|
||||
Extent2D newWindowSize = {
|
||||
static_cast<uint32_t>(windowRect.right - windowRect.left),
|
||||
static_cast<uint32_t>(windowRect.bottom - windowRect.top),
|
||||
};
|
||||
uint32_t newWindowSizeW = uint32_t(windowRect.right - windowRect.left);
|
||||
uint32_t newWindowSizeH = uint32_t(windowRect.bottom - windowRect.top);
|
||||
|
||||
if (m_windowSize.w != newWindowSize.w
|
||||
|| m_windowSize.h != newWindowSize.h) {
|
||||
m_buffer = nullptr;
|
||||
m_bufferView = nullptr;
|
||||
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;
|
||||
}
|
||||
|
||||
if (FAILED(m_swapChain->ResizeBuffers(0,
|
||||
newWindowSize.w, newWindowSize.h, DXGI_FORMAT_UNKNOWN, 0)))
|
||||
throw DxvkError("Failed to resize back buffers");
|
||||
Com<ID3D11Texture2D> backBuffer;
|
||||
if (FAILED(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)))) {
|
||||
std::cerr << "Failed to get swap chain back buffer" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&m_buffer))))
|
||||
throw DxvkError("Failed to get swap chain back buffer");
|
||||
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(m_buffer.ptr(), nullptr, &m_bufferView)))
|
||||
throw DxvkError("Failed to create render target view");
|
||||
m_windowSize = newWindowSize;
|
||||
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;
|
||||
Extent2D m_windowSize = { 1024, 600 };
|
||||
uint32_t m_windowSizeW = 1024;
|
||||
uint32_t m_windowSizeH = 600;
|
||||
bool m_initialized = false;
|
||||
bool m_occluded = false;
|
||||
|
||||
Com<IDXGIFactory> m_factory;
|
||||
Com<IDXGIFactory3> m_factory;
|
||||
Com<IDXGIAdapter> m_adapter;
|
||||
Com<ID3D11Device> m_device;
|
||||
Com<ID3D11DeviceContext> m_context;
|
||||
Com<IDXGISwapChain> m_swapChain;
|
||||
|
||||
Com<ID3D11Texture2D> m_buffer;
|
||||
Com<ID3D11RenderTargetView> m_bufferView;
|
||||
Com<ID3D11Buffer> m_resourceBuffer;
|
||||
Com<ID3D11ShaderResourceView> m_resourceView;
|
||||
Com<ID3D11Buffer> m_indexBuffer;
|
||||
Com<ID3D11Buffer> m_vertexBuffer;
|
||||
Com<ID3D11Device1> m_device;
|
||||
Com<ID3D11DeviceContext1> m_context;
|
||||
Com<IDXGISwapChain2> m_swapChain;
|
||||
|
||||
Com<ID3D11RenderTargetView> m_rtv;
|
||||
Com<ID3D11Buffer> m_ibo;
|
||||
Com<ID3D11Buffer> m_vbo;
|
||||
Com<ID3D11InputLayout> m_vertexFormat;
|
||||
|
||||
Com<ID3D11Texture2D> m_tex0;
|
||||
Com<ID3D11Texture2D> m_tex1;
|
||||
Com<ID3D11ShaderResourceView> m_srv0;
|
||||
Com<ID3D11ShaderResourceView> m_srv1;
|
||||
|
||||
Com<ID3D11VertexShader> m_vertexShader;
|
||||
Com<ID3D11HullShader> m_hullShader;
|
||||
Com<ID3D11DomainShader> m_domainShader;
|
||||
Com<ID3D11PixelShader> m_pixelShader;
|
||||
|
||||
Com<ID3D11Query> m_query;
|
||||
|
||||
D3D_FEATURE_LEVEL m_featureLevel;
|
||||
|
||||
uint32_t m_frameId = 0;
|
||||
Com<ID3D11Buffer> m_cbPs;
|
||||
Com<ID3D11Buffer> m_cbVs;
|
||||
|
||||
Com<ID3D11VertexShader> m_vs;
|
||||
Com<ID3D11PixelShader> m_ps;
|
||||
|
||||
LARGE_INTEGER m_qpcLastUpdate = { };
|
||||
LARGE_INTEGER m_qpcFrequency = { };
|
||||
|
||||
uint32_t m_frameCount = 0;
|
||||
|
||||
};
|
||||
|
||||
@ -495,69 +559,48 @@ LRESULT CALLBACK WindowProc(HWND hWnd,
|
||||
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);
|
||||
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"WindowClass1";
|
||||
wc.hbrBackground = HBRUSH(COLOR_WINDOW);
|
||||
wc.lpszClassName = L"WindowClass";
|
||||
RegisterClassExW(&wc);
|
||||
|
||||
hWnd = CreateWindowExW(0,
|
||||
L"WindowClass1",
|
||||
L"Our First Windowed Program",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
300, 300,
|
||||
640, 480,
|
||||
nullptr,
|
||||
nullptr,
|
||||
hInstance,
|
||||
nullptr);
|
||||
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;
|
||||
|
||||
try {
|
||||
TriangleApp app(hInstance, hWnd);
|
||||
|
||||
while (true) {
|
||||
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
if (msg.message == WM_QUIT)
|
||||
return msg.wParam;
|
||||
} else {
|
||||
app.run();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
} catch (const dxvk::DxvkError& e) {
|
||||
std::cerr << e.message() << std::endl;
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
if (m_report) {
|
||||
std::cout << "hwnd: " << hWnd << std::endl;
|
||||
std::cout << "msg: " << message << std::endl;
|
||||
std::cout << "wp: " << wParam << std::endl;
|
||||
std::cout << "lp: " << lParam << std::endl;
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user