1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // Objects.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #include "CompilationResult.h"
- #include "HLSLTestData.h"
- #include <stdint.h>
- #include "WexTestClass.h"
- #include "HlslTestUtils.h"
- #include <exception>
- #include <set>
- ///////////////////////////////////////////////////////////////////////////////
- // Utilities.
- namespace std {
- /// Returns the first element of the container.
- template <class Container>
- auto first(Container& cont) -> decltype (*begin(cont))
- {
- auto iter = begin(cont);
- return *iter;
- }
- /// Returns the first element of the container or the default value if empty.
- template <typename Container, typename ElementType>
- ElementType first_or_default(
- Container& cont,
- const ElementType& defaultValue
- )
- {
- auto iter = begin(cont);
- auto endIter = end(cont);
- if (iter == endIter) return defaultValue;
- return *iter;
- }
- }
- template <typename TEnumeration>
- class EnumFlagsIterator : public std::iterator<std::input_iterator_tag, TEnumeration>
- {
- private:
- unsigned long _value;
- public:
- EnumFlagsIterator(TEnumeration value) : _value(value) { }
- TEnumeration operator*() const
- {
- unsigned long l;
- _BitScanForward(&l, _value);
- return static_cast<TEnumeration>(1 << l);
- }
- EnumFlagsIterator<TEnumeration>& operator++()
- {
- unsigned long l;
- _BitScanForward(&l, _value);
- _value = _value & ~(1 << l);
- return *this;
- }
- bool equal(const EnumFlagsIterator<TEnumeration>& other)
- {
- return _value == other._value;
- }
- bool operator==(const EnumFlagsIterator<TEnumeration>& other)
- {
- return _value == other._value;
- }
- bool operator!=(const EnumFlagsIterator<TEnumeration>& other)
- {
- return _value != other._value;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Shader model test data.
- enum ShaderModel
- {
- ShaderModel4 = 4,
- ShaderModel5 = 5
- };
- enum ShaderType
- {
- /// Vertex shader.
- ST_Vertex = 1 << 0,
- /// Hull shader.
- ST_Hull = 1 << 1,
- /// Domain shader.
- ST_Domain = 1 << 2,
- /// Geometry shader type.
- ST_Geometry = 1 << 3,
- /// Pixel shader type.
- ST_Pixel = 1 << 4,
- /// Compute shader type.
- ST_Compute = 1 << 5,
- /// Hull and geometry shader types.
- ST_HullGeometry = ST_Hull | ST_Geometry,
- /// Hull and domain shader types.
- ST_HullDomain = ST_Hull | ST_Domain,
- /// Pixel and compute shader types.
- ST_PixelCompute = ST_Pixel | ST_Compute,
- /// All shader types.
- ST_All = ST_Vertex | ST_Hull | ST_Domain | ST_Geometry | ST_Pixel | ST_Compute
- };
- static
- const char* GetShaderTypeName(ShaderType value)
- {
- switch (value) {
- case ST_Vertex: return "Vertex shader";
- case ST_Hull: return "Hull shader";
- case ST_Domain: return "Domain shader";
- case ST_Geometry: return "Geometry shader";
- case ST_Pixel: return "Pixel shader";
- case ST_Compute: return "Compute shader";
- default: return "(unknown)";
- }
- }
- typedef EnumFlagsIterator<ShaderType> ShaderTypeIterator;
- ShaderTypeIterator begin(ShaderType value) { return ShaderTypeIterator(value); }
- ShaderTypeIterator end(ShaderType value) { return ShaderTypeIterator((ShaderType)0); }
- /// Enumerates types of shader objects like textures or buffers.
- enum ShaderObjectKind
- {
- /// Output buffer that appears as a stream the shader may append to.
- SOK_AppendStructuredBuffer,
- ///
- SOK_Buffer,
- SOK_ByteAddressBuffer,
- /// An input buffer that appears as a stream the shader may pull values from.
- SOK_ConsumeStructuredBuffer,
- /// Represents an array of control points that are available to the hull shader as inputs.
- SOK_InputPatch,
- /// Represents an array of output control points that are available to the hull shader's patch-constant function as well as the domain shader.
- SOK_OutputPatch,
- /// A read/write buffer.
- SOK_RWBuffer,
- /// A read/write buffer that indexes in bytes.
- SOK_RWByteAddressBuffer,
- /// A read/write buffer that can take a T type that is a structure.
- SOK_RWStructuredBuffer,
- /// A read/write resource.
- SOK_RWTexture1D,
- /// A read/write resource.
- SOK_RWTexture1DArray,
- /// A read/write resource.
- SOK_RWTexture2D,
- /// A read/write resource.
- SOK_RWTexture2DArray,
- /// A read/write resource.
- SOK_RWTexture3D,
- /// A stream-output object is a templated object that streams data out of the geometry-shader stage.
- SOK_StreamOutputLine,
- /// A stream-output object is a templated object that streams data out of the geometry-shader stage.
- SOK_StreamOutputPoint,
- /// A stream-output object is a templated object that streams data out of the geometry-shader stage.
- SOK_StreamOutputTriangle,
- /// A read-only buffer, which can take a T type that is a structure.
- SOK_StructuredBuffer,
- /// A read-only resource.
- SOK_Texture1D,
- /// A read-only resource.
- SOK_Texture1DArray,
- /// A read-only resource.
- SOK_Texture2D,
- /// A read-only resource.
- SOK_Texture2DArray,
- /// A read-only resource.
- SOK_Texture2DMS,
- /// A read-only resource.
- SOK_Texture2DArrayMS,
- /// A read-only resource.
- SOK_Texture3D,
- /// A read-only resource.
- SOK_TextureCube,
- /// A read-only resource.
- SOK_TextureCubeArray
- };
- static
- bool IsStreamOutputObject(ShaderObjectKind value)
- {
- return (value == SOK_StreamOutputPoint) ||
- (value == SOK_StreamOutputLine) ||
- (value == SOK_StreamOutputTriangle);
- }
- struct ShaderObjectDataItem
- {
- ShaderObjectKind Kind;
- const char* TypeName;
- ShaderModel MinShaderModel;
- ShaderType ValidShaderTypes;
- };
- static const
- ShaderObjectDataItem ShaderObjectData[] =
- {
- { SOK_AppendStructuredBuffer, "AppendStructuredBuffer", ShaderModel5, ST_PixelCompute },
- { SOK_Buffer, "Buffer", ShaderModel5, ST_All },
- { SOK_ByteAddressBuffer, "ByteAddressBuffer", ShaderModel5, ST_All },
- { SOK_ConsumeStructuredBuffer, "ConsumeStructuredBuffer", ShaderModel5, ST_PixelCompute },
- { SOK_InputPatch, "InputPatch", ShaderModel5, ST_HullGeometry },
- { SOK_OutputPatch, "OutputPatch", ShaderModel5, ST_HullDomain },
- { SOK_RWBuffer, "RWBuffer", ShaderModel5, ST_PixelCompute },
- { SOK_RWByteAddressBuffer, "RWByteAddressBuffer", ShaderModel5, ST_PixelCompute },
- { SOK_RWStructuredBuffer, "RWStructuredBuffer", ShaderModel5, ST_PixelCompute },
- { SOK_RWTexture1D, "RWTexture1D", ShaderModel5, ST_PixelCompute },
- { SOK_RWTexture1DArray, "RWTexture1DArray", ShaderModel5, ST_PixelCompute },
- { SOK_RWTexture2D, "RWTexture2D", ShaderModel5, ST_PixelCompute },
- { SOK_RWTexture2DArray, "RWTexture2DArray", ShaderModel5, ST_PixelCompute },
- { SOK_RWTexture3D, "RWTexture3D", ShaderModel5, ST_PixelCompute },
- { SOK_StreamOutputLine, "LineStream", ShaderModel4, ST_Geometry },
- { SOK_StreamOutputPoint, "PointStream", ShaderModel4, ST_Geometry },
- { SOK_StreamOutputTriangle, "TriangleStream", ShaderModel4, ST_Geometry },
- { SOK_StructuredBuffer, "StructuredBuffer", ShaderModel5, ST_All },
- { SOK_Texture1D, "Texture1D", ShaderModel4, ST_All },
- { SOK_Texture1DArray, "Texture1DArray", ShaderModel4, ST_All },
- { SOK_Texture2D, "Texture2D", ShaderModel4, ST_All },
- { SOK_Texture2DArray, "Texture2DArray", ShaderModel4, ST_All },
- { SOK_Texture2DMS, "Texture2DMS", ShaderModel4, ST_All },
- { SOK_Texture2DArrayMS, "Texture2DMSArray", ShaderModel4, ST_All },
- { SOK_Texture3D, "Texture3D", ShaderModel4, ST_All },
- { SOK_TextureCube, "TextureCube", ShaderModel4, ST_All },
- { SOK_TextureCubeArray, "TextureCubeArray", ShaderModel4, ST_All }
- };
- /// Enumerates the template shapes.
- /// This is a crude simplification of what the type system could do,
- /// but it covers all cases without unused generality.
- enum ShaderObjectTemplateKind
- {
- /// No parameters.
- SOTK_NoParams,
- /// Single parameter of type scalar or vector.
- SOTK_SingleSVParam,
- /// Single parameter of type scalar, vector or struct.
- SOTK_SingleSVCParam,
- /// Two parameters; a scalar or vector type and a sample count.
- SOTK_SVAndSampleCountParams,
- /// Two parameters; a scalar or vector type and a control point count (1-32).
- SOTK_SVCAndControlPointCountParams
- };
- struct ShaderObjectTemplateDataItem
- {
- ShaderObjectKind Kind;
- ShaderObjectTemplateKind TemplateKind;
- bool TemplateParamsOptional;
- };
- static const bool OptionalTrue = true;
- static const bool OptionalFalse = false;
- static const
- ShaderObjectTemplateDataItem ShaderObjectTemplateData[] =
- {
- { SOK_AppendStructuredBuffer, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_Buffer, SOTK_SingleSVParam, OptionalFalse },
- { SOK_ByteAddressBuffer, SOTK_NoParams, OptionalTrue },
- { SOK_ConsumeStructuredBuffer, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_InputPatch, SOTK_SVCAndControlPointCountParams, OptionalFalse },
- { SOK_OutputPatch, SOTK_SVCAndControlPointCountParams, OptionalFalse },
- { SOK_RWBuffer, SOTK_SingleSVParam, OptionalFalse },
- { SOK_RWByteAddressBuffer, SOTK_NoParams, OptionalTrue },
- { SOK_RWStructuredBuffer, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_RWTexture1D, SOTK_SingleSVParam, OptionalFalse },
- { SOK_RWTexture1DArray, SOTK_SingleSVParam, OptionalFalse },
- { SOK_RWTexture2D, SOTK_SingleSVParam, OptionalFalse },
- { SOK_RWTexture2DArray, SOTK_SingleSVParam, OptionalFalse },
- { SOK_RWTexture3D, SOTK_SingleSVParam, OptionalFalse },
- { SOK_StreamOutputLine, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_StreamOutputPoint, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_StreamOutputTriangle, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_StructuredBuffer, SOTK_SingleSVCParam, OptionalFalse },
- { SOK_Texture1D, SOTK_SingleSVParam, OptionalTrue },
- { SOK_Texture1DArray, SOTK_SingleSVParam, OptionalTrue },
- { SOK_Texture2D, SOTK_SingleSVParam, OptionalTrue },
- { SOK_Texture2DArray, SOTK_SingleSVParam, OptionalTrue },
- { SOK_Texture2DMS, SOTK_SVAndSampleCountParams, OptionalFalse },
- { SOK_Texture2DArrayMS, SOTK_SVAndSampleCountParams, OptionalFalse },
- { SOK_Texture3D, SOTK_SingleSVParam, OptionalTrue },
- { SOK_TextureCube, SOTK_SingleSVParam, OptionalTrue },
- { SOK_TextureCubeArray, SOTK_SingleSVParam, OptionalTrue }
- };
- static
- const ShaderObjectTemplateDataItem& GetTemplateData(const ShaderObjectDataItem& sod)
- {
- static_assert(
- _countof(ShaderObjectTemplateData) == _countof(ShaderObjectData),
- "otherwise lookup tables have different elements");
- struct Unary {
- ShaderObjectKind ObjectKind;
- Unary(ShaderObjectKind ok) : ObjectKind(ok) { }
- bool operator()(const ShaderObjectTemplateDataItem& i) { return i.Kind == ObjectKind; }
- };
- Unary filter(sod.Kind);
- auto iter = std::find_if(std::begin(ShaderObjectTemplateData), std::end(ShaderObjectTemplateData), filter);
- assert(iter != std::end(ShaderObjectTemplateData));
- return *iter;
- }
- static
- bool HasOptionalTemplateArguments(const ShaderObjectDataItem& sod)
- {
- const ShaderObjectTemplateDataItem& templateData = GetTemplateData(sod);
- return templateData.TemplateKind != SOTK_NoParams &&
- templateData.TemplateParamsOptional;
- }
- static
- int CountOptionalTemplateArguments(const ShaderObjectTemplateDataItem& templateData)
- {
- if (!templateData.TemplateParamsOptional) {
- return 0;
- }
- switch (templateData.TemplateKind) {
- default:
- case SOTK_NoParams: return 0;
- case SOTK_SingleSVParam: return 1;
- case SOTK_SingleSVCParam: return 1;
- case SOTK_SVAndSampleCountParams: return 2;
- case SOTK_SVCAndControlPointCountParams: return 2;
- }
- }
- struct ShaderObjectMethodDataItem
- {
- ShaderObjectKind ObjectKind;
- const char* MethodName;
- };
- static const
- ShaderObjectDataItem ShaderObjectMethodData[] =
- {
- { SOK_AppendStructuredBuffer, "Append" },
- { SOK_AppendStructuredBuffer, "GetDimensions" },
- { SOK_Buffer, "GetDimensions" },
- { SOK_Buffer, "Load" }, // overloaded!
- { SOK_Buffer, "operator[]" },
- { SOK_ByteAddressBuffer, "GetDimensions" },
- { SOK_ByteAddressBuffer, "Load" }, // overloaded
- { SOK_ByteAddressBuffer, "Load2" }, // overloaded
- { SOK_ByteAddressBuffer, "Load3" }, // overloaded
- { SOK_ByteAddressBuffer, "Load4" }, // overloaded
- { SOK_ConsumeStructuredBuffer, "Consume" },
- { SOK_ConsumeStructuredBuffer, "GetDimensions" },
- { SOK_InputPatch, "operator[]" },
- { SOK_InputPatch, "Length" }, // actually a property
- { SOK_OutputPatch, "operator[]" },
- { SOK_OutputPatch, "Length" }, // actually a property
- { SOK_RWBuffer, "GetDimensions" },
- { SOK_RWBuffer, "Load" }, // overloaded!
- { SOK_RWBuffer, "operator[]" }
- // TODO: add RWByteAddressBuffer members
- // TODO: add RWStructuredBuffer members
- };
- // - a RWBuffer supports globallycoherent storage class to generate memory barriers
- // TODO: ByteAddressBuffer is supported on SM4 on compute shaders
- // TODO: RWByteAddressBuffer is supported on SM4 on compute shaders
- // TODO: RWStructuredBuffer is supported on SM4 on compute shaders
- #include "dxc/dxcapi.internal.h"
- #include "dxc/HlslIntrinsicOp.h"
- #include "gen_intrin_main_tables_15.h"
- struct ShaderObjectIntrinsicDataItem
- {
- // Kind of shader object described.
- ShaderObjectKind Kind;
- // Pointer to first intrinsic in table.
- const HLSL_INTRINSIC* Intrinsics;
- // Count of elements in intrinsic table.
- size_t IntrinsicCount;
- };
- const ShaderObjectIntrinsicDataItem ShaderObjectIntrinsicData[] = {
- { SOK_AppendStructuredBuffer, g_AppendStructuredBufferMethods, _countof(g_AppendStructuredBufferMethods) },
- { SOK_Buffer, g_BufferMethods, _countof(g_BufferMethods) },
- { SOK_ByteAddressBuffer, g_ByteAddressBufferMethods, _countof(g_ByteAddressBufferMethods) },
- { SOK_ConsumeStructuredBuffer, g_ConsumeStructuredBufferMethods, _countof(g_ByteAddressBufferMethods) },
- { SOK_InputPatch, nullptr, 0 },
- { SOK_OutputPatch, nullptr, 0 },
- { SOK_RWBuffer, g_RWBufferMethods, _countof(g_RWBufferMethods) },
- { SOK_RWByteAddressBuffer, g_RWByteAddressBufferMethods, _countof(g_RWByteAddressBufferMethods) },
- { SOK_RWStructuredBuffer, g_RWStructuredBufferMethods, _countof(g_RWStructuredBufferMethods) },
- { SOK_RWTexture1D, g_RWTexture1DMethods, _countof(g_RWTexture1DMethods) },
- { SOK_RWTexture1DArray, g_RWTexture1DArrayMethods, _countof(g_RWTexture1DArrayMethods) },
- { SOK_RWTexture2D, g_RWTexture2DMethods, _countof(g_RWTexture2DMethods) },
- { SOK_RWTexture2DArray, g_RWTexture2DArrayMethods, _countof(g_RWTexture2DArrayMethods) },
- { SOK_RWTexture3D, g_RWTexture3DMethods, _countof(g_RWTexture3DMethods) },
- { SOK_StreamOutputLine, g_StreamMethods, _countof(g_StreamMethods) },
- { SOK_StreamOutputPoint, g_StreamMethods, _countof(g_StreamMethods) },
- { SOK_StreamOutputTriangle, g_StreamMethods, _countof(g_StreamMethods) },
- { SOK_StructuredBuffer, g_StructuredBufferMethods, _countof(g_StructuredBufferMethods) },
- { SOK_Texture1D, g_Texture1DMethods, _countof(g_Texture1DMethods) },
- { SOK_Texture1DArray, g_Texture1DArrayMethods, _countof(g_Texture1DArrayMethods) },
- { SOK_Texture2D, g_Texture2DMethods, _countof(g_Texture2DMethods) },
- { SOK_Texture2DArray, g_Texture2DArrayMethods, _countof(g_Texture2DArrayMethods) },
- { SOK_Texture2DMS, g_Texture2DMSMethods, _countof(g_Texture2DMSMethods) },
- { SOK_Texture2DArrayMS, g_Texture2DArrayMSMethods, _countof(g_Texture2DArrayMSMethods) },
- { SOK_Texture3D, g_Texture3DMethods, _countof(g_Texture3DMethods) },
- { SOK_TextureCube, g_TextureCUBEMethods, _countof(g_TextureCUBEMethods) },
- { SOK_TextureCubeArray, g_TextureCUBEArrayMethods, _countof(g_TextureCUBEArrayMethods) }
- };
- static
- const ShaderObjectIntrinsicDataItem& GetIntrinsicData(const ShaderObjectDataItem& sod)
- {
- for (int i = 0; i < _countof(ShaderObjectIntrinsicData); i++)
- {
- if (sod.Kind == ShaderObjectIntrinsicData[i].Kind)
- {
- return ShaderObjectIntrinsicData[i];
- }
- }
- throw std::exception("cannot find shader object kind");
- }
- // The test fixture.
- class ObjectTest
- {
- private:
- HlslIntellisenseSupport m_isenseSupport;
- public:
- BEGIN_TEST_CLASS(ObjectTest)
- TEST_CLASS_PROPERTY(L"Parallel", L"true")
- TEST_METHOD_PROPERTY(L"Priority", L"0")
- END_TEST_CLASS()
- TEST_CLASS_SETUP(ObjectTestSetup);
- TEST_METHOD(DeclareLocalObject);
- TEST_METHOD(OptionalTemplateArgs);
- TEST_METHOD(MissingTemplateArgs);
- TEST_METHOD(TooManyTemplateArgs);
- TEST_METHOD(PassAsParameter);
- TEST_METHOD(AssignVariables);
- TEST_METHOD(AssignReturnResult);
- TEST_METHOD(PassToInoutArgs);
- TEST_METHOD(TemplateArgConstraints);
- TEST_METHOD(FunctionInvoke);
- void FormatTypeNameAndPreamble(const ShaderObjectDataItem& sod,
- char (&typeName)[64],
- const char** preambleDecl) {
- *preambleDecl = "";
- auto templateData = GetTemplateData(sod);
- switch (templateData.TemplateKind) {
- case SOTK_NoParams:
- sprintf_s(typeName, _countof(typeName), "%s", sod.TypeName);
- break;
- case SOTK_SingleSVParam:
- sprintf_s(typeName, _countof(typeName), "%s<float4>", sod.TypeName);
- break;
- case SOTK_SingleSVCParam:
- *preambleDecl = "struct MY_STRUCT { float4 f4; bool b; int3 i3; };\n";
- sprintf_s(typeName, _countof(typeName), "%s<MY_STRUCT>", sod.TypeName);
- break;
- case SOTK_SVAndSampleCountParams:
- case SOTK_SVCAndControlPointCountParams:
- default:
- sprintf_s(typeName, _countof(typeName), "%s<float4, 1>", sod.TypeName);
- break;
- }
- }
- std::string BuildDeclarationFunction(const ShaderObjectDataItem& sod) {
- return BuildDeclarationFunction(sod, 0, false);
- }
- std::string BuildDeclarationFunction(const ShaderObjectDataItem& sod, int missingTemplateCount,
- bool collapseEmptyArgs) {
- char result[256];
- auto templateData = GetTemplateData(sod);
- const char StructDecl[] = "struct MY_STRUCT { float4 f4; bool b; int3 i3; };\n";
- const char StructParam[] = "<MY_STRUCT>\n";
- const char VectorParam[] = "<float4>\n";
- const char VectorAndCountParam[] = "<float4, 4>\n";
- const char EmptyTemplateArgs[] = "<>";
- const char MissingTemplateArgs[] = "";
- // Default setup for a 'SOTK_NoParams' case.
- const char* StructDeclFragment = "";
- const char* TemplateDeclFragment = MissingTemplateArgs;
- if (templateData.TemplateKind == SOTK_SingleSVParam && missingTemplateCount == 0) {
- TemplateDeclFragment = VectorParam;
- } else if (templateData.TemplateKind == SOTK_SingleSVCParam && missingTemplateCount == 0) {
- StructDeclFragment = StructDecl;
- TemplateDeclFragment = StructParam;
- } else if ((templateData.TemplateKind == SOTK_SVAndSampleCountParams ||
- templateData.TemplateKind == SOTK_SVCAndControlPointCountParams)) {
- if (missingTemplateCount == 0) {
- TemplateDeclFragment = VectorAndCountParam;
- } else if (missingTemplateCount == 1) {
- TemplateDeclFragment = VectorParam;
- }
- }
- // Allow 'Object<>' to collapse to 'Object' when collapseEmptyArgs is set.
- if (templateData.TemplateKind != SOTK_NoParams && TemplateDeclFragment == MissingTemplateArgs) {
- TemplateDeclFragment = collapseEmptyArgs ? MissingTemplateArgs : EmptyTemplateArgs;
- }
- sprintf_s(result, _countof(result), "%s"
- "float ps(float4 color : COLOR) { %s%s localVar; return 0; }",
- StructDeclFragment, sod.TypeName, TemplateDeclFragment);
- return std::string(result);
- }
- std::string BuildDeclarationFunctionTooManyArgs(const ShaderObjectDataItem& sod) {
- char result[256];
- auto templateData = GetTemplateData(sod);
- switch (templateData.TemplateKind) {
- case SOTK_NoParams:
- sprintf_s(result, _countof(result),
- "float ps(float4 color : COLOR) { %s localVar<float>; return 0; }", sod.TypeName);
- break;
- case SOTK_SingleSVParam:
- sprintf_s(result, _countof(result),
- "float ps(float4 color : COLOR) { %s<float4, 1> localVar; return 0; }", sod.TypeName);
- break;
- case SOTK_SingleSVCParam:
- sprintf_s(result, _countof(result),
- "struct MY_STRUCT { float4 f4; bool b; int3 i3; };\n"
- "float ps(float4 color : COLOR) { %s<MY_STRUCT, 1> localVar; return 0; }", sod.TypeName);
- break;
- case SOTK_SVAndSampleCountParams:
- case SOTK_SVCAndControlPointCountParams:
- default:
- sprintf_s(result, _countof(result),
- "float ps(float4 color : COLOR) { %s<float4, 4, 4> localVar; return 0; }", sod.TypeName);
- break;
- }
- return std::string(result);
- }
-
- std::string BuildPassAsParameter(const ShaderObjectDataItem& sod) {
- char result[256];
- char typeName[64];
- const char* preambleDecl;
- FormatTypeNameAndPreamble(sod, typeName, &preambleDecl);
- sprintf_s(result, _countof(result),
- "%s"
- "void f(%s parameter) { }\n"
- "float ps(float4 color : COLOR) { %s localVar; f(localVar); return 0; }",
- preambleDecl, typeName, typeName);
- return std::string(result);
- }
- std::string BuildAssignment(const ShaderObjectDataItem& sod) {
- char result[256];
- char typeName[64];
- const char* preambleDecl;
- FormatTypeNameAndPreamble(sod, typeName, &preambleDecl);
- sprintf_s(result, _countof(result),
- "%s"
- "float ps(float4 color : COLOR) { %s lv1; %s lv2; lv1 = lv2; return 0; }",
- preambleDecl, typeName, typeName);
- return std::string(result);
- }
-
- std::string BuildAssignmentFromResult(const ShaderObjectDataItem& sod) {
- char result[256];
- char typeName[64];
- const char* preambleDecl;
- FormatTypeNameAndPreamble(sod, typeName, &preambleDecl);
- sprintf_s(result, _countof(result),
- "%s"
- "%s f() { %s local; return local; }\n"
- "float ps(float4 color : COLOR) { %s lv1 = f(); return 0; }",
- preambleDecl, typeName, typeName, typeName);
- return std::string(result);
- }
-
- void CheckCompiles(const std::string& text, bool expected) {
- CheckCompiles(text.c_str(), text.size(), expected);
- }
-
- void CheckCompiles(const char* text, size_t textLen, bool expected) {
- CompilationResult result(
- CompilationResult::CreateForProgram(text, textLen));
- // Uncomment the line to print out the AST unconditionally.
- // printf("%s", result.BuildASTString().c_str());
- if (expected != result.ParseSucceeded())
- {
- EXPECT_EQ(expected, result.ParseSucceeded());
- // TODO: log this out
- //<< "for program " << text << "\n with AST\n" << result.BuildASTString()
- //<< "and errors\n" << result.GetTextForErrors();
- }
- }
- };
- bool ObjectTest::ObjectTestSetup()
- {
- // Runs once for all tests in this class.
- // Load the dxcompiler DLL and hold a reference to it to avoid unload/reloads.
- m_isenseSupport.Initialize();
- return m_isenseSupport.IsEnabled();
- }
- TEST_F(ObjectTest, DeclareLocalObject) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- CheckCompiles(BuildDeclarationFunction(sod), true);
- }
- }
- TEST_F(ObjectTest, OptionalTemplateArgs) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- const ShaderObjectTemplateDataItem& templateData = GetTemplateData(sod);
- int argCount = CountOptionalTemplateArguments(templateData);
- if (argCount == 0) {
- continue;
- }
- for (int missingCount = 1; missingCount <= argCount; missingCount++) {
- CheckCompiles(BuildDeclarationFunction(sod, missingCount, false), true);
- }
- }
- }
- TEST_F(ObjectTest, MissingTemplateArgs) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- const ShaderObjectTemplateDataItem& templateData = GetTemplateData(sod);
- int argCount = CountOptionalTemplateArguments(templateData);
- if (argCount == 0) {
- continue;
- }
- CheckCompiles(BuildDeclarationFunction(sod, argCount, true), true);
- }
- }
- TEST_F(ObjectTest, TooManyTemplateArgs) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- CheckCompiles(BuildDeclarationFunctionTooManyArgs(sod), false);
- }
- }
- TEST_F(ObjectTest, PassAsParameter) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- CheckCompiles(BuildPassAsParameter(sod), true);
- }
- }
- TEST_F(ObjectTest, AssignVariables) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- CheckCompiles(BuildAssignment(sod), true);
- }
- }
- TEST_F(ObjectTest, AssignReturnResult) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- CheckCompiles(BuildAssignmentFromResult(sod), true);
- }
- }
- TEST_F(ObjectTest, PassToInoutArgs) {
- for (const auto &sod : ShaderObjectData) {
- // Speed up the test by building one large program with all inout parameter modifiers per object.
- std::stringstream programText;
- unsigned uniqueId = 0;
- for (const auto &iop : InOutParameterModifierData) {
- char typeName[64];
- const char* preambleDecl;
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- FormatTypeNameAndPreamble(sod, typeName, &preambleDecl);
- if (uniqueId == 0) { // do this only once
- programText << preambleDecl << std::endl;
- }
- programText <<
- "float ps_" << uniqueId << "(" << iop.Keyword << " " << typeName << " o) { return 1.0f; }" << std::endl;
- programText << "void caller_" << uniqueId << "() { " << typeName << " lv; ps_" << uniqueId << "(lv); }" << std::endl;
- programText << std::endl;
- uniqueId++;
- }
-
- std::string programTextStr(programText.str());
- CheckCompiles(programTextStr.c_str(), programTextStr.size(), true);
- }
- }
- class TemplateSampleDataItem
- {
- public:
- TemplateSampleDataItem() { }
- TemplateSampleDataItem(const TemplateSampleDataItem& other)
- : Preamble(other.Preamble), TypeName(other.TypeName), IsValid(other.IsValid)
- {
- }
- TemplateSampleDataItem(const char* preamble, const char* typeName, bool isValid)
- : Preamble(preamble), TypeName(typeName), IsValid(isValid)
- {
- }
- std::string Preamble;
- std::string TypeName;
- bool IsValid;
- };
- std::vector<TemplateSampleDataItem>
- CreateSampleDataForTemplateArg(
- const ShaderObjectDataItem& sod,
- int templateIndex)
- {
- std::vector<TemplateSampleDataItem> result;
- char typeName[64];
- auto templateData = GetTemplateData(sod);
- assert(templateData.TemplateKind != SOTK_NoParams && "shouldn't call CreateSampleDataForTemplateArg");
- switch (templateData.TemplateKind) {
- case SOTK_SingleSVParam:
- case SOTK_SingleSVCParam:
- sprintf_s(typeName, _countof(typeName), "%s<float4>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, true));
- sprintf_s(typeName, _countof(typeName), "%s<SamplerState>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, false));
- break;
- case SOTK_SVAndSampleCountParams:
- case SOTK_SVCAndControlPointCountParams:
- if (templateIndex == 0) {
- sprintf_s(typeName, _countof(typeName), "%s<float4, 4>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, true));
- sprintf_s(typeName, _countof(typeName), "%s<SamplerState, 4>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, false));
- } else {
- sprintf_s(typeName, _countof(typeName), "%s<float4, 1>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, true));
- sprintf_s(typeName, _countof(typeName), "%s<float4, 128>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, true));
- // These are deferred to back-end validation for now.
- // bool largeNumberValid = sod.Kind == SOK_InputPatch || sod.Kind == SOK_OutputPatch;
- sprintf_s(typeName, _countof(typeName), "%s<float4, 129>", sod.TypeName);
- result.push_back(TemplateSampleDataItem("", typeName, false));
- }
-
- break;
- }
- return result;
- }
- TEST_F(ObjectTest, TemplateArgConstraints) {
- for (const auto &sod : ShaderObjectData) {
- // When shader models are validated, run through all of them.
- // for (const auto &st : sod.ValidShaderTypes)
- const auto st = std::first(sod.ValidShaderTypes);
- const ShaderObjectTemplateDataItem& templateData = GetTemplateData(sod);
- int argCount = CountOptionalTemplateArguments(templateData);
- if (argCount == 0) {
- continue;
- }
- for (int i = 0; i < argCount; i++) {
- std::vector<TemplateSampleDataItem> sampleData =
- CreateSampleDataForTemplateArg(sod, i);
- for (auto sampleDataItem : sampleData) {
- char result[256];
- sprintf_s(result, _countof(result),
- "%s"
- "float ps(float4 color : COLOR) { %s lv1; %s lv2; lv1 = lv2; return 0; }",
- sampleDataItem.Preamble.c_str(),
- sampleDataItem.TypeName.c_str(), sampleDataItem.TypeName.c_str());
- CheckCompiles(result, strlen(result), sampleDataItem.IsValid);
- }
- }
- }
- }
- static
- std::string SelectComponentType(BYTE legalTypes)
- {
- switch ((LEGAL_INTRINSIC_COMPTYPES)legalTypes)
- {
- case LICOMPTYPE_VOID: return "void";
- case LICOMPTYPE_BOOL: return "bool";
- case LICOMPTYPE_INT: return "int";
- case LICOMPTYPE_UINT: return "uint";
- case LICOMPTYPE_ANY_INT: return "int";
- case LICOMPTYPE_ANY_INT32: return "int";
- case LICOMPTYPE_UINT_ONLY: return "uint";
- case LICOMPTYPE_FLOAT: return "float";
- case LICOMPTYPE_ANY_FLOAT: return "float";
- case LICOMPTYPE_FLOAT_LIKE: return "float";
- case LICOMPTYPE_FLOAT_DOUBLE: return "double";
- case LICOMPTYPE_DOUBLE: return "double";
- case LICOMPTYPE_DOUBLE_ONLY: return "double";
- case LICOMPTYPE_NUMERIC: return "int";
- case LICOMPTYPE_NUMERIC32: return "float";
- case LICOMPTYPE_NUMERIC32_ONLY: return "double";
- case LICOMPTYPE_ANY: return "int";
- default: return "";
- //LICOMPTYPE_SAMPLER1D,
- //LICOMPTYPE_SAMPLER2D,
- //LICOMPTYPE_SAMPLER3D,
- //LICOMPTYPE_SAMPLERCUBE,
- //LICOMPTYPE_SAMPLERCMP,
- //LICOMPTYPE_SAMPLER,
- //LICOMPTYPE_STRING,
- }
- }
- TEST_F(ObjectTest, FunctionInvoke) {
- // This is pending complete support for primitive types - there are many
- // instances of uint usage, which isn't currently supported.
- #if 0
- // Tests for too many or too few arguments are available as lit-based tests.
- // Invoke each method, assigning the result of each method invocation as necessary.
- uint64_t iteration = 0;
- for (const auto &sod : ShaderObjectData) {
- const ShaderObjectIntrinsicDataItem& intrinsicData = GetIntrinsicData(sod);
- const ShaderObjectTemplateDataItem& templateData = GetTemplateData(sod);
- for (size_t i = 0; i < intrinsicData.IntrinsicCount; i++) {
- const HLSL_INTRINSIC* intrinsic = &intrinsicData.Intrinsics[i];
- ++iteration;
- // Build a program that will call this intrinsic.
- // Select an element type for the class if needed.
- std::string objectType;
- std::string elementType;
- std::string elementParameters;
- switch (templateData.TemplateKind)
- {
- case ShaderObjectTemplateKind::SOTK_NoParams:
- break;
- case ShaderObjectTemplateKind::SOTK_SingleSVCParam:
- case ShaderObjectTemplateKind::SOTK_SingleSVParam:
- elementParameters = "<float3>";
- elementType = "float3";
- break;
- case ShaderObjectTemplateKind::SOTK_SVAndSampleCountParams:
- case ShaderObjectTemplateKind::SOTK_SVCAndControlPointCountParams:
- elementParameters = "<float3, 4>";
- elementType = "float3";
- break;
- }
- objectType = sod.TypeName + elementParameters;
- // Select types for all arguments.
- // This implementation is brain-dead but (a) different from production,
- // so it's a sensible oracle, and (b) very straightforward. We simply
- // keep instantiating argument types until we finished.
- std::string argumentTypes[g_MaxIntrinsicParamCount];
- {
- bool madeProgress = false;
- int argsRemaining = intrinsic->uNumArgs - 1;
- do
- {
- madeProgress = false;
- for (int i = 1; i < intrinsic->uNumArgs; i++)
- {
- if (!argumentTypes[i - 1].empty())
- {
- continue;
- }
- // Determine whether we can make an independent selection.
- if (intrinsic->pArgs[i].uTemplateId == INTRIN_TEMPLATE_FROM_TYPE)
- {
- argumentTypes[i - 1] = elementType;
- madeProgress = true;
- --argsRemaining;
- continue;
- }
- // An independent scalar.
- if (intrinsic->pArgs[i].uTemplateId == i && intrinsic->pArgs[i].uComponentTypeId == i &&
- intrinsic->pArgs[i].uLegalComponentTypes != LITEMPLATE_ANY &&
- intrinsic->pArgs[i].uLegalTemplates == LITEMPLATE_SCALAR)
- {
- argumentTypes[i - 1] = SelectComponentType(intrinsic->pArgs[i].uLegalComponentTypes);
- madeProgress = true;
- --argsRemaining;
- continue;
- }
- // An independent vector.
- if (intrinsic->pArgs[i].uTemplateId == i && intrinsic->pArgs[i].uComponentTypeId == i &&
- intrinsic->pArgs[i].uLegalComponentTypes != LITEMPLATE_ANY &&
- intrinsic->pArgs[i].uLegalTemplates == LITEMPLATE_VECTOR)
- {
- argumentTypes[i - 1] = SelectComponentType(intrinsic->pArgs[i].uLegalComponentTypes) + "2";
- madeProgress = true;
- --argsRemaining;
- continue;
- }
- // TODO: complete the assignment cases with primitive types
- // Determine whether we have all dependencies assigned for a selection.
- }
- } while (madeProgress && argsRemaining > 0);
- EXPECT_EQ(0, argsRemaining) <<
- "otherwise we're unable to complete the signature for " << intrinsic->pArgs[0].pName <<
- " in iteration " << iteration;
- }
- // Determine what the result type is.
- bool resultIsVoid = intrinsic->pArgs[0].uLegalTemplates == LITEMPLATE_VOID;
- std::string resultType;
- if (!resultIsVoid) {
- }
- // Assemble the program as a series of declarations, a method call
- // and possibly an assignment if there's a return value.
- std::stringstream program;
- std::string assignmentLeftHand(resultIsVoid ? "" : (resultType + " result = "));
- program << "// iteration " << iteration << "\n"
- "void f() {\n"
- " " << objectType << " testObject;\n";
- for (int i = 1; i < intrinsic->uNumArgs; i++) {
- program << argumentTypes[i - 1] << ' ' << intrinsic->pArgs[i].pName << ";\n";
- }
- program << assignmentLeftHand << "testObject." << intrinsic->pArgs[0].pName << "(";
- for (int i = 1; i < intrinsic->uNumArgs; i++) {
- program << intrinsic->pArgs[i].pName;
- if (i != intrinsic->uNumArgs - 1) {
- program << ", ";
- }
- }
- program << ");\n}";
- // Verify it runs.
- CheckCompiles(program.str(), true);
- }
- }
- #endif
- }
- // TODO: force type promotion to occur for arguments.
|