Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/Shader.cpp
4565 views
/**************************************************************************1*2* Copyright 2012-2021 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/2627/*28* Shader.cpp --29* Functions that manipulate shader resources.30*/313233#include "Shader.h"34#include "ShaderParse.h"35#include "State.h"36#include "Query.h"3738#include "Debug.h"39#include "Format.h"4041#include "tgsi/tgsi_ureg.h"42#include "util/u_gen_mipmap.h"43#include "util/u_sampler.h"44#include "util/format/u_format.h"454647/*48* ----------------------------------------------------------------------49*50* CreateEmptyShader --51*52* Update the driver's currently bound constant buffers.53*54* ----------------------------------------------------------------------55*/5657void *58CreateEmptyShader(Device *pDevice,59enum pipe_shader_type processor)60{61struct pipe_context *pipe = pDevice->pipe;62struct ureg_program *ureg;63const struct tgsi_token *tokens;64uint nr_tokens;6566if (processor == PIPE_SHADER_GEOMETRY) {67return NULL;68}6970ureg = ureg_create(processor);71if (!ureg)72return NULL;7374ureg_END(ureg);7576tokens = ureg_get_tokens(ureg, &nr_tokens);77if (!tokens)78return NULL;7980ureg_destroy(ureg);8182struct pipe_shader_state state;83memset(&state, 0, sizeof state);84state.tokens = tokens;8586void *handle;87switch (processor) {88case PIPE_SHADER_FRAGMENT:89handle = pipe->create_fs_state(pipe, &state);90break;91case PIPE_SHADER_VERTEX:92handle = pipe->create_vs_state(pipe, &state);93break;94case PIPE_SHADER_GEOMETRY:95handle = pipe->create_gs_state(pipe, &state);96break;97default:98handle = NULL;99assert(0);100}101assert(handle);102103ureg_free_tokens(tokens);104105return handle;106}107108109/*110* ----------------------------------------------------------------------111*112* CreateEmptyShader --113*114* Update the driver's currently bound constant buffers.115*116* ----------------------------------------------------------------------117*/118119void120DeleteEmptyShader(Device *pDevice,121enum pipe_shader_type processor, void *handle)122{123struct pipe_context *pipe = pDevice->pipe;124125if (processor == PIPE_SHADER_GEOMETRY) {126assert(handle == NULL);127return;128}129130assert(handle != NULL);131switch (processor) {132case PIPE_SHADER_FRAGMENT:133pipe->delete_fs_state(pipe, handle);134break;135case PIPE_SHADER_VERTEX:136pipe->delete_vs_state(pipe, handle);137break;138case PIPE_SHADER_GEOMETRY:139pipe->delete_gs_state(pipe, handle);140break;141default:142assert(0);143}144}145146147/*148* ----------------------------------------------------------------------149*150* SetConstantBuffers --151*152* Update the driver's currently bound constant buffers.153*154* ----------------------------------------------------------------------155*/156157static void158SetConstantBuffers(enum pipe_shader_type shader_type, // IN159D3D10DDI_HDEVICE hDevice, // IN160UINT StartBuffer, // IN161UINT NumBuffers, // IN162const D3D10DDI_HRESOURCE *phBuffers) // IN163{164Device *pDevice = CastDevice(hDevice);165struct pipe_context *pipe = pDevice->pipe;166167for (UINT i = 0; i < NumBuffers; i++) {168struct pipe_constant_buffer cb;169memset(&cb, 0, sizeof cb);170cb.buffer = CastPipeResource(phBuffers[i]);171cb.buffer_offset = 0;172cb.buffer_size = cb.buffer ? cb.buffer->width0 : 0;173pipe->set_constant_buffer(pipe,174shader_type,175StartBuffer + i,176FALSE,177&cb);178}179}180181182/*183* ----------------------------------------------------------------------184*185* SetSamplers --186*187* Update the driver's currently bound sampler state.188*189* ----------------------------------------------------------------------190*/191192static void193SetSamplers(enum pipe_shader_type shader_type, // IN194D3D10DDI_HDEVICE hDevice, // IN195UINT Offset, // IN196UINT NumSamplers, // IN197const D3D10DDI_HSAMPLER *phSamplers) // IN198{199Device *pDevice = CastDevice(hDevice);200struct pipe_context *pipe = pDevice->pipe;201202void **samplers = pDevice->samplers[shader_type];203for (UINT i = 0; i < NumSamplers; i++) {204assert(Offset + i < PIPE_MAX_SAMPLERS);205samplers[Offset + i] = CastPipeSamplerState(phSamplers[i]);206}207208pipe->bind_sampler_states(pipe, shader_type, 0, PIPE_MAX_SAMPLERS, samplers);209}210211212/*213* ----------------------------------------------------------------------214*215* SetSamplers --216*217* Update the driver's currently bound sampler state.218*219* ----------------------------------------------------------------------220*/221222static void223SetShaderResources(enum pipe_shader_type shader_type, // IN224D3D10DDI_HDEVICE hDevice, // IN225UINT Offset, // IN226UINT NumViews, // IN227const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN228{229Device *pDevice = CastDevice(hDevice);230struct pipe_context *pipe = pDevice->pipe;231232assert(Offset + NumViews <= D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);233234struct pipe_sampler_view **sampler_views = pDevice->sampler_views[shader_type];235for (UINT i = 0; i < NumViews; i++) {236struct pipe_sampler_view *sampler_view =237CastPipeShaderResourceView(phShaderResourceViews[i]);238if (Offset + i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {239sampler_views[Offset + i] = sampler_view;240} else {241if (sampler_view) {242LOG_UNSUPPORTED(TRUE);243break;244}245}246}247248/*249* XXX: Now that the semantics are actually the same in gallium, should250* probably think about not updating all always... It should just work.251*/252pipe->set_sampler_views(pipe, shader_type, 0, PIPE_MAX_SHADER_SAMPLER_VIEWS,2530, sampler_views);254}255256257/*258* ----------------------------------------------------------------------259*260* CalcPrivateShaderSize --261*262* The CalcPrivateShaderSize function determines the size of263* the user-mode display driver's private region of memory264* (that is, the size of internal driver structures, not the265* size of the resource video memory) for a shader.266*267* ----------------------------------------------------------------------268*/269270SIZE_T APIENTRY271CalcPrivateShaderSize(D3D10DDI_HDEVICE hDevice, // IN272__in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN273__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN274{275return sizeof(Shader);276}277278279/*280* ----------------------------------------------------------------------281*282* DestroyShader --283*284* The DestroyShader function destroys the specified shader object.285* The shader object can be destoyed only if it is not currently286* bound to a display device.287*288* ----------------------------------------------------------------------289*/290291void APIENTRY292DestroyShader(D3D10DDI_HDEVICE hDevice, // IN293D3D10DDI_HSHADER hShader) // IN294{295LOG_ENTRYPOINT();296297struct pipe_context *pipe = CastPipeContext(hDevice);298Shader *pShader = CastShader(hShader);299300if (pShader->handle) {301switch (pShader->type) {302case PIPE_SHADER_FRAGMENT:303pipe->delete_fs_state(pipe, pShader->handle);304break;305case PIPE_SHADER_VERTEX:306pipe->delete_vs_state(pipe, pShader->handle);307break;308case PIPE_SHADER_GEOMETRY:309pipe->delete_gs_state(pipe, pShader->handle);310break;311default:312assert(0);313}314}315316if (pShader->state.tokens) {317ureg_free_tokens(pShader->state.tokens);318}319}320321322/*323* ----------------------------------------------------------------------324*325* CalcPrivateSamplerSize --326*327* The CalcPrivateSamplerSize function determines the size of the328* user-mode display driver's private region of memory (that is,329* the size of internal driver structures, not the size of the330* resource video memory) for a sampler.331*332* ----------------------------------------------------------------------333*/334335SIZE_T APIENTRY336CalcPrivateSamplerSize(D3D10DDI_HDEVICE hDevice, // IN337__in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc) // IN338{339return sizeof(SamplerState);340}341342343static uint344translate_address_mode(D3D10_DDI_TEXTURE_ADDRESS_MODE AddressMode)345{346switch (AddressMode) {347case D3D10_DDI_TEXTURE_ADDRESS_WRAP:348return PIPE_TEX_WRAP_REPEAT;349case D3D10_DDI_TEXTURE_ADDRESS_MIRROR:350return PIPE_TEX_WRAP_MIRROR_REPEAT;351case D3D10_DDI_TEXTURE_ADDRESS_CLAMP:352return PIPE_TEX_WRAP_CLAMP_TO_EDGE;353case D3D10_DDI_TEXTURE_ADDRESS_BORDER:354return PIPE_TEX_WRAP_CLAMP_TO_BORDER;355case D3D10_DDI_TEXTURE_ADDRESS_MIRRORONCE:356return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;357default:358assert(0);359return PIPE_TEX_WRAP_REPEAT;360}361}362363static uint364translate_comparison(D3D10_DDI_COMPARISON_FUNC Func)365{366switch (Func) {367case D3D10_DDI_COMPARISON_NEVER:368return PIPE_FUNC_NEVER;369case D3D10_DDI_COMPARISON_LESS:370return PIPE_FUNC_LESS;371case D3D10_DDI_COMPARISON_EQUAL:372return PIPE_FUNC_EQUAL;373case D3D10_DDI_COMPARISON_LESS_EQUAL:374return PIPE_FUNC_LEQUAL;375case D3D10_DDI_COMPARISON_GREATER:376return PIPE_FUNC_GREATER;377case D3D10_DDI_COMPARISON_NOT_EQUAL:378return PIPE_FUNC_NOTEQUAL;379case D3D10_DDI_COMPARISON_GREATER_EQUAL:380return PIPE_FUNC_GEQUAL;381case D3D10_DDI_COMPARISON_ALWAYS:382return PIPE_FUNC_ALWAYS;383default:384assert(0);385return PIPE_FUNC_ALWAYS;386}387}388389static uint390translate_filter(D3D10_DDI_FILTER_TYPE Filter)391{392switch (Filter) {393case D3D10_DDI_FILTER_TYPE_POINT:394return PIPE_TEX_FILTER_NEAREST;395case D3D10_DDI_FILTER_TYPE_LINEAR:396return PIPE_TEX_FILTER_LINEAR;397default:398assert(0);399return PIPE_TEX_FILTER_NEAREST;400}401}402403static uint404translate_min_filter(D3D10_DDI_FILTER Filter)405{406return translate_filter(D3D10_DDI_DECODE_MIN_FILTER(Filter));407}408409static uint410translate_mag_filter(D3D10_DDI_FILTER Filter)411{412return translate_filter(D3D10_DDI_DECODE_MAG_FILTER(Filter));413}414415/* Gallium uses a different enum for mipfilters, to accomodate the GL416* MIPFILTER_NONE mode.417*/418static uint419translate_mip_filter(D3D10_DDI_FILTER Filter)420{421switch (D3D10_DDI_DECODE_MIP_FILTER(Filter)) {422case D3D10_DDI_FILTER_TYPE_POINT:423return PIPE_TEX_MIPFILTER_NEAREST;424case D3D10_DDI_FILTER_TYPE_LINEAR:425return PIPE_TEX_MIPFILTER_LINEAR;426default:427assert(0);428return PIPE_TEX_MIPFILTER_NEAREST;429}430}431432/*433* ----------------------------------------------------------------------434*435* CreateSampler --436*437* The CreateSampler function creates a sampler.438*439* ----------------------------------------------------------------------440*/441442void APIENTRY443CreateSampler(D3D10DDI_HDEVICE hDevice, // IN444__in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc, // IN445D3D10DDI_HSAMPLER hSampler, // IN446D3D10DDI_HRTSAMPLER hRTSampler) // IN447{448LOG_ENTRYPOINT();449450struct pipe_context *pipe = CastPipeContext(hDevice);451SamplerState *pSamplerState = CastSamplerState(hSampler);452453struct pipe_sampler_state state;454455memset(&state, 0, sizeof state);456457/* d3d10 has seamless cube filtering always enabled */458state.seamless_cube_map = 1;459460/* Wrapping modes. */461state.wrap_s = translate_address_mode(pSamplerDesc->AddressU);462state.wrap_t = translate_address_mode(pSamplerDesc->AddressV);463state.wrap_r = translate_address_mode(pSamplerDesc->AddressW);464465/* Filtering */466state.min_img_filter = translate_min_filter(pSamplerDesc->Filter);467state.mag_img_filter = translate_mag_filter(pSamplerDesc->Filter);468state.min_mip_filter = translate_mip_filter(pSamplerDesc->Filter);469470if (D3D10_DDI_DECODE_IS_ANISOTROPIC_FILTER(pSamplerDesc->Filter)) {471state.max_anisotropy = pSamplerDesc->MaxAnisotropy;472}473474/* XXX: Handle the following bit.475*/476LOG_UNSUPPORTED(D3D10_DDI_DECODE_IS_TEXT_1BIT_FILTER(pSamplerDesc->Filter));477478/* Comparison. */479if (D3D10_DDI_DECODE_IS_COMPARISON_FILTER(pSamplerDesc->Filter)) {480state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;481state.compare_func = translate_comparison(pSamplerDesc->ComparisonFunc);482}483484state.normalized_coords = 1;485486/* Level of detail. */487state.lod_bias = pSamplerDesc->MipLODBias;488state.min_lod = pSamplerDesc->MinLOD;489state.max_lod = pSamplerDesc->MaxLOD;490491/* Border color. */492state.border_color.f[0] = pSamplerDesc->BorderColor[0];493state.border_color.f[1] = pSamplerDesc->BorderColor[1];494state.border_color.f[2] = pSamplerDesc->BorderColor[2];495state.border_color.f[3] = pSamplerDesc->BorderColor[3];496497pSamplerState->handle = pipe->create_sampler_state(pipe, &state);498}499500501/*502* ----------------------------------------------------------------------503*504* DestroySampler --505*506* The DestroySampler function destroys the specified sampler object.507* The sampler object can be destoyed only if it is not currently508* bound to a display device.509*510* ----------------------------------------------------------------------511*/512513void APIENTRY514DestroySampler(D3D10DDI_HDEVICE hDevice, // IN515D3D10DDI_HSAMPLER hSampler) // IN516{517LOG_ENTRYPOINT();518519struct pipe_context *pipe = CastPipeContext(hDevice);520SamplerState *pSamplerState = CastSamplerState(hSampler);521522pipe->delete_sampler_state(pipe, pSamplerState->handle);523}524525526/*527* ----------------------------------------------------------------------528*529* CreateVertexShader --530*531* The CreateVertexShader function creates a vertex shader.532*533* ----------------------------------------------------------------------534*/535536void APIENTRY537CreateVertexShader(D3D10DDI_HDEVICE hDevice, // IN538__in_ecount (pShaderCode[1]) const UINT *pCode, // IN539D3D10DDI_HSHADER hShader, // IN540D3D10DDI_HRTSHADER hRTShader, // IN541__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN542{543LOG_ENTRYPOINT();544545struct pipe_context *pipe = CastPipeContext(hDevice);546Shader *pShader = CastShader(hShader);547548pShader->type = PIPE_SHADER_VERTEX;549pShader->output_resolved = TRUE;550551memset(&pShader->state, 0, sizeof pShader->state);552pShader->state.tokens = Shader_tgsi_translate(pCode, pShader->output_mapping);553554pShader->handle = pipe->create_vs_state(pipe, &pShader->state);555556}557558559/*560* ----------------------------------------------------------------------561*562* VsSetShader --563*564* The VsSetShader function sets the vertex shader code so that all565* of the subsequent drawing operations use that code.566*567* ----------------------------------------------------------------------568*/569570void APIENTRY571VsSetShader(D3D10DDI_HDEVICE hDevice, // IN572D3D10DDI_HSHADER hShader) // IN573{574LOG_ENTRYPOINT();575576Device *pDevice = CastDevice(hDevice);577struct pipe_context *pipe = pDevice->pipe;578Shader *pShader = CastShader(hShader);579void *state = CastPipeShader(hShader);580581pDevice->bound_vs = pShader;582if (!state) {583state = pDevice->empty_vs;584}585586pipe->bind_vs_state(pipe, state);587}588589590/*591* ----------------------------------------------------------------------592*593* VsSetShaderResources --594*595* The VsSetShaderResources function sets resources for a596* vertex shader.597*598* ----------------------------------------------------------------------599*/600601void APIENTRY602VsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN603UINT Offset, // IN604UINT NumViews, // IN605__in_ecount (NumViews)606const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN607{608LOG_ENTRYPOINT();609610SetShaderResources(PIPE_SHADER_VERTEX, hDevice, Offset, NumViews, phShaderResourceViews);611612}613614615/*616* ----------------------------------------------------------------------617*618* VsSetConstantBuffers --619*620* The VsSetConstantBuffers function sets constant buffers621* for a vertex shader.622*623* ----------------------------------------------------------------------624*/625626void APIENTRY627VsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN628UINT StartBuffer, // IN629UINT NumBuffers, // IN630__in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN631{632LOG_ENTRYPOINT();633634SetConstantBuffers(PIPE_SHADER_VERTEX,635hDevice, StartBuffer, NumBuffers, phBuffers);636}637638639/*640* ----------------------------------------------------------------------641*642* VsSetSamplers --643*644* The VsSetSamplers function sets samplers for a vertex shader.645*646* ----------------------------------------------------------------------647*/648649void APIENTRY650VsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN651UINT Offset, // IN652UINT NumSamplers, // IN653__in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN654{655LOG_ENTRYPOINT();656657SetSamplers(PIPE_SHADER_VERTEX, hDevice, Offset, NumSamplers, phSamplers);658659}660661662/*663* ----------------------------------------------------------------------664*665* CreateGeometryShader --666*667* The CreateGeometryShader function creates a geometry shader.668*669* ----------------------------------------------------------------------670*/671672void APIENTRY673CreateGeometryShader(D3D10DDI_HDEVICE hDevice, // IN674__in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN675D3D10DDI_HSHADER hShader, // IN676D3D10DDI_HRTSHADER hRTShader, // IN677__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN678{679LOG_ENTRYPOINT();680681struct pipe_context *pipe = CastPipeContext(hDevice);682Shader *pShader = CastShader(hShader);683684pShader->type = PIPE_SHADER_GEOMETRY;685pShader->output_resolved = TRUE;686687memset(&pShader->state, 0, sizeof pShader->state);688pShader->state.tokens = Shader_tgsi_translate(pShaderCode, pShader->output_mapping);689690pShader->handle = pipe->create_gs_state(pipe, &pShader->state);691}692693694/*695* ----------------------------------------------------------------------696*697* GsSetShader --698*699* The GsSetShader function sets the geometry shader code so that700* all of the subsequent drawing operations use that code.701*702* ----------------------------------------------------------------------703*/704705void APIENTRY706GsSetShader(D3D10DDI_HDEVICE hDevice, // IN707D3D10DDI_HSHADER hShader) // IN708{709LOG_ENTRYPOINT();710711Device *pDevice = CastDevice(hDevice);712struct pipe_context *pipe = CastPipeContext(hDevice);713void *state = CastPipeShader(hShader);714Shader *pShader = CastShader(hShader);715716assert(pipe->bind_gs_state);717718if (pShader && !pShader->state.tokens) {719pDevice->bound_empty_gs = pShader;720} else {721pDevice->bound_empty_gs = NULL;722pipe->bind_gs_state(pipe, state);723}724}725726727/*728* ----------------------------------------------------------------------729*730* GsSetShaderResources --731*732* The GsSetShaderResources function sets resources for a733* geometry shader.734*735* ----------------------------------------------------------------------736*/737738void APIENTRY739GsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN740UINT Offset, // IN741UINT NumViews, // IN742__in_ecount (NumViews)743const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN744{745LOG_ENTRYPOINT();746747SetShaderResources(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumViews, phShaderResourceViews);748}749750751/*752* ----------------------------------------------------------------------753*754* GsSetConstantBuffers --755*756* The GsSetConstantBuffers function sets constant buffers for757* a geometry shader.758*759* ----------------------------------------------------------------------760*/761762void APIENTRY763GsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN764UINT StartBuffer, // IN765UINT NumBuffers, // IN766__in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN767{768LOG_ENTRYPOINT();769770SetConstantBuffers(PIPE_SHADER_GEOMETRY,771hDevice, StartBuffer, NumBuffers, phBuffers);772}773774775/*776* ----------------------------------------------------------------------777*778* GsSetSamplers --779*780* The GsSetSamplers function sets samplers for a geometry shader.781*782* ----------------------------------------------------------------------783*/784785void APIENTRY786GsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN787UINT Offset, // IN788UINT NumSamplers, // IN789__in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN790{791LOG_ENTRYPOINT();792793SetSamplers(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumSamplers, phSamplers);794}795796797/*798* ----------------------------------------------------------------------799*800* CalcPrivateGeometryShaderWithStreamOutput --801*802* The CalcPrivateGeometryShaderWithStreamOutput function determines803* the size of the user-mode display driver's private region of memory804* (that is, the size of internal driver structures, not the size of805* the resource video memory) for a geometry shader with stream output.806*807* ----------------------------------------------------------------------808*/809810SIZE_T APIENTRY811CalcPrivateGeometryShaderWithStreamOutput(812D3D10DDI_HDEVICE hDevice, // IN813__in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pCreateGeometryShaderWithStreamOutput, // IN814__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN815{816LOG_ENTRYPOINT();817return sizeof(Shader);818}819820821/*822* ----------------------------------------------------------------------823*824* CreateGeometryShaderWithStreamOutput --825*826* The CreateGeometryShaderWithStreamOutput function creates a827* geometry shader with stream output.828*829* ----------------------------------------------------------------------830*/831832void APIENTRY833CreateGeometryShaderWithStreamOutput(834D3D10DDI_HDEVICE hDevice, // IN835__in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pData, // IN836D3D10DDI_HSHADER hShader, // IN837D3D10DDI_HRTSHADER hRTShader, // IN838__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN839{840LOG_ENTRYPOINT();841842struct pipe_context *pipe = CastPipeContext(hDevice);843Shader *pShader = CastShader(hShader);844int total_components[PIPE_MAX_SO_BUFFERS] = {0};845unsigned num_holes = 0;846boolean all_slot_zero = TRUE;847848pShader->type = PIPE_SHADER_GEOMETRY;849850memset(&pShader->state, 0, sizeof pShader->state);851if (pData->pShaderCode) {852pShader->state.tokens = Shader_tgsi_translate(pData->pShaderCode,853pShader->output_mapping);854}855pShader->output_resolved = (pShader->state.tokens != NULL);856857for (unsigned i = 0; i < pData->NumEntries; ++i) {858CONST D3D10DDIARG_STREAM_OUTPUT_DECLARATION_ENTRY* pOutputStreamDecl =859&pData->pOutputStreamDecl[i];860BYTE RegisterMask = pOutputStreamDecl->RegisterMask;861unsigned start_component = 0;862unsigned num_components = 0;863if (RegisterMask) {864while ((RegisterMask & 1) == 0) {865++start_component;866RegisterMask >>= 1;867}868while (RegisterMask) {869++num_components;870RegisterMask >>= 1;871}872assert(start_component < 4);873assert(1 <= num_components && num_components <= 4);874LOG_UNSUPPORTED(((1 << num_components) - 1) << start_component !=875pOutputStreamDecl->RegisterMask);876}877878if (pOutputStreamDecl->RegisterIndex == 0xffffffff) {879++num_holes;880} else {881unsigned idx = i - num_holes;882pShader->state.stream_output.output[idx].start_component =883start_component;884pShader->state.stream_output.output[idx].num_components =885num_components;886pShader->state.stream_output.output[idx].output_buffer =887pOutputStreamDecl->OutputSlot;888pShader->state.stream_output.output[idx].register_index =889ShaderFindOutputMapping(pShader, pOutputStreamDecl->RegisterIndex);890pShader->state.stream_output.output[idx].dst_offset =891total_components[pOutputStreamDecl->OutputSlot];892if (pOutputStreamDecl->OutputSlot != 0)893all_slot_zero = FALSE;894}895total_components[pOutputStreamDecl->OutputSlot] += num_components;896}897pShader->state.stream_output.num_outputs = pData->NumEntries - num_holes;898for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; ++i) {899/* stream_output.stride[i] is in dwords */900if (all_slot_zero) {901pShader->state.stream_output.stride[i] =902pData->StreamOutputStrideInBytes / sizeof(float);903} else {904pShader->state.stream_output.stride[i] = total_components[i];905}906}907908pShader->handle = pipe->create_gs_state(pipe, &pShader->state);909}910911912/*913* ----------------------------------------------------------------------914*915* SoSetTargets --916*917* The SoSetTargets function sets stream output target resources.918*919* ----------------------------------------------------------------------920*/921922void APIENTRY923SoSetTargets(D3D10DDI_HDEVICE hDevice, // IN924UINT SOTargets, // IN925UINT ClearTargets, // IN926__in_ecount (SOTargets) const D3D10DDI_HRESOURCE *phResource, // IN927__in_ecount (SOTargets) const UINT *pOffsets) // IN928{929unsigned i;930931LOG_ENTRYPOINT();932933Device *pDevice = CastDevice(hDevice);934struct pipe_context *pipe = pDevice->pipe;935936assert(SOTargets + ClearTargets <= PIPE_MAX_SO_BUFFERS);937938for (i = 0; i < SOTargets; ++i) {939Resource *resource = CastResource(phResource[i]);940struct pipe_resource *buffer = CastPipeResource(phResource[i]);941struct pipe_stream_output_target *so_target =942resource ? resource->so_target : NULL;943944if (buffer) {945unsigned buffer_size = buffer->width0;946947if (!so_target ||948so_target->buffer != buffer ||949so_target->buffer_size != buffer_size) {950if (so_target) {951pipe_so_target_reference(&so_target, NULL);952}953so_target = pipe->create_stream_output_target(pipe, buffer,9540,/*buffer offset*/955buffer_size);956resource->so_target = so_target;957}958}959pDevice->so_targets[i] = so_target;960}961962for (i = 0; i < ClearTargets; ++i) {963pDevice->so_targets[SOTargets + i] = NULL;964}965966if (!pipe->set_stream_output_targets) {967LOG_UNSUPPORTED(pipe->set_stream_output_targets);968return;969}970971pipe->set_stream_output_targets(pipe, SOTargets, pDevice->so_targets,972pOffsets);973}974975976/*977* ----------------------------------------------------------------------978*979* CreatePixelShader --980*981* The CreatePixelShader function converts pixel shader code into a982* hardware-specific format and associates this code with a983* shader handle.984*985* ----------------------------------------------------------------------986*/987988void APIENTRY989CreatePixelShader(D3D10DDI_HDEVICE hDevice, // IN990__in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN991D3D10DDI_HSHADER hShader, // IN992D3D10DDI_HRTSHADER hRTShader, // IN993__in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN994{995LOG_ENTRYPOINT();996997struct pipe_context *pipe = CastPipeContext(hDevice);998Shader *pShader = CastShader(hShader);9991000pShader->type = PIPE_SHADER_FRAGMENT;1001pShader->output_resolved = TRUE;10021003memset(&pShader->state, 0, sizeof pShader->state);1004pShader->state.tokens = Shader_tgsi_translate(pShaderCode,1005pShader->output_mapping);10061007pShader->handle = pipe->create_fs_state(pipe, &pShader->state);10081009}101010111012/*1013* ----------------------------------------------------------------------1014*1015* PsSetShader --1016*1017* The PsSetShader function sets a pixel shader to be used1018* in all drawing operations.1019*1020* ----------------------------------------------------------------------1021*/10221023void APIENTRY1024PsSetShader(D3D10DDI_HDEVICE hDevice, // IN1025D3D10DDI_HSHADER hShader) // IN1026{1027LOG_ENTRYPOINT();10281029Device *pDevice = CastDevice(hDevice);1030struct pipe_context *pipe = pDevice->pipe;1031void *state = CastPipeShader(hShader);10321033if (!state) {1034state = pDevice->empty_fs;1035}10361037pipe->bind_fs_state(pipe, state);1038}103910401041/*1042* ----------------------------------------------------------------------1043*1044* PsSetShaderResources --1045*1046* The PsSetShaderResources function sets resources for a pixel shader.1047*1048* ----------------------------------------------------------------------1049*/10501051void APIENTRY1052PsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN1053UINT Offset, // IN1054UINT NumViews, // IN1055__in_ecount (NumViews)1056const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN1057{1058LOG_ENTRYPOINT();10591060SetShaderResources(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumViews, phShaderResourceViews);1061}106210631064/*1065* ----------------------------------------------------------------------1066*1067* PsSetConstantBuffers --1068*1069* The PsSetConstantBuffers function sets constant buffers for1070* a pixel shader.1071*1072* ----------------------------------------------------------------------1073*/10741075void APIENTRY1076PsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN1077UINT StartBuffer, // IN1078UINT NumBuffers, // IN1079__in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN1080{1081LOG_ENTRYPOINT();10821083SetConstantBuffers(PIPE_SHADER_FRAGMENT,1084hDevice, StartBuffer, NumBuffers, phBuffers);1085}10861087/*1088* ----------------------------------------------------------------------1089*1090* PsSetSamplers --1091*1092* The PsSetSamplers function sets samplers for a pixel shader.1093*1094* ----------------------------------------------------------------------1095*/10961097void APIENTRY1098PsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN1099UINT Offset, // IN1100UINT NumSamplers, // IN1101__in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN1102{1103LOG_ENTRYPOINT();11041105SetSamplers(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumSamplers, phSamplers);1106}110711081109/*1110* ----------------------------------------------------------------------1111*1112* ShaderResourceViewReadAfterWriteHazard --1113*1114* The ShaderResourceViewReadAfterWriteHazard function informs1115* the usermode display driver that the specified resource was1116* used as an output from the graphics processing unit (GPU)1117* and that the resource will be used as an input to the GPU.1118* A shader resource view is also provided to indicate which1119* view caused the hazard.1120*1121* ----------------------------------------------------------------------1122*/11231124void APIENTRY1125ShaderResourceViewReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, // IN1126D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN1127D3D10DDI_HRESOURCE hResource) // IN1128{1129LOG_ENTRYPOINT();11301131/* Not actually necessary */1132}113311341135/*1136* ----------------------------------------------------------------------1137*1138* CalcPrivateShaderResourceViewSize --1139*1140* The CalcPrivateShaderResourceViewSize function determines the size1141* of the usermode display driver's private region of memory1142* (that is, the size of internal driver structures, not the size of1143* the resource video memory) for a shader resource view.1144*1145* ----------------------------------------------------------------------1146*/11471148SIZE_T APIENTRY1149CalcPrivateShaderResourceViewSize(1150D3D10DDI_HDEVICE hDevice, // IN1151__in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView) // IN1152{1153return sizeof(ShaderResourceView);1154}115511561157/*1158* ----------------------------------------------------------------------1159*1160* CalcPrivateShaderResourceViewSize --1161*1162* The CalcPrivateShaderResourceViewSize function determines the size1163* of the usermode display driver's private region of memory1164* (that is, the size of internal driver structures, not the size of1165* the resource video memory) for a shader resource view.1166*1167* ----------------------------------------------------------------------1168*/11691170SIZE_T APIENTRY1171CalcPrivateShaderResourceViewSize1(1172D3D10DDI_HDEVICE hDevice, // IN1173__in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView) // IN1174{1175return sizeof(ShaderResourceView);1176}117711781179/*1180* ----------------------------------------------------------------------1181*1182* CreateShaderResourceView --1183*1184* The CreateShaderResourceView function creates a shader1185* resource view.1186*1187* ----------------------------------------------------------------------1188*/11891190void APIENTRY1191CreateShaderResourceView(1192D3D10DDI_HDEVICE hDevice, // IN1193__in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView, // IN1194D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN1195D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView) // IN1196{1197LOG_ENTRYPOINT();11981199struct pipe_context *pipe = CastPipeContext(hDevice);1200ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);1201struct pipe_resource *resource;1202enum pipe_format format;12031204struct pipe_sampler_view desc;1205memset(&desc, 0, sizeof desc);1206resource = CastPipeResource(pCreateSRView->hDrvResource);1207format = FormatTranslate(pCreateSRView->Format, FALSE);12081209u_sampler_view_default_template(&desc,1210resource,1211format);12121213switch (pCreateSRView->ResourceDimension) {1214case D3D10DDIRESOURCE_BUFFER: {1215const struct util_format_description *fdesc = util_format_description(format);1216desc.u.buf.offset = pCreateSRView->Buffer.FirstElement *1217(fdesc->block.bits / 8) * fdesc->block.width;1218desc.u.buf.size = pCreateSRView->Buffer.NumElements *1219(fdesc->block.bits / 8) * fdesc->block.width;1220}1221break;1222case D3D10DDIRESOURCE_TEXTURE1D:1223desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip;1224desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level;1225desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice;1226desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer;1227assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1);1228assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1);1229break;1230case D3D10DDIRESOURCE_TEXTURE2D:1231desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip;1232desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level;1233desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice;1234desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer;1235assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1);1236assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1);1237break;1238case D3D10DDIRESOURCE_TEXTURE3D:1239desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip;1240desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level;1241/* layer info filled in by default_template */1242assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1);1243break;1244case D3D10DDIRESOURCE_TEXTURECUBE:1245desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip;1246desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level;1247/* layer info filled in by default_template */1248assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1);1249break;1250default:1251assert(0);1252return;1253}12541255pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc);1256}125712581259/*1260* ----------------------------------------------------------------------1261*1262* CreateShaderResourceView1 --1263*1264* The CreateShaderResourceView function creates a shader1265* resource view.1266*1267* ----------------------------------------------------------------------1268*/12691270void APIENTRY1271CreateShaderResourceView1(1272D3D10DDI_HDEVICE hDevice, // IN1273__in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView, // IN1274D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN1275D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView) // IN1276{1277LOG_ENTRYPOINT();12781279struct pipe_context *pipe = CastPipeContext(hDevice);1280ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);1281struct pipe_resource *resource;1282enum pipe_format format;12831284struct pipe_sampler_view desc;1285memset(&desc, 0, sizeof desc);1286resource = CastPipeResource(pCreateSRView->hDrvResource);1287format = FormatTranslate(pCreateSRView->Format, FALSE);12881289u_sampler_view_default_template(&desc,1290resource,1291format);12921293switch (pCreateSRView->ResourceDimension) {1294case D3D10DDIRESOURCE_BUFFER: {1295const struct util_format_description *fdesc = util_format_description(format);1296desc.u.buf.offset = pCreateSRView->Buffer.FirstElement *1297(fdesc->block.bits / 8) * fdesc->block.width;1298desc.u.buf.size = pCreateSRView->Buffer.NumElements *1299(fdesc->block.bits / 8) * fdesc->block.width;1300}1301break;1302case D3D10DDIRESOURCE_TEXTURE1D:1303desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip;1304desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level;1305desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice;1306desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer;1307assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1);1308assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1);1309break;1310case D3D10DDIRESOURCE_TEXTURE2D:1311desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip;1312desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level;1313desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice;1314desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer;1315assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1);1316assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1);1317break;1318case D3D10DDIRESOURCE_TEXTURE3D:1319desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip;1320desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level;1321/* layer info filled in by default_template */1322assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1);1323break;1324case D3D10DDIRESOURCE_TEXTURECUBE:1325desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip;1326desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level;1327desc.u.tex.first_layer = pCreateSRView->TexCube.First2DArrayFace;1328desc.u.tex.last_layer = 6*pCreateSRView->TexCube.NumCubes - 1 +1329pCreateSRView->TexCube.First2DArrayFace;1330assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1);1331break;1332default:1333assert(0);1334return;1335}13361337pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc);1338}133913401341/*1342* ----------------------------------------------------------------------1343*1344* DestroyShaderResourceView --1345*1346* The DestroyShaderResourceView function destroys the specified1347* shader resource view object. The shader resource view object1348* can be destoyed only if it is not currently bound to a1349* display device.1350*1351* ----------------------------------------------------------------------1352*/13531354void APIENTRY1355DestroyShaderResourceView(D3D10DDI_HDEVICE hDevice, // IN1356D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) // IN1357{1358LOG_ENTRYPOINT();13591360ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);13611362pipe_sampler_view_reference(&pSRView->handle, NULL);1363}136413651366/*1367* ----------------------------------------------------------------------1368*1369* GenMips --1370*1371* The GenMips function generates the lower MIP-map levels1372* on the specified shader-resource view.1373*1374* ----------------------------------------------------------------------1375*/13761377void APIENTRY1378GenMips(D3D10DDI_HDEVICE hDevice, // IN1379D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) // IN1380{1381LOG_ENTRYPOINT();13821383Device *pDevice = CastDevice(hDevice);1384if (!CheckPredicate(pDevice)) {1385return;1386}13871388struct pipe_context *pipe = pDevice->pipe;1389struct pipe_sampler_view *sampler_view = CastPipeShaderResourceView(hShaderResourceView);13901391util_gen_mipmap(pipe,1392sampler_view->texture,1393sampler_view->format,1394sampler_view->u.tex.first_level,1395sampler_view->u.tex.last_level,1396sampler_view->u.tex.first_layer,1397sampler_view->u.tex.last_layer,1398PIPE_TEX_FILTER_LINEAR);1399}140014011402unsigned1403ShaderFindOutputMapping(Shader *shader, unsigned registerIndex)1404{1405if (!shader || !shader->state.tokens)1406return registerIndex;14071408for (unsigned i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) {1409if (shader->output_mapping[i] == registerIndex)1410return i;1411}1412return registerIndex;1413}141414151416