Adds documentation and tests for min/max intrinsics. (#81)
Improves xml-based tests to allow existing devices to be used. Improves dxexp to print out SM6/wave/i64 support under experimental mode. Bumps the hctversion to 0.7
This commit is contained in:
Родитель
98f201b5fd
Коммит
7bdef32133
|
@ -19,6 +19,31 @@
|
|||
]]>
|
||||
</Shader>
|
||||
</ShaderOp>
|
||||
<ShaderOp Name="MinMax" CS="CS" DispatchX="10" DispatchY="10">
|
||||
<RootSignature>RootFlags(0), UAV(u0)</RootSignature>
|
||||
<Resource Name="SPrimitives" Dimension="BUFFER" Width="1024" Flags="ALLOW_UNORDERED_ACCESS" InitialResourceState="COPY_DEST" TransitionTo="UNORDERED_ACCESS" Init="ByName" ReadBack="true" />
|
||||
<RootValues>
|
||||
<RootValue Index="0" ResName="SPrimitives" />
|
||||
</RootValues>
|
||||
<Shader Name="CS" Target="cs_6_0">
|
||||
<![CDATA[
|
||||
struct SMinMaxElem {
|
||||
float f_fa;
|
||||
float f_fb;
|
||||
float f_fmin_o;
|
||||
float f_fmax_o;
|
||||
};
|
||||
RWStructuredBuffer<SMinMaxElem> g_buf : register(u0);
|
||||
[numthreads(10,10,1)]
|
||||
void main(uint GI : SV_GroupIndex) {
|
||||
SMinMaxElem l = g_buf[GI];
|
||||
l.f_fmin_o = min(l.f_fa, l.f_fb);
|
||||
l.f_fmax_o = max(l.f_fa, l.f_fb);
|
||||
g_buf[GI] = l;
|
||||
};
|
||||
]]>
|
||||
</Shader>
|
||||
</ShaderOp>
|
||||
<ShaderOp Name="OOB" PS="PS" VS="VS">
|
||||
<RootSignature>RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), CBV(b0), DescriptorTable(SRV(t0,numDescriptors=2))</RootSignature>
|
||||
<Resource Name="CB0" Dimension="BUFFER" InitialResourceState="COPY_DEST" Init="FromBytes" TransitionTo="VERTEX_AND_CONSTANT_BUFFER">
|
||||
|
|
|
@ -194,6 +194,7 @@ public:
|
|||
TEST_METHOD(BasicComputeTest);
|
||||
TEST_METHOD(BasicTriangleTest);
|
||||
TEST_METHOD(BasicTriangleOpTest);
|
||||
TEST_METHOD(MinMaxTest);
|
||||
TEST_METHOD(OutOfBoundsTest);
|
||||
TEST_METHOD(SaturateTest);
|
||||
TEST_METHOD(SignTest);
|
||||
|
@ -617,6 +618,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ReadHlslDataIntoNewStream(LPCWSTR relativePath, IStream **ppStream) {
|
||||
VERIFY_SUCCEEDED(m_support.Initialize());
|
||||
CComPtr<IDxcLibrary> pLibrary;
|
||||
CComPtr<IDxcBlobEncoding> pBlob;
|
||||
CComPtr<IStream> pStream;
|
||||
std::wstring path = GetPathToHlslDataFile(relativePath);
|
||||
VERIFY_SUCCEEDED(m_support.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(path.c_str(), nullptr, &pBlob));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateStreamFromBlobReadOnly(pBlob, &pStream));
|
||||
*ppStream = pStream.Detach();
|
||||
}
|
||||
|
||||
void RecordRenderAndReadback(ID3D12GraphicsCommandList *pList,
|
||||
ID3D12DescriptorHeap *pRtvHeap,
|
||||
UINT rtvDescriptorSize,
|
||||
|
@ -825,9 +838,9 @@ TEST_F(ExecutionTest, BasicComputeTest) {
|
|||
static const int DispatchGroupCount = 1;
|
||||
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::vector<uint32_t> values;
|
||||
SetupComputeValuePattern(values, ThreadsPerGroup * DispatchGroupCount);
|
||||
VERIFY_ARE_EQUAL(values[0], 0);
|
||||
|
@ -1016,9 +1029,9 @@ TEST_F(ExecutionTest, Int64Test) {
|
|||
static const int DispatchGroupCount = 1;
|
||||
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
if (!DoesDeviceSupportInt64(pDevice)) {
|
||||
// Optional feature, so it's correct to not support it if declared as such.
|
||||
WEX::Logging::Log::Comment(L"Device does not support int64 operations.");
|
||||
|
@ -1047,9 +1060,9 @@ TEST_F(ExecutionTest, SignTest) {
|
|||
static const int DispatchGroupCount = 1;
|
||||
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::vector<uint32_t> values = { (uint32_t)-3, (uint32_t)-2, (uint32_t)-1, 0, 1, 2, 3, 4};
|
||||
RunRWByteBufferComputeTest(pDevice, pShader, values);
|
||||
VERIFY_ARE_EQUAL(values[0], -1);
|
||||
|
@ -1159,9 +1172,9 @@ TEST_F(ExecutionTest, WaveIntrinsicsTest) {
|
|||
static const int DispatchGroupCount = 1;
|
||||
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
if (!DoesDeviceSupportWaveOps(pDevice)) {
|
||||
// Optional feature, so it's correct to not support it if declared as such.
|
||||
WEX::Logging::Log::Comment(L"Device does not support wave operations.");
|
||||
|
@ -1809,7 +1822,8 @@ static float g_SinCosFloats[] = {
|
|||
};
|
||||
|
||||
std::shared_ptr<ShaderOpTestResult>
|
||||
RunShaderOpTest(dxc::DxcDllSupport &support, IStream *pStream, LPCSTR pName,
|
||||
RunShaderOpTest(ID3D12Device *pDevice, dxc::DxcDllSupport &support,
|
||||
IStream *pStream, LPCSTR pName,
|
||||
st::ShaderOpTest::TInitCallbackFn pInitCallback) {
|
||||
DXASSERT_NOMSG(pStream != nullptr);
|
||||
std::shared_ptr<st::ShaderOpSet> ShaderOpSet =
|
||||
|
@ -1860,18 +1874,15 @@ static bool isdenorm(double d) {
|
|||
|
||||
TEST_F(ExecutionTest, DoShaderOpArithTest) {
|
||||
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
|
||||
VERIFY_SUCCEEDED(m_support.Initialize());
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcLibrary> pLibrary;
|
||||
CComPtr<IDxcBlobEncoding> pBlob;
|
||||
CComPtr<IStream> pStream;
|
||||
std::wstring path = GetPathToHlslDataFile(L"ShaderOpArith.xml");
|
||||
VERIFY_SUCCEEDED(m_support.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(path.c_str(), nullptr, &pBlob));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateStreamFromBlobReadOnly(pBlob, &pStream));
|
||||
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
|
||||
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
// Single operation test at the moment.
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(m_support, pStream, "SinCos",
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "SinCos",
|
||||
[](LPCSTR Name, std::vector<BYTE> &Data) {
|
||||
// Initialize the SPrimitives buffer.
|
||||
VERIFY_IS_TRUE(0 == _stricmp(Name, "SPrimitives"));
|
||||
|
@ -1933,20 +1944,111 @@ TEST_F(ExecutionTest, DoShaderOpArithTest) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(ExecutionTest, OutOfBoundsTest) {
|
||||
static float ifdenorm_flushf(float a) {
|
||||
return isdenorm(a) ? copysign(0.0f, a) : a;
|
||||
}
|
||||
|
||||
static bool ifdenorm_flushf_eq(float a, float b) {
|
||||
return ifdenorm_flushf(a) == ifdenorm_flushf(b);
|
||||
}
|
||||
|
||||
static bool ifdenorm_flushf_eq_or_nans(float a, float b) {
|
||||
if (isnan(a) && isnan(b)) return true;
|
||||
return ifdenorm_flushf(a) == ifdenorm_flushf(b);
|
||||
}
|
||||
|
||||
TEST_F(ExecutionTest, MinMaxTest) {
|
||||
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
|
||||
VERIFY_SUCCEEDED(m_support.Initialize());
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcLibrary> pLibrary;
|
||||
CComPtr<IDxcBlobEncoding> pBlob;
|
||||
CComPtr<IStream> pStream;
|
||||
std::wstring path = GetPathToHlslDataFile(L"ShaderOpArith.xml");
|
||||
VERIFY_SUCCEEDED(m_support.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(path.c_str(), nullptr, &pBlob));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateStreamFromBlobReadOnly(pBlob, &pStream));
|
||||
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
|
||||
|
||||
struct SMinMaxElem {
|
||||
float f_fa;
|
||||
float f_fb;
|
||||
float f_fmin_o;
|
||||
float f_fmax_o;
|
||||
};
|
||||
float TestValues[] = {
|
||||
-(INFINITY),
|
||||
-1.0f,
|
||||
-(FLT_MIN/2),
|
||||
-0.0f,
|
||||
0.0f,
|
||||
FLT_MIN / 2,
|
||||
1.0f,
|
||||
INFINITY,
|
||||
NAN
|
||||
};
|
||||
|
||||
// Single operation test at the moment.
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(m_support, pStream, "OOB", nullptr);
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "MinMax",
|
||||
[&TestValues](LPCSTR Name, std::vector<BYTE> &Data) {
|
||||
// Initialize the SPrimitives buffer.
|
||||
VERIFY_IS_TRUE(0 == _stricmp(Name, "SPrimitives"));
|
||||
size_t count = 10 * 10;
|
||||
size_t size = sizeof(SMinMaxElem) * count;
|
||||
Data.resize(size);
|
||||
SMinMaxElem *pElems = (SMinMaxElem *)Data.data();
|
||||
for (size_t a = 0; a < 10; ++a) {
|
||||
float fa = TestValues[a % _countof(TestValues)];
|
||||
for (size_t b = 0; b < 10; ++b) {
|
||||
SMinMaxElem *p = &pElems[a * 10 + b];
|
||||
ZeroMemory(p, sizeof(*p));
|
||||
p->f_fa = fa;
|
||||
p->f_fb = TestValues[b % _countof(TestValues)];
|
||||
}
|
||||
}
|
||||
});
|
||||
MappedData data;
|
||||
test->Test->GetReadBackData("SPrimitives", &data);
|
||||
// data.dump(); // Uncomment to dump raw bytes from buffer.
|
||||
|
||||
unsigned count = 10 * 10;
|
||||
SMinMaxElem *pPrimitives = (SMinMaxElem *)data.data();
|
||||
WEX::TestExecution::DisableVerifyExceptions dve;
|
||||
static const float Error = 0.0008f;
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
SMinMaxElem *p = &pPrimitives[i];
|
||||
float fa = p->f_fa;
|
||||
float fb = p->f_fb;
|
||||
float fmin = p->f_fmin_o;
|
||||
float fmax = p->f_fmax_o;
|
||||
LogCommentFmt(L"Element #%u, a %f, b %f, min=%f, max=%f", i, fa, fb, fmin, fmax);
|
||||
if (isnan(fa)) {
|
||||
VERIFY_IS_TRUE(ifdenorm_flushf_eq_or_nans(fmin, fb));
|
||||
VERIFY_IS_TRUE(ifdenorm_flushf_eq_or_nans(fmax, fb));
|
||||
}
|
||||
else if (isnan(fb)) {
|
||||
VERIFY_IS_TRUE(ifdenorm_flushf_eq_or_nans(fmin, fa));
|
||||
VERIFY_IS_TRUE(ifdenorm_flushf_eq_or_nans(fmax, fa));
|
||||
}
|
||||
else {
|
||||
// Flushing is allowed - check both cases.
|
||||
float fmax_0 = fa >= fb ? fa : fb;
|
||||
float fmax_1 = ifdenorm_flushf(fmax_0);
|
||||
VERIFY_IS_TRUE(fmax == fmax_0 || fmax == fmax_1);
|
||||
float fmin_0 = fa < fb ? fa : fb;
|
||||
float fmin_1 = ifdenorm_flushf(fmin_0);
|
||||
VERIFY_IS_TRUE(fmin == fmin_0 || fmin == fmin_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ExecutionTest, OutOfBoundsTest) {
|
||||
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
|
||||
CComPtr<IStream> pStream;
|
||||
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
|
||||
|
||||
// Single operation test at the moment.
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "OOB", nullptr);
|
||||
MappedData data;
|
||||
// Read back to CPU and examine contents - should get pure red.
|
||||
{
|
||||
|
@ -1960,18 +2062,15 @@ TEST_F(ExecutionTest, OutOfBoundsTest) {
|
|||
|
||||
TEST_F(ExecutionTest, SaturateTest) {
|
||||
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
|
||||
VERIFY_SUCCEEDED(m_support.Initialize());
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcLibrary> pLibrary;
|
||||
CComPtr<IDxcBlobEncoding> pBlob;
|
||||
CComPtr<IStream> pStream;
|
||||
std::wstring path = GetPathToHlslDataFile(L"ShaderOpArith.xml");
|
||||
VERIFY_SUCCEEDED(m_support.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(path.c_str(), nullptr, &pBlob));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateStreamFromBlobReadOnly(pBlob, &pStream));
|
||||
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
|
||||
|
||||
// Single operation test at the moment.
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(m_support, pStream, "Saturate", nullptr);
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "Saturate", nullptr);
|
||||
MappedData data;
|
||||
test->Test->GetReadBackData("U0", &data);
|
||||
const float *pValues = (float *)data.data();
|
||||
|
@ -1989,18 +2088,15 @@ TEST_F(ExecutionTest, SaturateTest) {
|
|||
|
||||
TEST_F(ExecutionTest, BasicTriangleOpTest) {
|
||||
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
|
||||
VERIFY_SUCCEEDED(m_support.Initialize());
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcLibrary> pLibrary;
|
||||
CComPtr<IDxcBlobEncoding> pBlob;
|
||||
CComPtr<IStream> pStream;
|
||||
std::wstring path = GetPathToHlslDataFile(L"ShaderOpArith.xml");
|
||||
VERIFY_SUCCEEDED(m_support.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(path.c_str(), nullptr, &pBlob));
|
||||
VERIFY_SUCCEEDED(pLibrary->CreateStreamFromBlobReadOnly(pBlob, &pStream));
|
||||
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
|
||||
|
||||
// Single operation test at the moment.
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(m_support, pStream, "Triangle", nullptr);
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
if (!CreateDevice(&pDevice))
|
||||
return;
|
||||
|
||||
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "Triangle", nullptr);
|
||||
MappedData data;
|
||||
D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc;
|
||||
UINT width = (UINT64)D.Width;
|
||||
|
|
|
@ -931,6 +931,10 @@ void ShaderOpTest::SetRootValues(ID3D12GraphicsCommandList *pList,
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderOpTest::SetDevice(ID3D12Device *pDevice) {
|
||||
m_pDevice = pDevice;
|
||||
}
|
||||
|
||||
void ShaderOpTest::SetDxcSupport(dxc::DxcDllSupport *pDxcSupport) {
|
||||
m_pDxcSupport = pDxcSupport;
|
||||
}
|
||||
|
@ -942,7 +946,7 @@ void ShaderOpTest::SetInitCallback(TInitCallbackFn InitCallbackFn) {
|
|||
void ShaderOpTest::SetupRenderTarget(ShaderOp *pShaderOp, ID3D12Device *pDevice,
|
||||
ID3D12CommandQueue *pCommandQueue,
|
||||
ID3D12Resource *pRenderTarget) {
|
||||
m_pDevice = pDevice;
|
||||
SetDevice(pDevice);
|
||||
m_CommandList.Queue = pCommandQueue;
|
||||
// Simplification - add the render target name if missing, set it up 'by hand' if not.
|
||||
if (pShaderOp->RenderTargets.empty()) {
|
||||
|
|
|
@ -235,6 +235,7 @@ public:
|
|||
void GetReadBackData(LPCSTR pResourceName, MappedData *pData);
|
||||
void RunShaderOp(ShaderOp *pShaderOp);
|
||||
void RunShaderOp(std::shared_ptr<ShaderOp> pShaderOp);
|
||||
void SetDevice(ID3D12Device* pDevice);
|
||||
void SetDxcSupport(dxc::DxcDllSupport *pDxcSupport);
|
||||
void SetInitCallback(TInitCallbackFn InitCallbackFn);
|
||||
void SetupRenderTarget(ShaderOp *pShaderOp, ID3D12Device *pDevice,
|
||||
|
|
|
@ -14,8 +14,15 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <d3d12.h>
|
||||
#include <atlbase.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#pragma comment(lib, "d3d12.lib")
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
|
||||
// A more recent Windows SDK than currently required is needed for these.
|
||||
typedef HRESULT (WINAPI *D3D12EnableExperimentalFeaturesFn)(
|
||||
UINT NumFeatures,
|
||||
|
@ -30,6 +37,49 @@ static const GUID D3D12ExperimentalShaderModelsID = { /* 76f5573e-f13a-40f5-b297
|
|||
{ 0xb2, 0x97, 0x81, 0xce, 0x9e, 0x18, 0x93, 0x3f }
|
||||
};
|
||||
|
||||
static HRESULT AtlCheck(HRESULT hr) {
|
||||
if (FAILED(hr))
|
||||
AtlThrow(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static char *BoolToStr(bool value) {
|
||||
return value ? "YES" : "NO";
|
||||
}
|
||||
|
||||
static void PrintAdapters() {
|
||||
try {
|
||||
CComPtr<IDXGIFactory2> pFactory;
|
||||
AtlCheck(CreateDXGIFactory2(0, IID_PPV_ARGS(&pFactory)));
|
||||
UINT AdapterIndex = 0;
|
||||
for (;;) {
|
||||
CComPtr<IDXGIAdapter1> pAdapter;
|
||||
CComPtr<ID3D12Device> pDevice;
|
||||
HRESULT hrEnum = pFactory->EnumAdapters1(AdapterIndex, &pAdapter);
|
||||
if (hrEnum == DXGI_ERROR_NOT_FOUND)
|
||||
break;
|
||||
AtlCheck(hrEnum);
|
||||
DXGI_ADAPTER_DESC1 AdapterDesc;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS1 DeviceOptions;
|
||||
D3D12_FEATURE_DATA_SHADER_MODEL DeviceSM;
|
||||
AtlCheck(pAdapter->GetDesc1(&AdapterDesc));
|
||||
AtlCheck(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&pDevice)));
|
||||
AtlCheck(pDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1, &DeviceOptions, sizeof(DeviceOptions)));
|
||||
DeviceSM.HighestShaderModel = D3D_SHADER_MODEL_6_0;
|
||||
AtlCheck(pDevice->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &DeviceSM, sizeof(DeviceSM)));
|
||||
printf("%S - SM6 [%s] Wave [%s] I64 [%s]\n", AdapterDesc.Description,
|
||||
BoolToStr(DeviceSM.HighestShaderModel >= D3D_SHADER_MODEL_6_0),
|
||||
BoolToStr(DeviceOptions.WaveOps),
|
||||
BoolToStr(DeviceOptions.Int64ShaderOps));
|
||||
AdapterIndex++;
|
||||
}
|
||||
}
|
||||
catch (ATL::CAtlException &) {
|
||||
printf("%s", "Unable to print information for adapters.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return codes:
|
||||
// 0 - experimental mode worked
|
||||
// 1 - cannot load d3d12.dll
|
||||
|
@ -74,6 +124,7 @@ int main(int argc, const char *argv[]) {
|
|||
HRESULT hr = pD3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModelsID, nullptr, nullptr);
|
||||
if (SUCCEEDED(hr)) {
|
||||
printf("Experimental shader model feature succeeded.\n");
|
||||
PrintAdapters();
|
||||
return 0;
|
||||
}
|
||||
else if (hr == E_NOINTERFACE) {
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
# further remarks
|
||||
#
|
||||
# Keep these ordered alphabetically for ease of maintenance.
|
||||
#
|
||||
# Dump instructions with no extra documentation with this snippet.
|
||||
# import hctdb
|
||||
# h = hctdb.db_dxil()
|
||||
# for i in [item.name for item in h.instr if item.is_dxil_op and not item.remarks]: print(i)
|
||||
|
||||
* Inst: Cos - returns cosine(theta) for theta in radians.
|
||||
|
||||
|
@ -25,6 +30,52 @@ The maximum absolute error is 0.0008 in the interval from -100*Pi to +100*Pi.
|
|||
The FAbs instruction takes simply forces the sign of the number(s) on the source operand positive, including on INF values.
|
||||
Applying FAbs on NaN preserves NaN, although the particular NaN bit pattern that results is not defined.
|
||||
|
||||
* Inst: FMax - returns a if a >= b, else b
|
||||
|
||||
>= is used instead of > so that if min(x,y) = x then max(x,y) = y.
|
||||
|
||||
NaN has special handling: If one source operand is NaN, then the other source operand is returned.
|
||||
If both are NaN, any NaN representation is returned.
|
||||
This conforms to new IEEE 754R rules.
|
||||
|
||||
Denorms are flushed (sign preserved) before comparison, however the result written to dest may or may not be denorm flushed.
|
||||
|
||||
+------+-----------------------------+
|
||||
| a | b |
|
||||
| +------+--------+------+------+
|
||||
| | -inf | F | +inf | NaN |
|
||||
------+------+--------+------+------+
|
||||
| -inf | -inf | b | +inf | -inf |
|
||||
+------+------+--------+------+------+
|
||||
| F | a | a or b | +inf | a |
|
||||
+------+------+--------+------+------+
|
||||
| +inf | +inf | +inf | +inf | +inf |
|
||||
+------+------+--------+------+------+
|
||||
| NaN | -inf | b | +inf | NaN |
|
||||
+------+------+--------+------+------+
|
||||
|
||||
* Inst: FMin - returns a if a < b, else b
|
||||
|
||||
NaN has special handling: If one source operand is NaN, then the other source operand is returned.
|
||||
If both are NaN, any NaN representation is returned.
|
||||
This conforms to new IEEE 754R rules.
|
||||
|
||||
Denorms are flushed (sign preserved) before comparison, however the result written to dest may or may not be denorm flushed.
|
||||
|
||||
+------+-----------------------------+
|
||||
| a | b |
|
||||
| +------+--------+------+------+
|
||||
| | -inf | F | +inf | NaN |
|
||||
+------+------+--------+------+------+
|
||||
| -inf | -inf | -inf | -inf | -inf |
|
||||
+------+------+--------+------+------+
|
||||
| F | -inf | a or b | a | a |
|
||||
+------+------+--------+------+------+
|
||||
| +inf | -inf | b | +inf | +inf |
|
||||
+------+------+--------+------+------+
|
||||
| NaN | -inf | b | +inf | NaN |
|
||||
+------+------+--------+------+------+
|
||||
|
||||
* Inst: Saturate - clamps the result of a single or double precision floating point value to [0.0f...1.0f]
|
||||
|
||||
The Saturate instruction performs the following operation on its input value:
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.1
|
||||
0.7
|
Загрузка…
Ссылка в новой задаче